diff options
author | Stanislav Malyshev <stas@php.net> | 2016-06-21 00:01:48 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2016-06-21 00:01:48 -0700 |
commit | 7dde353ee79fcee73873cc19e1124704b94bd366 (patch) | |
tree | f0bd2c3969846a52fcb19fac8b63b18eb8121379 | |
parent | d144590d38fa321b46b8e199c754006318985c84 (diff) | |
parent | c395c6e5d7e8df37a21265ff76e48fe75ceb5ae6 (diff) | |
download | php-git-7dde353ee79fcee73873cc19e1124704b94bd366.tar.gz |
Merge branch 'PHP-5.5' into PHP-5.6.23
* PHP-5.5:
Fixed bug #72446 - Integer Overflow in gdImagePaletteToTrueColor() resulting in heap overflow
update NEWS
fix tests
fix build
Fix bug #72455: Heap Overflow due to integer overflows
Fix bug #72434: ZipArchive class Use After Free Vulnerability in PHP's GC algorithm and unserialize
Fixed ##72433: Use After Free Vulnerability in PHP's GC algorithm and unserialize
Fix bug #72407: NULL Pointer Dereference at _gdScaleVert
Fix bug #72402: _php_mb_regex_ereg_replace_exec - double free
Fix bug #72298 pass2_no_dither out-of-bounds access
Fixed #72339 Integer Overflow in _gd2GetHeader() resulting in heap overflow
Fix bug #72262 - do not overflow int
Fix bug #72400 and #72403 - prevent signed int overflows for string lengths
Fix bug #72275: don't allow smart_str to overflow int
Fix bug #72340: Double Free Courruption in wddx_deserialize
update NEWS
Fix #66387: Stack overflow with imagefilltoborder
Skip test which is 64bits only
5.5.37 now
Conflicts:
configure.in
ext/mcrypt/mcrypt.c
ext/spl/spl_directory.c
main/php_version.h
-rw-r--r-- | Zend/tests/gc_024.phpt | 2 | ||||
-rw-r--r-- | ext/gd/libgd/gd.c | 22 | ||||
-rw-r--r-- | ext/gd/libgd/gd_gd2.c | 7 | ||||
-rw-r--r-- | ext/gd/libgd/gd_interpolation.c | 3 | ||||
-rw-r--r-- | ext/gd/libgd/gd_topal.c | 14 | ||||
-rw-r--r-- | ext/gd/tests/bug72298.phpt | 15 | ||||
-rw-r--r-- | ext/gd/tests/bug72339.gd | bin | 0 -> 67108882 bytes | |||
-rw-r--r-- | ext/gd/tests/bug72339.phpt | 11 | ||||
-rw-r--r-- | ext/mbstring/php_mbregex.c | 65 | ||||
-rw-r--r-- | ext/mbstring/tests/bug72402.phpt | 17 | ||||
-rw-r--r-- | ext/mcrypt/mcrypt.c | 78 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 11 | ||||
-rw-r--r-- | ext/spl/spl_directory.c | 208 | ||||
-rw-r--r-- | ext/standard/php_smart_str.h | 17 | ||||
-rw-r--r-- | ext/standard/string.c | 25 | ||||
-rw-r--r-- | ext/standard/tests/strings/bug72433.phpt | 32 | ||||
-rw-r--r-- | ext/standard/tests/strings/bug72434.phpt | 33 | ||||
-rw-r--r-- | ext/standard/url.c | 96 | ||||
-rw-r--r-- | ext/wddx/tests/bug72340.phpt | 24 | ||||
-rw-r--r-- | ext/wddx/wddx.c | 4 | ||||
-rw-r--r-- | ext/zip/php_zip.c | 9 |
21 files changed, 450 insertions, 243 deletions
diff --git a/Zend/tests/gc_024.phpt b/Zend/tests/gc_024.phpt index 9a2ceb88f5..ca78da63d3 100644 --- a/Zend/tests/gc_024.phpt +++ b/Zend/tests/gc_024.phpt @@ -13,5 +13,5 @@ var_dump(gc_collect_cycles()); echo "ok\n"; ?> --EXPECT-- -int(1) +int(2) ok diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c index 5170f4f8c0..da0e094114 100644 --- a/ext/gd/libgd/gd.c +++ b/ext/gd/libgd/gd.c @@ -133,6 +133,10 @@ gdImagePtr gdImageCreate (int sx, int sy) return NULL; } + if (overflow2(sizeof(unsigned char *), sx)) { + return NULL; + } + im = (gdImage *) gdCalloc(1, sizeof(gdImage)); /* Row-major ever since gd 1.3 */ @@ -1098,12 +1102,12 @@ void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color) int thick = im->thick; if (color == gdAntiAliased) { - /* + /* gdAntiAliased passed as color: use the much faster, much cheaper and equally attractive gdImageAALine implementation. That clips too, so don't clip twice. */ - gdImageAALine(im, x1, y1, x2, y2, im->AA_color); + gdImageAALine(im, x1, y1, x2, y2, im->AA_color); return; } @@ -1886,7 +1890,7 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc) return; } - alphablending_bak = im->alphaBlendingFlag; + alphablending_bak = im->alphaBlendingFlag; im->alphaBlendingFlag = 0; if (nc==gdTiled){ @@ -1898,7 +1902,7 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc) wx2=im->sx;wy2=im->sy; oc = gdImageGetPixel(im, x, y); if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) { - im->alphaBlendingFlag = alphablending_bak; + im->alphaBlendingFlag = alphablending_bak; return; } @@ -1961,7 +1965,7 @@ skip: for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++); efree(stack); done: - im->alphaBlendingFlag = alphablending_bak; + im->alphaBlendingFlag = alphablending_bak; } static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) @@ -2069,7 +2073,7 @@ void gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color) x1ul = x1 - half; y1ul = y1 - half; - + x2lr = x2 + half; y2lr = y2 + half; @@ -2271,7 +2275,7 @@ void gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int s int tox, toy; int ncR, ncG, ncB; toy = dstY; - + for (y = srcY; y < (srcY + h); y++) { tox = dstX; for (x = srcX; x < (srcX + w); x++) { @@ -2368,7 +2372,7 @@ void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int int colorMap[gdMaxColors]; /* Stretch vectors */ int *stx, *sty; - + if (overflow2(sizeof(int), srcW)) { return; } @@ -2913,7 +2917,7 @@ int gdAlphaBlend (int dst, int src) { src_weight = gdAlphaTransparent - src_alpha; dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax; tot_weight = src_weight + dst_weight; - + /* -------------------------------------------------------------------- */ /* What red, green and blue result values will we use? */ /* -------------------------------------------------------------------- */ diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c index 6726fee826..e954aafa68 100644 --- a/ext/gd/libgd/gd_gd2.c +++ b/ext/gd/libgd/gd_gd2.c @@ -138,11 +138,18 @@ static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, in if (gd2_compressed(*fmt)) { nc = (*ncx) * (*ncy); GD2_DBG(php_gd_error("Reading %d chunk index entries", nc)); + if (overflow2(sizeof(t_chunk_info), nc)) { + goto fail1; + } sidx = sizeof(t_chunk_info) * nc; if (sidx <= 0) { goto fail1; } cidx = gdCalloc(sidx, 1); + if (cidx == NULL) { + goto fail1; + } + for (i = 0; i < nc; i++) { if (gdGetInt(&cidx[i].offset, in) != 1) { gdFree(cidx); diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c index 6d703b8b30..83319966f9 100644 --- a/ext/gd/libgd/gd_interpolation.c +++ b/ext/gd/libgd/gd_interpolation.c @@ -1047,6 +1047,9 @@ static inline void _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_w } contrib = _gdContributionsCalc(dst_height, src_height, (double)(dst_height) / (double)(src_height), pSrc->interpolation); + if (contrib == NULL) { + return; + } /* scale each column */ for (u = 0; u < dst_width - 1; u++) { _gdScaleCol(pSrc, src_width, pDst, dst_width, dst_height, u, contrib); diff --git a/ext/gd/libgd/gd_topal.c b/ext/gd/libgd/gd_topal.c index b9cb928648..d8dda45cb9 100644 --- a/ext/gd/libgd/gd_topal.c +++ b/ext/gd/libgd/gd_topal.c @@ -43,7 +43,7 @@ * If it is not working, it's not Thomas G. Lane's fault. */ -/* +/* SETTING THIS ONE CAUSES STRIPED IMAGE to be done: solve this #define ORIGINAL_LIB_JPEG_REVERSE_ODD_ROWS @@ -152,7 +152,7 @@ * color space, and repeatedly splits the "largest" remaining box until we * have as many boxes as desired colors. Then the mean color in each * remaining box becomes one of the possible output colors. - * + * * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires @@ -1320,16 +1320,16 @@ pass2_no_dither (j_decompress_ptr cinfo, #else r = gdTrueColorGetRed (*inptr); g = gdTrueColorGetGreen (*inptr); - /* + /* 2.0.24: inptr must not be incremented until after - transparency check, if any. Thanks to "Super Pikeman." + transparency check, if any. Thanks to "Super Pikeman." */ b = gdTrueColorGetBlue (*inptr); /* If the pixel is transparent, we assign it the palette index that * will later be added at the end of the palette as the transparent * index. */ - if ((oim->transparent >= 0) && (oim->transparent == *(inptr - 1))) + if ((oim->transparent >= 0) && (oim->transparent == *inptr)) { *outptr++ = nim->colorsTotal; inptr++; @@ -1795,7 +1795,7 @@ static void gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int color } } else { nim = oim; - } + } if (!oim->trueColor) { /* (Almost) nothing to do! */ @@ -2004,7 +2004,7 @@ static void gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int color } /* Success! Get rid of the truecolor image data. */ - if (!cimP) { + if (!cimP) { oim->trueColor = 0; /* Junk the truecolor pixels */ for (i = 0; i < oim->sy; i++) diff --git a/ext/gd/tests/bug72298.phpt b/ext/gd/tests/bug72298.phpt new file mode 100644 index 0000000000..7fba241ed1 --- /dev/null +++ b/ext/gd/tests/bug72298.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #72298: pass2_no_dither out-of-bounds access +--SKIPIF-- +<?php + if (!extension_loaded('gd')) die("skip gd extension not available\n"); +?> +--FILE-- +<?php +$img = imagecreatetruecolor (1 , 1); +imagecolortransparent($img, 0); +imagetruecolortopalette($img, false, 4); +?> +DONE +--EXPECT-- +DONE
\ No newline at end of file diff --git a/ext/gd/tests/bug72339.gd b/ext/gd/tests/bug72339.gd Binary files differnew file mode 100644 index 0000000000..0634c99005 --- /dev/null +++ b/ext/gd/tests/bug72339.gd diff --git a/ext/gd/tests/bug72339.phpt b/ext/gd/tests/bug72339.phpt new file mode 100644 index 0000000000..763ae71000 --- /dev/null +++ b/ext/gd/tests/bug72339.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #72339 Integer Overflow in _gd2GetHeader() resulting in heap overflow +--SKIPIF-- +<?php if (!function_exists("imagecreatefromgd2")) print "skip"; ?> +--FILE-- +<?php imagecreatefromgd2(dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug72339.gd"); ?> +--EXPECTF-- +Warning: imagecreatefromgd2(): gd warning: product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully + in %sbug72339.php on line %d + +Warning: imagecreatefromgd2(): '%sbug72339.gd' is not a valid GD2 file in %sbug72339.php on line %d diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c index b1b634ea5e..67951a828e 100644 --- a/ext/mbstring/php_mbregex.c +++ b/ext/mbstring/php_mbregex.c @@ -32,7 +32,7 @@ #include "ext/standard/info.h" #include "php_mbregex.h" #include "mbstring.h" - + #include "php_onig_compat.h" /* must come prior to the oniguruma header */ #include <oniguruma.h> #undef UChar @@ -55,7 +55,7 @@ struct _zend_mb_regex_globals { #define MBREX(g) (MBSTRG(mb_regex_globals)->g) /* {{{ static void php_mb_regex_free_cache() */ -static void php_mb_regex_free_cache(php_mb_regex_t **pre) +static void php_mb_regex_free_cache(php_mb_regex_t **pre) { onig_free(*pre); } @@ -78,7 +78,7 @@ static int _php_mb_regex_globals_ctor(zend_mb_regex_globals *pglobals TSRMLS_DC) /* }}} */ /* {{{ _php_mb_regex_globals_dtor */ -static void _php_mb_regex_globals_dtor(zend_mb_regex_globals *pglobals TSRMLS_DC) +static void _php_mb_regex_globals_dtor(zend_mb_regex_globals *pglobals TSRMLS_DC) { zend_hash_destroy(&pglobals->ht_rc); } @@ -466,7 +466,7 @@ static php_mb_regex_t *php_mbregex_compile_pattern(const char *pattern, int patl retval = *rc; } out: - return retval; + return retval; } /* }}} */ @@ -483,7 +483,7 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT --len_left; *(p++) = 'i'; } - ++len_req; + ++len_req; } if ((option & ONIG_OPTION_EXTEND) != 0) { @@ -491,7 +491,7 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT --len_left; *(p++) = 'x'; } - ++len_req; + ++len_req; } if ((option & (ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE)) == @@ -500,14 +500,14 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT --len_left; *(p++) = 'p'; } - ++len_req; + ++len_req; } else { if ((option & ONIG_OPTION_MULTILINE) != 0) { if (len_left > 0) { --len_left; *(p++) = 'm'; } - ++len_req; + ++len_req; } if ((option & ONIG_OPTION_SINGLELINE) != 0) { @@ -515,22 +515,22 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT --len_left; *(p++) = 's'; } - ++len_req; + ++len_req; } - } + } if ((option & ONIG_OPTION_FIND_LONGEST) != 0) { if (len_left > 0) { --len_left; *(p++) = 'l'; } - ++len_req; + ++len_req; } if ((option & ONIG_OPTION_FIND_NOT_EMPTY) != 0) { if (len_left > 0) { --len_left; *(p++) = 'n'; } - ++len_req; + ++len_req; } c = 0; @@ -566,7 +566,7 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT --len_left; *(p++) = '\0'; } - ++len_req; + ++len_req; if (len < len_req) { return len_req; } @@ -577,11 +577,11 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT /* {{{ _php_mb_regex_init_options */ static void -_php_mb_regex_init_options(const char *parg, int narg, OnigOptionType *option, OnigSyntaxType **syntax, int *eval) +_php_mb_regex_init_options(const char *parg, int narg, OnigOptionType *option, OnigSyntaxType **syntax, int *eval) { int n; char c; - int optm = 0; + int optm = 0; *syntax = ONIG_SYNTAX_RUBY; @@ -636,13 +636,13 @@ _php_mb_regex_init_options(const char *parg, int narg, OnigOptionType *option, O *syntax = ONIG_SYNTAX_POSIX_EXTENDED; break; case 'e': - if (eval != NULL) *eval = 1; + if (eval != NULL) *eval = 1; break; default: break; } } - if (option != NULL) *option|=optm; + if (option != NULL) *option|=optm; } } /* }}} */ @@ -860,11 +860,11 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp } else { /* FIXME: this code is not multibyte aware! */ convert_to_long_ex(arg_pattern_zval); - pat_buf[0] = (char)Z_LVAL_PP(arg_pattern_zval); + pat_buf[0] = (char)Z_LVAL_PP(arg_pattern_zval); pat_buf[1] = '\0'; arg_pattern = pat_buf; - arg_pattern_len = 1; + arg_pattern_len = 1; } /* create regex pattern buffer */ re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax TSRMLS_CC); @@ -934,7 +934,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp } } } - + if (eval) { zval v; /* null terminate buffer */ @@ -953,32 +953,31 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp eval_buf.len = 0; zval_dtor(&v); } else if (is_callable) { - zval *retval_ptr; + zval *retval_ptr = NULL; zval **args[1]; zval *subpats; int i; - + MAKE_STD_ZVAL(subpats); array_init(subpats); - + for (i = 0; i < regs->num_regs; i++) { add_next_index_stringl(subpats, string + regs->beg[i], regs->end[i] - regs->beg[i], 1); - } - + } + args[0] = &subpats; /* null terminate buffer */ smart_str_0(&eval_buf); - + arg_replace_fci.param_count = 1; arg_replace_fci.params = args; arg_replace_fci.retval_ptr_ptr = &retval_ptr; - if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache TSRMLS_CC) == SUCCESS && arg_replace_fci.retval_ptr_ptr) { + if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache TSRMLS_CC) == SUCCESS && arg_replace_fci.retval_ptr_ptr && retval_ptr) { convert_to_string_ex(&retval_ptr); smart_str_appendl(&out_buf, Z_STRVAL_P(retval_ptr), Z_STRLEN_P(retval_ptr)); eval_buf.len = 0; zval_ptr_dtor(&retval_ptr); } else { - efree(description); if (!EG(exception)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call custom replacement function"); } @@ -991,7 +990,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp pos = (OnigUChar *)string + n; } else { if (pos < string_lim) { - smart_str_appendl(&out_buf, pos, 1); + smart_str_appendl(&out_buf, pos, 1); } pos++; } @@ -1013,7 +1012,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp smart_str_free(&eval_buf); if (err <= -2) { - smart_str_free(&out_buf); + smart_str_free(&out_buf); RETVAL_FALSE; } else { smart_str_appendc(&out_buf, '\0'); @@ -1063,7 +1062,7 @@ PHP_FUNCTION(mb_split) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &arg_pattern, &arg_pattern_len, &string, &string_len, &count) == FAILURE) { RETURN_FALSE; - } + } if (count > 0) { count--; @@ -1317,7 +1316,7 @@ PHP_FUNCTION(mb_ereg_search_init) if (zend_parse_parameters(argc TSRMLS_CC, "z|ss", &arg_str, &arg_pattern, &arg_pattern_len, &arg_options, &arg_options_len) == FAILURE) { return; } - + if (argc > 1 && arg_pattern_len == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty pattern"); RETURN_FALSE; @@ -1416,7 +1415,7 @@ PHP_FUNCTION(mb_ereg_search_setpos) /* }}} */ /* {{{ php_mb_regex_set_options */ -static void _php_mb_regex_set_options(OnigOptionType options, OnigSyntaxType *syntax, OnigOptionType *prev_options, OnigSyntaxType **prev_syntax TSRMLS_DC) +static void _php_mb_regex_set_options(OnigOptionType options, OnigSyntaxType *syntax, OnigOptionType *prev_options, OnigSyntaxType **prev_syntax TSRMLS_DC) { if (prev_options != NULL) { *prev_options = MBREX(regex_default_options); diff --git a/ext/mbstring/tests/bug72402.phpt b/ext/mbstring/tests/bug72402.phpt new file mode 100644 index 0000000000..abb290bf4d --- /dev/null +++ b/ext/mbstring/tests/bug72402.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #72402: _php_mb_regex_ereg_replace_exec - double free +--SKIPIF-- +<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?> +--FILE-- +<?php +function throwit() { + throw new Exception('it'); +} +$var10 = "throwit"; +try { + $var14 = mb_ereg_replace_callback("", $var10, ""); +} catch(Exception $e) {} +?> +DONE +--EXPECT-- +DONE
\ No newline at end of file diff --git a/ext/mcrypt/mcrypt.c b/ext/mcrypt/mcrypt.c index 45dd5a5f6f..7539d9e53f 100644 --- a/ext/mcrypt/mcrypt.c +++ b/ext/mcrypt/mcrypt.c @@ -45,7 +45,7 @@ static int le_mcrypt; -typedef struct _php_mcrypt { +typedef struct _php_mcrypt { MCRYPT td; zend_bool init; } php_mcrypt; @@ -295,7 +295,7 @@ ZEND_DECLARE_MODULE_GLOBALS(mcrypt) zend_module_entry mcrypt_module_entry = { STANDARD_MODULE_HEADER, - "mcrypt", + "mcrypt", mcrypt_functions, PHP_MINIT(mcrypt), PHP_MSHUTDOWN(mcrypt), NULL, NULL, @@ -343,7 +343,7 @@ typedef enum { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mcryptind) == FAILURE) { \ return; \ } \ - ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt); + ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt); #define MCRYPT_GET_MODE_DIR_ARGS(DIRECTORY) \ char *dir = NULL; \ @@ -374,7 +374,7 @@ PHP_INI_END() static void php_mcrypt_module_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { php_mcrypt *pm = (php_mcrypt *) rsrc->ptr; - if (pm) { + if (pm) { mcrypt_generic_deinit(pm->td); mcrypt_module_close(pm->td); efree(pm); @@ -517,7 +517,7 @@ PHP_MINFO_FUNCTION(mcrypt) /* {{{ */ smart_str_free(&tmp1); smart_str_free(&tmp2); php_info_print_table_end(); - + DISPLAY_INI_ENTRIES(); } /* }}} */ @@ -532,17 +532,17 @@ PHP_FUNCTION(mcrypt_module_open) int mode_len, mode_dir_len; MCRYPT td; php_mcrypt *pm; - + if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ssss", &cipher, &cipher_len, &cipher_dir, &cipher_dir_len, &mode, &mode_len, &mode_dir, &mode_dir_len)) { return; } - + td = mcrypt_module_open ( cipher, cipher_dir_len > 0 ? cipher_dir : MCG(algorithms_dir), - mode, + mode, mode_dir_len > 0 ? mode_dir : MCG(modes_dir) ); @@ -569,7 +569,7 @@ PHP_FUNCTION(mcrypt_generic_init) int max_key_size, key_size, iv_size; php_mcrypt *pm; int result = 0; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &mcryptind, &key, &key_len, &iv, &iv_len) == FAILURE) { return; } @@ -648,7 +648,7 @@ PHP_FUNCTION(mcrypt_generic) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { return; } - + ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt); PHP_MCRYPT_INIT_CHECK @@ -661,6 +661,10 @@ PHP_FUNCTION(mcrypt_generic) if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ block_size = mcrypt_enc_get_block_size(pm->td); data_size = (((data_len - 1) / block_size) + 1) * block_size; + if (data_size <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size"); + RETURN_FALSE; + } data_s = emalloc(data_size + 1); memset(data_s, 0, data_size); memcpy(data_s, data, data_len); @@ -670,7 +674,7 @@ PHP_FUNCTION(mcrypt_generic) memset(data_s, 0, data_size); memcpy(data_s, data, data_len); } - + mcrypt_generic(pm->td, data_s, data_size); data_s[data_size] = '\0'; @@ -689,11 +693,11 @@ PHP_FUNCTION(mdecrypt_generic) php_mcrypt *pm; char* data_s; int block_size, data_size; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { return; } - + ZEND_FETCH_RESOURCE(pm, php_mcrypt * , &mcryptind, -1, "MCrypt", le_mcrypt); PHP_MCRYPT_INIT_CHECK @@ -706,6 +710,10 @@ PHP_FUNCTION(mdecrypt_generic) if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ block_size = mcrypt_enc_get_block_size(pm->td); data_size = (((data_len - 1) / block_size) + 1) * block_size; + if (data_size <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size"); + RETURN_FALSE; + } data_s = emalloc(data_size + 1); memset(data_s, 0, data_size); memcpy(data_s, data, data_len); @@ -715,7 +723,7 @@ PHP_FUNCTION(mdecrypt_generic) memset(data_s, 0, data_size); memcpy(data_s, data, data_len); } - + mdecrypt_generic(pm->td, data_s, data_size); RETVAL_STRINGL(data_s, data_size, 1); @@ -729,7 +737,7 @@ PHP_FUNCTION(mcrypt_enc_get_supported_key_sizes) { int i, count = 0; int *key_sizes; - + MCRYPT_GET_TD_ARG array_init(return_value); @@ -798,7 +806,7 @@ PHP_FUNCTION(mcrypt_enc_is_block_algorithm) MCRYPT_GET_TD_ARG if (mcrypt_enc_is_block_algorithm(pm->td) == 1) { - RETURN_TRUE + RETURN_TRUE } else { RETURN_FALSE } @@ -877,7 +885,7 @@ PHP_FUNCTION(mcrypt_enc_get_modes_name) PHP_FUNCTION(mcrypt_module_self_test) { MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir); - + if (mcrypt_module_self_test(module, dir) == 0) { RETURN_TRUE; } else { @@ -891,7 +899,7 @@ PHP_FUNCTION(mcrypt_module_self_test) PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode) { MCRYPT_GET_MODE_DIR_ARGS(modes_dir) - + if (mcrypt_module_is_block_algorithm_mode(module, dir) == 1) { RETURN_TRUE; } else { @@ -905,7 +913,7 @@ PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode) PHP_FUNCTION(mcrypt_module_is_block_algorithm) { MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) - + if (mcrypt_module_is_block_algorithm(module, dir) == 1) { RETURN_TRUE; } else { @@ -919,7 +927,7 @@ PHP_FUNCTION(mcrypt_module_is_block_algorithm) PHP_FUNCTION(mcrypt_module_is_block_mode) { MCRYPT_GET_MODE_DIR_ARGS(modes_dir) - + if (mcrypt_module_is_block_mode(module, dir) == 1) { RETURN_TRUE; } else { @@ -933,7 +941,7 @@ PHP_FUNCTION(mcrypt_module_is_block_mode) PHP_FUNCTION(mcrypt_module_get_algo_block_size) { MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) - + RETURN_LONG(mcrypt_module_get_algo_block_size(module, dir)); } /* }}} */ @@ -943,7 +951,7 @@ PHP_FUNCTION(mcrypt_module_get_algo_block_size) PHP_FUNCTION(mcrypt_module_get_algo_key_size) { MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir); - + RETURN_LONG(mcrypt_module_get_algo_key_size(module, dir)); } /* }}} */ @@ -954,7 +962,7 @@ PHP_FUNCTION(mcrypt_module_get_supported_key_sizes) { int i, count = 0; int *key_sizes; - + MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) array_init(return_value); @@ -980,7 +988,7 @@ PHP_FUNCTION(mcrypt_list_algorithms) &lib_dir, &lib_dir_len) == FAILURE) { return; } - + array_init(return_value); modules = mcrypt_list_algorithms(lib_dir, &count); @@ -1027,7 +1035,7 @@ PHP_FUNCTION(mcrypt_get_key_size) { char *cipher; char *module; - int cipher_len, module_len; + int cipher_len, module_len; char *cipher_dir_string; char *module_dir_string; MCRYPT td; @@ -1038,7 +1046,7 @@ PHP_FUNCTION(mcrypt_get_key_size) &cipher, &cipher_len, &module, &module_len) == FAILURE) { return; } - + td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); if (td != MCRYPT_FAILED) { RETVAL_LONG(mcrypt_enc_get_key_size(td)); @@ -1056,7 +1064,7 @@ PHP_FUNCTION(mcrypt_get_block_size) { char *cipher; char *module; - int cipher_len, module_len; + int cipher_len, module_len; char *cipher_dir_string; char *module_dir_string; MCRYPT td; @@ -1067,7 +1075,7 @@ PHP_FUNCTION(mcrypt_get_block_size) &cipher, &cipher_len, &module, &module_len) == FAILURE) { return; } - + td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); if (td != MCRYPT_FAILED) { RETVAL_LONG(mcrypt_enc_get_block_size(td)); @@ -1085,7 +1093,7 @@ PHP_FUNCTION(mcrypt_get_iv_size) { char *cipher; char *module; - int cipher_len, module_len; + int cipher_len, module_len; char *cipher_dir_string; char *module_dir_string; MCRYPT td; @@ -1096,7 +1104,7 @@ PHP_FUNCTION(mcrypt_get_iv_size) &cipher, &cipher_len, &module, &module_len) == FAILURE) { return; } - + td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); if (td != MCRYPT_FAILED) { RETVAL_LONG(mcrypt_enc_get_iv_size(td)); @@ -1360,7 +1368,7 @@ PHP_FUNCTION(mcrypt_ecb) zval **mode; char *cipher, *key, *data, *iv = NULL; int cipher_len, key_len, data_len, iv_len = 0; - + MCRYPT_GET_CRYPT_ARGS convert_to_long_ex(mode); @@ -1392,7 +1400,7 @@ PHP_FUNCTION(mcrypt_cfb) zval **mode; char *cipher, *key, *data, *iv = NULL; int cipher_len, key_len, data_len, iv_len = 0; - + MCRYPT_GET_CRYPT_ARGS convert_to_long_ex(mode); @@ -1408,7 +1416,7 @@ PHP_FUNCTION(mcrypt_ofb) zval **mode; char *cipher, *key, *data, *iv = NULL; int cipher_len, key_len, data_len, iv_len = 0; - + MCRYPT_GET_CRYPT_ARGS convert_to_long_ex(mode); @@ -1434,9 +1442,9 @@ PHP_FUNCTION(mcrypt_create_iv) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create an IV with a size of less than 1 or greater than %d", INT_MAX); RETURN_FALSE; } - + iv = ecalloc(size + 1, 1); - + if (source == RANDOM || source == URANDOM) { #if PHP_WIN32 /* random/urandom equivalent on Windows */ diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 78bb33dda4..42a8e7aa44 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -846,6 +846,16 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* } /* }}} */ +static HashTable *spl_array_get_gc(zval *object, zval ***gc_data, int *gc_data_count TSRMLS_DC) /* {{{ */ +{ + spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + + *gc_data = &intern->array; + *gc_data_count = 1; + return zend_std_get_properties(object TSRMLS_CC); +} +/* }}} */ + static zval *spl_array_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ { spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); @@ -1975,6 +1985,7 @@ PHP_MINIT_FUNCTION(spl_array) spl_handler_ArrayObject.get_properties = spl_array_get_properties; spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info; + spl_handler_ArrayObject.get_gc = spl_array_get_gc; spl_handler_ArrayObject.read_property = spl_array_read_property; spl_handler_ArrayObject.write_property = spl_array_write_property; spl_handler_ArrayObject.get_property_ptr_ptr = spl_array_get_property_ptr_ptr; diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index e60078a539..73a2d70acc 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -79,9 +79,9 @@ static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */ if (intern->oth_handler && intern->oth_handler->dtor) { intern->oth_handler->dtor(intern TSRMLS_CC); } - + zend_object_std_dtor(&intern->std TSRMLS_CC); - + if (intern->_path) { efree(intern->_path); } @@ -98,7 +98,7 @@ static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */ } if (intern->u.dir.sub_path) { efree(intern->u.dir.sub_path); - } + } break; case SPL_FS_FILE: if (intern->u.file.stream) { @@ -134,13 +134,13 @@ static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */ } /* }}} */ /* {{{ spl_ce_dir_object_new */ -/* creates the object by - - allocating memory +/* creates the object by + - allocating memory - initializing the object members - storing the object - setting it's handlers - called from + called from - clone - new */ @@ -313,7 +313,7 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu /* avoid reference counting in debug mode, thus do it manually */ ZVAL_RESOURCE(&intern->u.file.zresource, php_stream_get_resource_id(intern->u.file.stream)); Z_SET_REFCOUNT(intern->u.file.zresource, 1); - + intern->u.file.delimiter = ','; intern->u.file.enclosure = '"'; intern->u.file.escape = '\\'; @@ -325,7 +325,7 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu /* {{{ spl_filesystem_object_clone */ /* Local zend_object_value creation (on stack) - Load the 'other' object + Load the 'other' object Create a new empty object (See spl_filesystem_object_new_ex) Open the directory Clone other members (properties) @@ -370,7 +370,7 @@ static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC) php_error_docref(NULL TSRMLS_CC, E_ERROR, "An object of class %s cannot be cloned", old_object->ce->name); break; } - + intern->file_class = source->file_class; intern->info_class = source->info_class; intern->oth = source->oth; @@ -389,7 +389,7 @@ static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC) void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, int len, int use_copy TSRMLS_DC) /* {{{ */ { char *p1, *p2; - + if (intern->file_name) { efree(intern->file_name); } @@ -413,7 +413,7 @@ void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, } else { intern->_path_len = 0; } - + if (intern->_path) { efree(intern->_path); } @@ -459,7 +459,7 @@ static spl_filesystem_object * spl_filesystem_object_create_info(spl_filesystem_ } else { spl_filesystem_info_set_filename(intern, file_path, file_path_len, use_copy TSRMLS_CC); } - + zend_restore_error_handling(&error_handling TSRMLS_CC); return intern; } /* }}} */ @@ -514,7 +514,7 @@ static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_fil return_value->value.obj = spl_filesystem_object_new_ex(ce, &intern TSRMLS_CC); Z_TYPE_P(return_value) = IS_OBJECT; - + spl_filesystem_object_get_file_name(source TSRMLS_CC); if (ce->constructor->common.scope != spl_ce_SplFileObject) { @@ -530,12 +530,12 @@ static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_fil intern->file_name_len = source->file_name_len; intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len TSRMLS_CC); intern->_path = estrndup(intern->_path, intern->_path_len); - + intern->u.file.open_mode = "r"; intern->u.file.open_mode_len = 1; - - if (ht && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sbr", - &intern->u.file.open_mode, &intern->u.file.open_mode_len, + + if (ht && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sbr", + &intern->u.file.open_mode, &intern->u.file.open_mode_len, &use_include_path, &intern->u.file.zcontext) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); intern->u.file.open_mode = NULL; @@ -544,7 +544,7 @@ static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_fil Z_TYPE_P(return_value) = IS_NULL; return NULL; } - + if (spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); zval_dtor(return_value); @@ -553,7 +553,7 @@ static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_fil } } break; - case SPL_FS_DIR: + case SPL_FS_DIR: zend_restore_error_handling(&error_handling TSRMLS_CC); zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Operation not supported"); return NULL; @@ -617,7 +617,7 @@ static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp T if (intern->file_name) { pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1, &pnlen TSRMLS_CC); spl_filesystem_object_get_path(intern, &path_len TSRMLS_CC); - + if (path_len && path_len < intern->file_name_len) { add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1), 1); } else { @@ -665,13 +665,13 @@ static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp T zend_function *spl_filesystem_object_get_method_check(zval **object_ptr, char *method, int method_len, const struct _zend_literal *key TSRMLS_DC) /* {{{ */ { spl_filesystem_object *fsobj = zend_object_store_get_object(*object_ptr TSRMLS_CC); - + if (fsobj->u.dir.entry.d_name[0] == '\0' && fsobj->orig_path == NULL) { method = "_bad_state_ex"; method_len = sizeof("_bad_state_ex") - 1; key = NULL; } - + return zend_get_std_object_handlers()->get_method(object_ptr, method, method_len, key TSRMLS_CC); } /* }}} */ @@ -751,7 +751,7 @@ SPL_METHOD(DirectoryIterator, __construct) SPL_METHOD(DirectoryIterator, rewind) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -769,7 +769,7 @@ SPL_METHOD(DirectoryIterator, rewind) SPL_METHOD(DirectoryIterator, key) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -799,7 +799,7 @@ SPL_METHOD(DirectoryIterator, next) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -860,7 +860,7 @@ SPL_METHOD(DirectoryIterator, seek) SPL_METHOD(DirectoryIterator, valid) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -876,7 +876,7 @@ SPL_METHOD(SplFileInfo, getPath) spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); char *path; int path_len; - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -892,13 +892,13 @@ SPL_METHOD(SplFileInfo, getFilename) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); int path_len; - + if (zend_parse_parameters_none() == FAILURE) { return; } spl_filesystem_object_get_path(intern, &path_len TSRMLS_CC); - + if (path_len && path_len < intern->file_name_len) { RETURN_STRINGL(intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1), 1); } else { @@ -912,7 +912,7 @@ SPL_METHOD(SplFileInfo, getFilename) SPL_METHOD(DirectoryIterator, getFilename) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1020,7 +1020,7 @@ SPL_METHOD(SplFileInfo, getBasename) RETURN_STRINGL(fname, flen, 0); } -/* }}}*/ +/* }}}*/ /* {{{ proto string DirectoryIterator::getBasename([string $suffix]) U Returns filename component of current dir entry */ @@ -1030,7 +1030,7 @@ SPL_METHOD(DirectoryIterator, getBasename) char *suffix = 0, *fname; int slen = 0; size_t flen; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &suffix, &slen) == FAILURE) { return; } @@ -1066,7 +1066,7 @@ SPL_METHOD(SplFileInfo, getPathname) SPL_METHOD(FilesystemIterator, key) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1085,7 +1085,7 @@ SPL_METHOD(FilesystemIterator, key) SPL_METHOD(FilesystemIterator, current) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1108,7 +1108,7 @@ SPL_METHOD(FilesystemIterator, current) SPL_METHOD(DirectoryIterator, isDot) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1122,8 +1122,8 @@ SPL_METHOD(DirectoryIterator, isDot) /* zend_replace_error_handling() is used to throw exceptions in case the constructor fails. Here we use this to ensure the object has a valid directory resource. - - When the constructor gets called the object is already created + + When the constructor gets called the object is already created by the engine, so we must only call 'additional' initializations. */ SPL_METHOD(SplFileInfo, __construct) @@ -1141,11 +1141,11 @@ SPL_METHOD(SplFileInfo, __construct) } intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_info_set_filename(intern, path, len, 1 TSRMLS_CC); zend_restore_error_handling(&error_handling TSRMLS_CC); - + /* intern->type = SPL_FS_INFO; already set */ } /* }}} */ @@ -1250,7 +1250,7 @@ SPL_METHOD(SplFileInfo, getLinkTarget) int ret; char buff[MAXPATHLEN]; zend_error_handling error_handling; - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1298,7 +1298,7 @@ SPL_METHOD(SplFileInfo, getRealPath) char buff[MAXPATHLEN]; char *filename; zend_error_handling error_handling; - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1308,10 +1308,10 @@ SPL_METHOD(SplFileInfo, getRealPath) if (intern->type == SPL_FS_DIR && !intern->file_name && intern->u.dir.entry.d_name[0]) { spl_filesystem_object_get_file_name(intern TSRMLS_CC); } - + if (intern->orig_path) { filename = intern->orig_path; - } else { + } else { filename = intern->file_name; } @@ -1349,7 +1349,7 @@ SPL_METHOD(SplFileInfo, setFileClass) spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); zend_class_entry *ce = spl_ce_SplFileObject; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == SUCCESS) { @@ -1367,7 +1367,7 @@ SPL_METHOD(SplFileInfo, setInfoClass) spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); zend_class_entry *ce = spl_ce_SplFileInfo; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == SUCCESS) { @@ -1385,7 +1385,7 @@ SPL_METHOD(SplFileInfo, getFileInfo) spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); zend_class_entry *ce = intern->info_class; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == SUCCESS) { @@ -1403,7 +1403,7 @@ SPL_METHOD(SplFileInfo, getPathInfo) spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); zend_class_entry *ce = intern->info_class; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == SUCCESS) { @@ -1464,7 +1464,7 @@ SPL_METHOD(FilesystemIterator, rewind) SPL_METHOD(FilesystemIterator, getFlags) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1520,11 +1520,11 @@ SPL_METHOD(RecursiveDirectoryIterator, getChildren) spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); spl_filesystem_object *subdir; char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; - + if (zend_parse_parameters_none() == FAILURE) { return; } - + spl_filesystem_object_get_file_name(intern TSRMLS_CC); MAKE_STD_ZVAL(zflags); @@ -1555,7 +1555,7 @@ SPL_METHOD(RecursiveDirectoryIterator, getChildren) SPL_METHOD(RecursiveDirectoryIterator, getSubPath) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1576,7 +1576,7 @@ SPL_METHOD(RecursiveDirectoryIterator, getSubPathname) char *sub_name; int len; char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1612,7 +1612,7 @@ SPL_METHOD(GlobIterator, __construct) SPL_METHOD(GlobIterator, count) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1667,7 +1667,7 @@ zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval iterator->current = object; } zval_add_ref(&object); - + return (zend_object_iterator*)iterator; } /* }}} */ @@ -1702,7 +1702,7 @@ static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC) static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; - + *data = &iterator->current; } /* }}} */ @@ -1720,7 +1720,7 @@ static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval * static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); - + object->u.dir.index++; spl_filesystem_dir_read(object TSRMLS_CC); if (object->file_name) { @@ -1734,7 +1734,7 @@ static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); - + object->u.dir.index = 0; if (object->u.dir.dirp) { php_stream_rewinddir(object->u.dir.dirp); @@ -1804,7 +1804,7 @@ static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter TSRML { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator); - + object->u.dir.index++; do { spl_filesystem_dir_read(object TSRMLS_CC); @@ -1825,7 +1825,7 @@ static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter TSRMLS_DC) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator); - + object->u.dir.index = 0; if (object->u.dir.dirp) { php_stream_rewinddir(object->u.dir.dirp); @@ -1869,7 +1869,7 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva iterator->intern.funcs = &spl_filesystem_tree_it_funcs; } zval_add_ref(&object); - + return (zend_object_iterator*)iterator; } /* }}} */ @@ -1925,7 +1925,7 @@ static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type TS /* {{{ declare method parameters */ /* supply a name and default to call by parameter */ -ZEND_BEGIN_ARG_INFO(arginfo_info___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_info___construct, 0) ZEND_ARG_INFO(0, file_name) ZEND_END_ARG_INFO() @@ -1984,11 +1984,11 @@ static const zend_function_entry spl_SplFileInfo_functions[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0) ZEND_ARG_INFO(0, path) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_dir_it_seek, 0) +ZEND_BEGIN_ARG_INFO(arginfo_dir_it_seek, 0) ZEND_ARG_INFO(0, position) ZEND_END_ARG_INFO(); @@ -2010,7 +2010,7 @@ static const zend_function_entry spl_DirectoryIterator_functions[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO_EX(arginfo_r_dir___construct, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_r_dir___construct, 0, 0, 1) ZEND_ARG_INFO(0, path) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO() @@ -2059,7 +2059,7 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TS long line_add = (intern->u.file.current_line || intern->u.file.current_zval) ? 1 : 0; spl_filesystem_file_free_line(intern TSRMLS_CC); - + if (php_stream_eof(intern->u.file.stream)) { if (!silent) { zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name); @@ -2087,7 +2087,7 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TS line_len = strcspn(buf, "\r\n"); buf[line_len] = '\0'; } - + intern->u.file.current_line = buf; intern->u.file.current_line_len = line_len; } @@ -2108,7 +2108,7 @@ static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function zval ***params = (zval***)safe_emalloc(num_args, sizeof(zval**), 0); params[0] = &zresource_ptr; - + if (arg2) { params[1] = &arg2; } @@ -2160,11 +2160,11 @@ static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, char escape, zval *return_value TSRMLS_DC) /* {{{ */ { int ret = SUCCESS; - + do { ret = spl_filesystem_file_read(intern, 1 TSRMLS_CC); } while (ret == SUCCESS && !intern->u.file.current_line_len && SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY)); - + if (ret == SUCCESS) { size_t buf_len = intern->u.file.current_line_len; char *buf = estrndup(intern->u.file.current_line, buf_len); @@ -2238,7 +2238,7 @@ static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern TSRML if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) && zend_hash_num_elements(Z_ARRVAL_P(intern->u.file.current_zval)) == 1) { zval ** first = Z_ARRVAL_P(intern->u.file.current_zval)->pListHead->pData; - + return Z_TYPE_PP(first) == IS_STRING && Z_STRLEN_PP(first) == 0; } return zend_hash_num_elements(Z_ARRVAL_P(intern->u.file.current_zval)) == 0; @@ -2261,7 +2261,7 @@ static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object spl_filesystem_file_free_line(intern TSRMLS_CC); ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent TSRMLS_CC); } - + return ret; } /* }}} */ @@ -2299,16 +2299,16 @@ SPL_METHOD(SplFileObject, __construct) intern->u.file.open_mode = NULL; intern->u.file.open_mode_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sbr!", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sbr!", &intern->file_name, &intern->file_name_len, - &intern->u.file.open_mode, &intern->u.file.open_mode_len, - &use_include_path, &intern->u.file.zcontext) == FAILURE) { + &intern->u.file.open_mode, &intern->u.file.open_mode_len, + &use_include_path, &intern->u.file.zcontext) == FAILURE) { intern->u.file.open_mode = NULL; intern->file_name = NULL; zend_restore_error_handling(&error_handling TSRMLS_CC); return; } - + if (intern->u.file.open_mode == NULL) { intern->u.file.open_mode = "r"; intern->u.file.open_mode_len = 1; @@ -2373,7 +2373,7 @@ SPL_METHOD(SplTempFileObject, __construct) intern->u.file.open_mode = "wb"; intern->u.file.open_mode_len = 1; intern->u.file.zcontext = NULL; - + if (spl_filesystem_file_open(intern, 0, 0 TSRMLS_CC) == SUCCESS) { intern->_path_len = 0; intern->_path = estrndup("", 0); @@ -2386,7 +2386,7 @@ SPL_METHOD(SplTempFileObject, __construct) SPL_METHOD(SplFileObject, rewind) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2399,7 +2399,7 @@ SPL_METHOD(SplFileObject, rewind) SPL_METHOD(SplFileObject, eof) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2417,7 +2417,7 @@ SPL_METHOD(SplFileObject, eof) SPL_METHOD(SplFileObject, valid) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2437,7 +2437,7 @@ SPL_METHOD(SplFileObject, valid) SPL_METHOD(SplFileObject, fgets) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2458,7 +2458,7 @@ SPL_METHOD(SplFileObject, fgets) SPL_METHOD(SplFileObject, current) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2484,7 +2484,7 @@ SPL_METHOD(SplFileObject, current) SPL_METHOD(SplFileObject, key) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2501,7 +2501,7 @@ SPL_METHOD(SplFileObject, key) SPL_METHOD(SplFileObject, next) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2553,7 +2553,7 @@ SPL_METHOD(SplFileObject, setMaxLineLen) zend_throw_exception_ex(spl_ce_DomainException, 0 TSRMLS_CC, "Maximum line length must be greater than or equal zero"); return; } - + intern->u.file.max_line_len = max_len; } /* }}} */ @@ -2562,7 +2562,7 @@ SPL_METHOD(SplFileObject, setMaxLineLen) SPL_METHOD(SplFileObject, getMaxLineLen) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2577,7 +2577,7 @@ SPL_METHOD(SplFileObject, hasChildren) if (zend_parse_parameters_none() == FAILURE) { return; } - + RETURN_FALSE; } /* }}} */ @@ -2608,7 +2608,7 @@ SPL_METHOD(SplFileObject, fgetcsv) char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape; char *delim = NULL, *enclo = NULL, *esc = NULL; int d_len = 0, e_len = 0, esc_len = 0; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { if(!intern->u.file.stream) { @@ -2656,7 +2656,7 @@ SPL_METHOD(SplFileObject, fputcsv) char *delim = NULL, *enclo = NULL, *esc = NULL; int d_len = 0, e_len = 0, esc_len = 0, ret; zval *fields = NULL; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|sss", &fields, &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { switch(ZEND_NUM_ARGS()) { @@ -2699,7 +2699,7 @@ SPL_METHOD(SplFileObject, setCsvControl) char delimiter = ',', enclosure = '"', escape='\\'; char *delim = NULL, *enclo = NULL, *esc = NULL; int d_len = 0, e_len = 0, esc_len = 0; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { switch(ZEND_NUM_ARGS()) { @@ -2742,7 +2742,7 @@ SPL_METHOD(SplFileObject, getCsvControl) char delimiter[2], enclosure[2]; array_init(return_value); - + delimiter[0] = intern->u.file.delimiter; delimiter[1] = '\0'; enclosure[0] = intern->u.file.enclosure; @@ -2948,6 +2948,10 @@ SPL_METHOD(SplFileObject, fread) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0"); RETURN_FALSE; } + if (length > INT_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be no more than %d", INT_MAX); + RETURN_FALSE; + } Z_STRVAL_P(return_value) = emalloc(length + 1); Z_STRLEN_P(return_value) = php_stream_read(intern->u.file.stream, Z_STRVAL_P(return_value), length); @@ -2968,7 +2972,7 @@ SPL_METHOD(SplFileObject, ftruncate) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); long size; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size) == FAILURE) { return; } @@ -2982,7 +2986,7 @@ SPL_METHOD(SplFileObject, ftruncate) zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Can't truncate file %s", intern->file_name); RETURN_FALSE; } - + RETURN_BOOL(0 == php_stream_truncate_set_size(intern->u.file.stream, size)); } /* }}} */ @@ -3003,11 +3007,11 @@ SPL_METHOD(SplFileObject, seek) if (line_pos < 0) { zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Can't seek file %s to negative line %ld", intern->file_name, line_pos); - RETURN_FALSE; + RETURN_FALSE; } spl_filesystem_file_rewind(getThis(), intern TSRMLS_CC); - + while(intern->u.file.current_line_num < line_pos) { if (spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC) == FAILURE) { break; @@ -3044,17 +3048,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fputcsv, 0, 0, 1) ZEND_ARG_INFO(0, escape) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_flock, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_flock, 0, 0, 1) ZEND_ARG_INFO(0, operation) ZEND_ARG_INFO(1, wouldblock) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fseek, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fseek, 0, 0, 1) ZEND_ARG_INFO(0, pos) ZEND_ARG_INFO(0, whence) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetss, 0, 0, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetss, 0, 0, 0) ZEND_ARG_INFO(0, allowable_tags) ZEND_END_ARG_INFO() @@ -3063,7 +3067,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 0, 0, 1) ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fwrite, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fwrite, 0, 0, 1) ZEND_ARG_INFO(0, str) ZEND_ARG_INFO(0, length) ZEND_END_ARG_INFO() @@ -3072,11 +3076,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fread, 0, 0, 1) ZEND_ARG_INFO(0, length) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_ftruncate, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_ftruncate, 0, 0, 1) ZEND_ARG_INFO(0, size) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_seek, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_seek, 0, 0, 1) ZEND_ARG_INFO(0, line_pos) ZEND_END_ARG_INFO() @@ -3165,7 +3169,7 @@ PHP_MINIT_FUNCTION(spl_directory) REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, FilesystemIterator, spl_filesystem_object_new, spl_RecursiveDirectoryIterator_functions); REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator); - + memcpy(&spl_filesystem_object_check_handlers, &spl_filesystem_object_handlers, sizeof(zend_object_handlers)); spl_filesystem_object_check_handlers.get_method = spl_filesystem_object_get_method_check; @@ -3182,7 +3186,7 @@ PHP_MINIT_FUNCTION(spl_directory) REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_AHEAD", SPL_FILE_OBJECT_READ_AHEAD); REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "SKIP_EMPTY", SPL_FILE_OBJECT_SKIP_EMPTY); REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_CSV", SPL_FILE_OBJECT_READ_CSV); - + REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_new_check, spl_SplTempFileObject_functions); return SUCCESS; } diff --git a/ext/standard/php_smart_str.h b/ext/standard/php_smart_str.h index a9a34bddc0..edd9d3a89f 100644 --- a/ext/standard/php_smart_str.h +++ b/ext/standard/php_smart_str.h @@ -63,6 +63,9 @@ newlen = (d)->len + (n); \ if (newlen >= (d)->a) { \ (d)->a = newlen + SMART_STR_PREALLOC; \ + if (UNEXPECTED((d)->a >= INT_MAX)) { \ + zend_error(E_ERROR, "String size overflow"); \ + } \ SMART_STR_DO_REALLOC(d, what); \ } \ } \ @@ -148,17 +151,17 @@ * for GCC compatible compilers, e.g. * * #define f(..) ({char *r;..;__r;}) - */ - + */ + static inline char *smart_str_print_long(char *buf, long num) { - char *r; - smart_str_print_long4(buf, num, unsigned long, r); + char *r; + smart_str_print_long4(buf, num, unsigned long, r); return r; } static inline char *smart_str_print_unsigned(char *buf, long num) { - char *r; - smart_str_print_unsigned4(buf, num, unsigned long, r); + char *r; + smart_str_print_unsigned4(buf, num, unsigned long, r); return r; } @@ -168,7 +171,7 @@ static inline char *smart_str_print_unsigned(char *buf, long num) { smart_str_print##func##4 (__b + sizeof(__b) - 1, (num), vartype, __t); \ smart_str_appendl_ex((dest), __t, __b + sizeof(__b) - 1 - __t, (type)); \ } while (0) - + #define smart_str_append_unsigned_ex(dest, num, type) \ smart_str_append_generic_ex((dest), (num), (type), unsigned long, _unsigned) diff --git a/ext/standard/string.c b/ext/standard/string.c index d5f83e7d0f..6fc6acbf1c 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -132,6 +132,9 @@ static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t * register unsigned char *result = NULL; size_t i, j; + if (UNEXPECTED(oldlen * 2 * sizeof(char) > INT_MAX)) { + zend_error(E_ERROR, "String size overflow"); + } result = (unsigned char *) safe_emalloc(oldlen, 2 * sizeof(char), 1); for (i = j = 0; i < oldlen; i++) { @@ -2608,6 +2611,7 @@ PHP_FUNCTION(quotemeta) char *p, *q; char c; int old_len; + size_t new_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &old, &old_len) == FAILURE) { return; @@ -2642,8 +2646,13 @@ PHP_FUNCTION(quotemeta) } } *q = 0; + new_len = q - str; + if (UNEXPECTED(new_len > INT_MAX)) { + efree(str); + zend_error(E_ERROR, "String size overflow"); + } - RETURN_STRINGL(erealloc(str, q - str + 1), q - str, 0); + RETURN_STRINGL(erealloc(str, new_len + 1), new_len, 0); } /* }}} */ @@ -3495,7 +3504,7 @@ PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int s char *source, *target; char *end; char c; - int newlen; + size_t newlen; if (!wlength) { wlength = strlen(what); @@ -3526,11 +3535,15 @@ PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int s } *target = 0; newlen = target - new_str; + if (UNEXPECTED(newlen > INT_MAX)) { + efree(new_str); + zend_error(E_ERROR, "String size overflow"); + } if (target - new_str < length * 4) { new_str = erealloc(new_str, newlen + 1); } if (new_length) { - *new_length = newlen; + *new_length = (int)newlen; } if (should_free) { STR_FREE((char*)str); @@ -3582,6 +3595,9 @@ PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_f *target = 0; *new_length = target - new_str; + if (UNEXPECTED(*new_length < 0)) { + zend_error(E_ERROR, "String size overflow"); + } if (should_free) { STR_FREE(str); } @@ -4285,6 +4301,9 @@ PHP_FUNCTION(nl2br) size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1); new_length = str_len + repl_cnt * repl_len; + if (UNEXPECTED(new_length > INT_MAX)) { + zend_error(E_ERROR, "String size overflow"); + } tmp = target = safe_emalloc(repl_cnt, repl_len, str_len + 1); } diff --git a/ext/standard/tests/strings/bug72433.phpt b/ext/standard/tests/strings/bug72433.phpt new file mode 100644 index 0000000000..3a2c89701b --- /dev/null +++ b/ext/standard/tests/strings/bug72433.phpt @@ -0,0 +1,32 @@ +--TEST-- +Bug #72433: Use After Free Vulnerability in PHP's GC algorithm and unserialize +--FILE-- +<?php +// Fill any potential freed spaces until now. +$filler = array(); +for($i = 0; $i < 100; $i++) + $filler[] = ""; +// Create our payload and unserialize it. +$serialized_payload = 'a:3:{i:0;r:1;i:1;r:1;i:2;C:11:"ArrayObject":19:{x:i:0;r:1;;m:a:0:{}}}'; +$free_me = unserialize($serialized_payload); +// We need to increment the reference counter of our ArrayObject s.t. all reference counters of our unserialized array become 0. +$inc_ref_by_one = $free_me[2]; +// The call to gc_collect_cycles will free '$free_me'. +gc_collect_cycles(); +// We now have multiple freed spaces. Fill all of them. +$fill_freed_space_1 = "filler_zval_1"; +$fill_freed_space_2 = "filler_zval_2"; +var_dump($free_me); +?> +--EXPECTF-- +array(3) { + [0]=> + *RECURSION* + [1]=> + *RECURSION* + [2]=> + object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + *RECURSION* + } +} diff --git a/ext/standard/tests/strings/bug72434.phpt b/ext/standard/tests/strings/bug72434.phpt new file mode 100644 index 0000000000..1408b8f578 --- /dev/null +++ b/ext/standard/tests/strings/bug72434.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug #72434: ZipArchive class Use After Free Vulnerability in PHP's GC algorithm and unserialize +--SKIPIF-- +<?php +if(!class_exists('zip')) die('ZipArchive'); +?> +--FILE-- +<?php +// The following array will be serialized and this representation will be freed later on. +$free_me = array(new StdClass()); +// Create our payload and unserialize it. +$serialized_payload = 'a:3:{i:1;N;i:2;O:10:"ZipArchive":1:{s:8:"filename";'.serialize($free_me).'}i:1;R:4;}'; +$unserialized_payload = unserialize($serialized_payload); +gc_collect_cycles(); +// The reference counter for $free_me is at -1 for PHP 7 right now. +// Increment the reference counter by 1 -> rc is 0 +$a = $unserialized_payload[1]; +// Increment the reference counter by 1 again -> rc is 1 +$b = $a; +// Trigger free of $free_me (referenced by $m[1]). +unset($b); +$fill_freed_space_1 = "filler_zval_1"; +$fill_freed_space_2 = "filler_zval_2"; +$fill_freed_space_3 = "filler_zval_3"; +$fill_freed_space_4 = "filler_zval_4"; +debug_zval_dump($unserialized_payload[1]); +?> +--EXPECTF-- +array(1) refcount(1){ + [0]=> + object(stdClass)#%d (0) refcount(3){ + } +} diff --git a/ext/standard/url.c b/ext/standard/url.c index b34f16a518..4b52000f64 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -65,27 +65,27 @@ PHPAPI char *php_replace_controlchars_ex(char *str, int len) { unsigned char *s = (unsigned char *)str; unsigned char *e = (unsigned char *)str + len; - + if (!str) { return (NULL); } - + while (s < e) { - + if (iscntrl(*s)) { *s='_'; - } + } s++; } - + return (str); -} +} /* }}} */ PHPAPI char *php_replace_controlchars(char *str) { return php_replace_controlchars_ex(str, strlen(str)); -} +} PHPAPI php_url *php_url_parse(char const *str) { @@ -99,7 +99,7 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) char port_buf[6]; php_url *ret = ecalloc(1, sizeof(php_url)); char const *s, *e, *p, *pp, *ue; - + s = str; ue = s + length; @@ -118,40 +118,40 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) } p++; } - + if (*(e + 1) == '\0') { /* only scheme is available */ ret->scheme = estrndup(s, (e - s)); php_replace_controlchars_ex(ret->scheme, (e - s)); goto end; } - /* + /* * certain schemas like mailto: and zlib: may not have any / after them * this check ensures we support those. */ if (*(e+1) != '/') { - /* check if the data we get is a port this allows us to + /* check if the data we get is a port this allows us to * correctly parse things like a.com:80 */ p = e + 1; while (isdigit(*p)) { p++; } - + if ((*p == '\0' || *p == '/') && (p - e) < 7) { goto parse_port; } - + ret->scheme = estrndup(s, (e-s)); php_replace_controlchars_ex(ret->scheme, (e - s)); - + length -= ++e - s; s = e; goto just_path; } else { ret->scheme = estrndup(s, (e-s)); php_replace_controlchars_ex(ret->scheme, (e - s)); - + if (*(e+2) == '/') { s = e + 3; if (!strncasecmp("file", ret->scheme, sizeof("file"))) { @@ -173,9 +173,9 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) length -= ++e - s; s = e; goto just_path; - } + } } - } + } } else if (e) { /* no scheme; starts with colon: look for port */ parse_port: p = e + 1; @@ -216,9 +216,9 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) ue = s + length; goto nohost; } - + e = ue; - + if (!(p = memchr(s, '/', (ue - s)))) { char *query, *fragment; @@ -238,14 +238,14 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) } } else { e = p; - } - + } + /* check for login and password */ if ((p = zend_memrchr(s, '@', (e-s)))) { if ((pp = memchr(s, ':', (p-s)))) { ret->user = estrndup(s, (pp-s)); php_replace_controlchars_ex(ret->user, (pp - s)); - + pp++; ret->pass = estrndup(pp, (p-pp)); php_replace_controlchars_ex(ret->pass, (p-pp)); @@ -253,14 +253,14 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) ret->user = estrndup(s, (p-s)); php_replace_controlchars_ex(ret->user, (p-s)); } - + s = p + 1; } /* check for port */ if (*s == '[' && *(e-1) == ']') { - /* Short circuit portscan, - we're dealing with an + /* Short circuit portscan, + we're dealing with an IPv6 embedded address */ p = s; } else { @@ -294,11 +294,11 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) } } p--; - } + } } else { p = e; } - + /* check if we have a valid host, if we don't reject the string as url */ if ((p-s) < 1) { STR_FREE(ret->scheme); @@ -310,15 +310,15 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) ret->host = estrndup(s, (p-s)); php_replace_controlchars_ex(ret->host, (p - s)); - + if (e == ue) { return ret; } - + s = e; - + nohost: - + if ((p = memchr(s, '?', (ue - s)))) { pp = memchr(s, '#', (ue - s)); @@ -330,14 +330,14 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) p = pp; goto label_parse; } - + if (p - s) { ret->path = estrndup(s, (p-s)); php_replace_controlchars_ex(ret->path, (p - s)); - } - + } + if (pp) { - if (pp - ++p) { + if (pp - ++p) { ret->query = estrndup(p, (pp-p)); php_replace_controlchars_ex(ret->query, (pp - p)); } @@ -351,15 +351,15 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length) if (p - s) { ret->path = estrndup(s, (p-s)); php_replace_controlchars_ex(ret->path, (p - s)); - } - + } + label_parse: p++; - + if (ue - p) { ret->fragment = estrndup(p, (ue-p)); php_replace_controlchars_ex(ret->fragment, (ue - p)); - } + } } else { ret->path = estrndup(s, (ue-s)); php_replace_controlchars_ex(ret->path, (ue - s)); @@ -441,7 +441,7 @@ PHP_FUNCTION(parse_url) add_assoc_string(return_value, "query", resource->query, 1); if (resource->fragment != NULL) add_assoc_string(return_value, "fragment", resource->fragment, 1); -done: +done: php_url_free(resource); } /* }}} */ @@ -489,7 +489,7 @@ PHPAPI char *php_url_encode(char const *s, int len, int *new_length) register unsigned char c; unsigned char *to, *start; unsigned char const *from, *end; - + from = (unsigned char *)s; end = (unsigned char *)s + len; start = to = (unsigned char *) safe_emalloc(3, len, 1); @@ -575,7 +575,7 @@ PHPAPI int php_url_decode(char *str, int len) if (*data == '+') { *dest = ' '; } - else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) + else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) { #ifndef CHARSET_EBCDIC *dest = (char) php_htoi(data + 1); @@ -625,6 +625,10 @@ PHPAPI char *php_raw_url_encode(char const *s, int len, int *new_length) if (new_length) { *new_length = y; } + if (UNEXPECTED(y > INT_MAX)) { + efree(str); + zend_error(E_ERROR, "String size overflow"); + } return ((char *) str); } /* }}} */ @@ -673,7 +677,7 @@ PHPAPI int php_raw_url_decode(char *str, int len) char *data = str; while (len--) { - if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) + if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) { #ifndef CHARSET_EBCDIC *dest = (char) php_htoi(data + 1); @@ -705,7 +709,7 @@ PHP_FUNCTION(get_headers) HashPosition pos; HashTable *hashT; long format = 0; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &url, &url_len, &format) == FAILURE) { return; } @@ -724,12 +728,12 @@ PHP_FUNCTION(get_headers) /* check for curl-wrappers that provide headers via a special "headers" element */ if (zend_hash_find(HASH_OF(stream->wrapperdata), "headers", sizeof("headers"), (void **)&h) != FAILURE && Z_TYPE_PP(h) == IS_ARRAY) { - /* curl-wrappers don't load data until the 1st read */ + /* curl-wrappers don't load data until the 1st read */ if (!Z_ARRVAL_PP(h)->nNumOfElements) { php_stream_getc(stream); } zend_hash_find(HASH_OF(stream->wrapperdata), "headers", sizeof("headers"), (void **)&h); - hashT = Z_ARRVAL_PP(h); + hashT = Z_ARRVAL_PP(h); } else { hashT = HASH_OF(stream->wrapperdata); } diff --git a/ext/wddx/tests/bug72340.phpt b/ext/wddx/tests/bug72340.phpt new file mode 100644 index 0000000000..8d694ca52e --- /dev/null +++ b/ext/wddx/tests/bug72340.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #72340: Double Free Courruption in wddx_deserialize +--SKIPIF-- +<?php +if (!extension_loaded("wddx")) print "skip"; +?> +--FILE-- +<?php +$xml = <<<EOF +<?xml version='1.0' ?> +<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'> +<wddxPacket version='1.0'> + <array><var name="XXXXXXXX"><boolean value="none">TEST</boolean></var> + <var name="YYYYYYYY"><var name="ZZZZZZZZ"><var name="EZEZEZEZ"> + </var></var></var> + </array> +</wddxPacket> +EOF; +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +array(0) { +} diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index 22ff535c63..2cbad93c3e 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -1094,6 +1094,9 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len) break; case ST_BOOLEAN: + if(!ent->data) { + break; + } if (!strcmp(s, "true")) { Z_LVAL_P(ent->data) = 1; } else if (!strcmp(s, "false")) { @@ -1102,6 +1105,7 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len) zval_ptr_dtor(&ent->data); if (ent->varname) { efree(ent->varname); + ent->varname = NULL; } ent->data = NULL; } diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 1791548e0e..47477ac256 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1042,6 +1042,14 @@ static int php_zip_has_property(zval *object, zval *member, int type KEY_ARG_DC } /* }}} */ +static HashTable *php_zip_get_gc(zval *object, zval ***gc_data, int *gc_data_count TSRMLS_DC) /* {{{ */ +{ + *gc_data = NULL; + *gc_data_count = 0; + return zend_std_get_properties(object TSRMLS_CC); +} +/* }}} */ + static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */ { ze_zip_object *obj; @@ -3039,6 +3047,7 @@ static PHP_MINIT_FUNCTION(zip) zip_object_handlers.clone_obj = NULL; zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr; + zip_object_handlers.get_gc = php_zip_get_gc; zip_object_handlers.get_properties = php_zip_get_properties; zip_object_handlers.read_property = php_zip_read_property; zip_object_handlers.has_property = php_zip_has_property; |