mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
More int->size_t and string overflow fixes
This commit is contained in:
parent
d858b4c77f
commit
669763d88a
10 changed files with 53 additions and 44 deletions
|
@ -278,6 +278,19 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A bit more generic version of the same */
|
||||||
|
static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, size_t offset, const char *message)
|
||||||
|
{
|
||||||
|
int overflow;
|
||||||
|
size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
|
||||||
|
|
||||||
|
if (UNEXPECTED(overflow)) {
|
||||||
|
zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* ZEND_MULTIPLY_H */
|
#endif /* ZEND_MULTIPLY_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2677,6 +2677,14 @@ zend_strtod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dig_done:
|
dig_done:
|
||||||
|
if (nd < 0) {
|
||||||
|
/* overflow */
|
||||||
|
nd = DBL_DIG + 2;
|
||||||
|
}
|
||||||
|
if (nf < 0) {
|
||||||
|
/* overflow */
|
||||||
|
nf = DBL_DIG + 2;
|
||||||
|
}
|
||||||
e = 0;
|
e = 0;
|
||||||
if (c == 'e' || c == 'E') {
|
if (c == 'e' || c == 'E') {
|
||||||
if (!nd && !nz && !nz0) {
|
if (!nd && !nz && !nz0) {
|
||||||
|
@ -4543,7 +4551,7 @@ static void destroy_freelist(void)
|
||||||
}
|
}
|
||||||
freelist[i] = NULL;
|
freelist[i] = NULL;
|
||||||
}
|
}
|
||||||
FREE_DTOA_LOCK(0)
|
FREE_DTOA_LOCK(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -588,8 +588,8 @@ static PHP_FUNCTION(bzdecompress)
|
||||||
bzs.avail_in = source_len;
|
bzs.avail_in = source_len;
|
||||||
|
|
||||||
/* in most cases bz2 offers at least 2:1 compression, so we use that as our base */
|
/* in most cases bz2 offers at least 2:1 compression, so we use that as our base */
|
||||||
|
dest = zend_string_safe_alloc(source_len, 2, 1, 0);
|
||||||
bzs.avail_out = source_len * 2;
|
bzs.avail_out = source_len * 2;
|
||||||
dest = zend_string_alloc(bzs.avail_out + 1, 0);
|
|
||||||
bzs.next_out = ZSTR_VAL(dest);
|
bzs.next_out = ZSTR_VAL(dest);
|
||||||
|
|
||||||
while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) {
|
while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) {
|
||||||
|
|
|
@ -1537,7 +1537,7 @@ PHP_FUNCTION(pg_connect_poll)
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pgsql_link) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pgsql_link) == FAILURE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pgsql = (PGconn *)zend_fetch_resource2(Z_RES_P(pgsql_link), "PostgreSQL link", le_link, le_plink)) == NULL) {
|
if ((pgsql = (PGconn *)zend_fetch_resource2(Z_RES_P(pgsql_link), "PostgreSQL link", le_link, le_plink)) == NULL) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -4356,7 +4356,7 @@ PHP_FUNCTION(pg_escape_string)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
to = zend_string_alloc(ZSTR_LEN(from) * 2, 0);
|
to = zend_string_safe_alloc(ZSTR_LEN(from), 2, 0, 0);
|
||||||
#ifdef HAVE_PQESCAPE_CONN
|
#ifdef HAVE_PQESCAPE_CONN
|
||||||
if (link) {
|
if (link) {
|
||||||
if ((pgsql = (PGconn *)zend_fetch_resource2(link, "PostgreSQL link", le_link, le_plink)) == NULL) {
|
if ((pgsql = (PGconn *)zend_fetch_resource2(link, "PostgreSQL link", le_link, le_plink)) == NULL) {
|
||||||
|
@ -4408,7 +4408,7 @@ PHP_FUNCTION(pg_escape_bytea)
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
to = (char *)PQescapeByteaConn(pgsql, (unsigned char *)from, (size_t)from_len, &to_len);
|
to = (char *)PQescapeByteaConn(pgsql, (unsigned char *)from, (size_t)from_len, &to_len);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
to = (char *)PQescapeBytea((unsigned char*)from, from_len, &to_len);
|
to = (char *)PQescapeBytea((unsigned char*)from, from_len, &to_len);
|
||||||
|
|
||||||
|
|
|
@ -199,7 +199,7 @@ static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *in
|
||||||
if (intern->file_name) {
|
if (intern->file_name) {
|
||||||
efree(intern->file_name);
|
efree(intern->file_name);
|
||||||
}
|
}
|
||||||
intern->file_name_len = (int)spprintf(&intern->file_name, 0, "%s%c%s",
|
intern->file_name_len = spprintf(&intern->file_name, 0, "%s%c%s",
|
||||||
spl_filesystem_object_get_path(intern, NULL),
|
spl_filesystem_object_get_path(intern, NULL),
|
||||||
slash, intern->u.dir.entry.d_name);
|
slash, intern->u.dir.entry.d_name);
|
||||||
break;
|
break;
|
||||||
|
@ -232,7 +232,7 @@ static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path)
|
||||||
int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
|
int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
|
||||||
|
|
||||||
intern->type = SPL_FS_DIR;
|
intern->type = SPL_FS_DIR;
|
||||||
intern->_path_len = (int)strlen(path);
|
intern->_path_len = strlen(path);
|
||||||
intern->u.dir.dirp = php_stream_opendir(path, REPORT_ERRORS, FG(default_context));
|
intern->u.dir.dirp = php_stream_opendir(path, REPORT_ERRORS, FG(default_context));
|
||||||
|
|
||||||
if (intern->_path_len > 1 && IS_SLASH_AT(path, intern->_path_len-1)) {
|
if (intern->_path_len > 1 && IS_SLASH_AT(path, intern->_path_len-1)) {
|
||||||
|
@ -383,7 +383,7 @@ void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
intern->file_name = use_copy ? estrndup(path, len) : path;
|
intern->file_name = use_copy ? estrndup(path, len) : path;
|
||||||
intern->file_name_len = (int)len;
|
intern->file_name_len = len;
|
||||||
|
|
||||||
while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
|
while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
|
||||||
intern->file_name[intern->file_name_len-1] = 0;
|
intern->file_name[intern->file_name_len-1] = 0;
|
||||||
|
@ -397,7 +397,7 @@ void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path,
|
||||||
p2 = 0;
|
p2 = 0;
|
||||||
#endif
|
#endif
|
||||||
if (p1 || p2) {
|
if (p1 || p2) {
|
||||||
intern->_path_len = (int)((p1 > p2 ? p1 : p2) - intern->file_name);
|
intern->_path_len = ((p1 > p2 ? p1 : p2) - intern->file_name);
|
||||||
} else {
|
} else {
|
||||||
intern->_path_len = 0;
|
intern->_path_len = 0;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path,
|
||||||
intern->_path = estrndup(path, intern->_path_len);
|
intern->_path = estrndup(path, intern->_path_len);
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
|
||||||
static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, int file_path_len, int use_copy, zend_class_entry *ce, zval *return_value) /* {{{ */
|
static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, size_t file_path_len, int use_copy, zend_class_entry *ce, zval *return_value) /* {{{ */
|
||||||
{
|
{
|
||||||
spl_filesystem_object *intern;
|
spl_filesystem_object *intern;
|
||||||
zval arg1;
|
zval arg1;
|
||||||
|
@ -916,7 +916,7 @@ SPL_METHOD(SplFileInfo, getExtension)
|
||||||
const char *p;
|
const char *p;
|
||||||
size_t flen;
|
size_t flen;
|
||||||
size_t path_len;
|
size_t path_len;
|
||||||
int idx;
|
size_t idx;
|
||||||
zend_string *ret;
|
zend_string *ret;
|
||||||
|
|
||||||
if (zend_parse_parameters_none() == FAILURE) {
|
if (zend_parse_parameters_none() == FAILURE) {
|
||||||
|
@ -937,7 +937,7 @@ SPL_METHOD(SplFileInfo, getExtension)
|
||||||
|
|
||||||
p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
|
p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
|
||||||
if (p) {
|
if (p) {
|
||||||
idx = (int)(p - ZSTR_VAL(ret));
|
idx = p - ZSTR_VAL(ret);
|
||||||
RETVAL_STRINGL(ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
|
RETVAL_STRINGL(ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
|
||||||
zend_string_release(ret);
|
zend_string_release(ret);
|
||||||
return;
|
return;
|
||||||
|
@ -954,7 +954,7 @@ SPL_METHOD(DirectoryIterator, getExtension)
|
||||||
{
|
{
|
||||||
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
|
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
|
||||||
const char *p;
|
const char *p;
|
||||||
int idx;
|
size_t idx;
|
||||||
zend_string *fname;
|
zend_string *fname;
|
||||||
|
|
||||||
if (zend_parse_parameters_none() == FAILURE) {
|
if (zend_parse_parameters_none() == FAILURE) {
|
||||||
|
@ -965,7 +965,7 @@ SPL_METHOD(DirectoryIterator, getExtension)
|
||||||
|
|
||||||
p = zend_memrchr(ZSTR_VAL(fname), '.', ZSTR_LEN(fname));
|
p = zend_memrchr(ZSTR_VAL(fname), '.', ZSTR_LEN(fname));
|
||||||
if (p) {
|
if (p) {
|
||||||
idx = (int)(p - ZSTR_VAL(fname));
|
idx = p - ZSTR_VAL(fname);
|
||||||
RETVAL_STRINGL(ZSTR_VAL(fname) + idx + 1, ZSTR_LEN(fname) - idx - 1);
|
RETVAL_STRINGL(ZSTR_VAL(fname) + idx + 1, ZSTR_LEN(fname) - idx - 1);
|
||||||
zend_string_release(fname);
|
zend_string_release(fname);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1383,7 +1383,7 @@ SPL_METHOD(SplFileInfo, getPathInfo)
|
||||||
if (path) {
|
if (path) {
|
||||||
char *dpath = estrndup(path, path_len);
|
char *dpath = estrndup(path, path_len);
|
||||||
path_len = php_dirname(dpath, path_len);
|
path_len = php_dirname(dpath, path_len);
|
||||||
spl_filesystem_object_create_info(intern, dpath, (int)path_len, 1, ce, return_value);
|
spl_filesystem_object_create_info(intern, dpath, path_len, 1, ce, return_value);
|
||||||
efree(dpath);
|
efree(dpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1507,9 +1507,9 @@ SPL_METHOD(RecursiveDirectoryIterator, getChildren)
|
||||||
subdir = Z_SPLFILESYSTEM_P(return_value);
|
subdir = Z_SPLFILESYSTEM_P(return_value);
|
||||||
if (subdir) {
|
if (subdir) {
|
||||||
if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) {
|
if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) {
|
||||||
subdir->u.dir.sub_path_len = (int)spprintf(&subdir->u.dir.sub_path, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name);
|
subdir->u.dir.sub_path_len = spprintf(&subdir->u.dir.sub_path, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name);
|
||||||
} else {
|
} else {
|
||||||
subdir->u.dir.sub_path_len = (int)strlen(intern->u.dir.entry.d_name);
|
subdir->u.dir.sub_path_len = strlen(intern->u.dir.entry.d_name);
|
||||||
subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len);
|
subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len);
|
||||||
}
|
}
|
||||||
subdir->info_class = intern->info_class;
|
subdir->info_class = intern->info_class;
|
||||||
|
@ -2293,7 +2293,7 @@ SPL_METHOD(SplFileObject, __construct)
|
||||||
p2 = 0;
|
p2 = 0;
|
||||||
#endif
|
#endif
|
||||||
if (p1 || p2) {
|
if (p1 || p2) {
|
||||||
intern->_path_len = (int)((p1 > p2 ? p1 : p2) - tmp_path);
|
intern->_path_len = ((p1 > p2 ? p1 : p2) - tmp_path);
|
||||||
} else {
|
} else {
|
||||||
intern->_path_len = 0;
|
intern->_path_len = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1269,11 +1269,7 @@ PHPAPI zend_string *php_escape_html_entities_ex(unsigned char *old, size_t oldle
|
||||||
if (oldlen < 64) {
|
if (oldlen < 64) {
|
||||||
maxlen = 128;
|
maxlen = 128;
|
||||||
} else {
|
} else {
|
||||||
maxlen = 2 * oldlen;
|
maxlen = zend_safe_addmult(oldlen, 2, 0, "html_entities");
|
||||||
if (maxlen < oldlen) {
|
|
||||||
zend_error_noreturn(E_ERROR, "Input string is too long");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced = zend_string_alloc(maxlen, 0);
|
replaced = zend_string_alloc(maxlen, 0);
|
||||||
|
|
|
@ -1151,19 +1151,15 @@ PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, char *dec_poin
|
||||||
|
|
||||||
/* calculate the length of the return buffer */
|
/* calculate the length of the return buffer */
|
||||||
if (dp) {
|
if (dp) {
|
||||||
integral = (int)(dp - ZSTR_VAL(tmpbuf));
|
integral = (dp - ZSTR_VAL(tmpbuf));
|
||||||
} else {
|
} else {
|
||||||
/* no decimal point was found */
|
/* no decimal point was found */
|
||||||
integral = (int)ZSTR_LEN(tmpbuf);
|
integral = ZSTR_LEN(tmpbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allow for thousand separators */
|
/* allow for thousand separators */
|
||||||
if (thousand_sep) {
|
if (thousand_sep) {
|
||||||
if (integral + thousand_sep_len * ((integral-1) / 3) < integral) {
|
integral = zend_safe_addmult((integral-1)/3, thousand_sep_len, integral, "number formatting");
|
||||||
/* overflow */
|
|
||||||
php_error_docref(NULL, E_ERROR, "String overflow");
|
|
||||||
}
|
|
||||||
integral += thousand_sep_len * ((integral-1) / 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reslen = integral;
|
reslen = integral;
|
||||||
|
@ -1172,11 +1168,7 @@ PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, char *dec_poin
|
||||||
reslen += dec;
|
reslen += dec;
|
||||||
|
|
||||||
if (dec_point) {
|
if (dec_point) {
|
||||||
if (reslen + dec_point_len < dec_point_len) {
|
reslen = zend_safe_addmult(reslen, 1, dec_point_len, "number formatting");
|
||||||
/* overflow */
|
|
||||||
php_error_docref(NULL, E_ERROR, "String overflow");
|
|
||||||
}
|
|
||||||
reslen += dec_point_len;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1194,8 +1186,8 @@ PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, char *dec_poin
|
||||||
* Take care, as the sprintf implementation may return less places than
|
* Take care, as the sprintf implementation may return less places than
|
||||||
* we requested due to internal buffer limitations */
|
* we requested due to internal buffer limitations */
|
||||||
if (dec) {
|
if (dec) {
|
||||||
int declen = (int)(dp ? s - dp : 0);
|
size_t declen = (dp ? s - dp : 0);
|
||||||
int topad = dec > declen ? dec - declen : 0;
|
size_t topad = dec > declen ? dec - declen : 0;
|
||||||
|
|
||||||
/* pad with '0's */
|
/* pad with '0's */
|
||||||
while (topad--) {
|
while (topad--) {
|
||||||
|
|
|
@ -268,7 +268,7 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
|
||||||
zval obj, zfilter;
|
zval obj, zfilter;
|
||||||
zval func_name;
|
zval func_name;
|
||||||
zval retval;
|
zval retval;
|
||||||
int len;
|
size_t len;
|
||||||
|
|
||||||
/* some sanity checks */
|
/* some sanity checks */
|
||||||
if (persistent) {
|
if (persistent) {
|
||||||
|
@ -277,7 +277,7 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = (int)strlen(filtername);
|
len = strlen(filtername);
|
||||||
|
|
||||||
/* determine the classname/class entry */
|
/* determine the classname/class entry */
|
||||||
if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), (char*)filtername, len))) {
|
if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), (char*)filtername, len))) {
|
||||||
|
@ -289,7 +289,7 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
|
||||||
TODO: Allow failed userfilter creations to continue
|
TODO: Allow failed userfilter creations to continue
|
||||||
scanning through the list */
|
scanning through the list */
|
||||||
if ((period = strrchr(filtername, '.'))) {
|
if ((period = strrchr(filtername, '.'))) {
|
||||||
char *wildcard = emalloc(len + 3);
|
char *wildcard = safe_emalloc(len, 1, 3);
|
||||||
|
|
||||||
/* Search for wildcard matches instead */
|
/* Search for wildcard matches instead */
|
||||||
memcpy(wildcard, filtername, len + 1); /* copy \0 */
|
memcpy(wildcard, filtername, len + 1); /* copy \0 */
|
||||||
|
@ -452,7 +452,7 @@ static void php_stream_bucket_attach(int append, INTERNAL_FUNCTION_PARAMETERS)
|
||||||
if (!bucket->own_buf) {
|
if (!bucket->own_buf) {
|
||||||
bucket = php_stream_bucket_make_writeable(bucket);
|
bucket = php_stream_bucket_make_writeable(bucket);
|
||||||
}
|
}
|
||||||
if ((int)bucket->buflen != Z_STRLEN_P(pzdata)) {
|
if (bucket->buflen != Z_STRLEN_P(pzdata)) {
|
||||||
bucket->buf = perealloc(bucket->buf, Z_STRLEN_P(pzdata), bucket->is_persistent);
|
bucket->buf = perealloc(bucket->buf, Z_STRLEN_P(pzdata), bucket->is_persistent);
|
||||||
bucket->buflen = Z_STRLEN_P(pzdata);
|
bucket->buflen = Z_STRLEN_P(pzdata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,7 @@ void simplestring_addn(simplestring* target, const char* source, size_t add_len)
|
||||||
simplestring_init_str(target);
|
simplestring_init_str(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((INT_MAX - add_len) < target->len || (INT_MAX - add_len - 1) < target->len) {
|
if((SIZE_MAX - add_len) < target->len || (SIZE_MAX - add_len - 1) < target->len) {
|
||||||
/* check for overflows, if there's a potential overflow do nothing */
|
/* check for overflows, if there's a potential overflow do nothing */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,8 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
typedef struct _simplestring {
|
typedef struct _simplestring {
|
||||||
char* str; /* string buf */
|
char* str; /* string buf */
|
||||||
int len; /* length of string/buf */
|
size_t len; /* length of string/buf */
|
||||||
int size; /* size of allocated buffer */
|
size_t size; /* size of allocated buffer */
|
||||||
} simplestring;
|
} simplestring;
|
||||||
/******/
|
/******/
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue