summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_alloc.c24
-rw-r--r--ext/bz2/bz2.c18
-rw-r--r--ext/curl/interface.c8
-rw-r--r--ext/exif/exif.c5
-rw-r--r--ext/exif/tests/bug72627.phpt71
-rw-r--r--ext/exif/tests/bug72627.tiffbin0 -> 1250 bytes
-rw-r--r--ext/gd/gd.c11
-rw-r--r--ext/gd/tests/bug72697.phpt17
-rw-r--r--ext/gd/tests/bug72730.phpt15
-rw-r--r--ext/gd/tests/imagetruecolortopalette_error3.phpt2
-rw-r--r--ext/gd/tests/imagetruecolortopalette_error4.phpt4
-rw-r--r--ext/mcrypt/mcrypt.c16
-rw-r--r--ext/session/session.c31
-rw-r--r--ext/session/tests/bug72681.phpt17
-rw-r--r--ext/snmp/snmp.c2
-rw-r--r--ext/standard/base64.c2
-rw-r--r--ext/standard/ftp_fopen_wrapper.c3
-rw-r--r--ext/standard/php_smart_string.h17
-rw-r--r--ext/standard/quot_print.c2
-rw-r--r--ext/standard/tests/serialize/bug72663.phpt56
-rw-r--r--ext/standard/tests/serialize/bug72663_2.phpt27
-rw-r--r--ext/standard/tests/serialize/bug72663_3.phpt17
-rw-r--r--ext/standard/tests/streams/bug72853.phpt59
-rw-r--r--ext/standard/tests/strings/bug70436.phpt65
-rw-r--r--ext/standard/tests/strings/bug72663.phpt26
-rw-r--r--ext/standard/tests/strings/bug72663_2.phpt17
-rw-r--r--ext/standard/tests/strings/bug72663_3.phpt20
-rw-r--r--ext/standard/uuencode.c6
-rw-r--r--ext/standard/var_unserializer.c1036
-rw-r--r--ext/standard/var_unserializer.re50
-rw-r--r--ext/wddx/tests/bug72142.phpt2
-rw-r--r--ext/wddx/tests/bug72749.phpt34
-rw-r--r--ext/wddx/tests/bug72750.phpt34
-rw-r--r--ext/wddx/tests/bug72790.phpt36
-rw-r--r--ext/wddx/tests/bug72799.phpt29
-rw-r--r--ext/wddx/wddx.c35
-rw-r--r--main/fopen_wrappers.c6
-rw-r--r--main/streams/plain_wrapper.c12
38 files changed, 1246 insertions, 586 deletions
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index ed7575d256..1d04646f07 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -1503,21 +1503,21 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size, si
ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted");
if (info & ZEND_MM_IS_SRUN) {
- int old_bin_num, bin_num;
-
- old_bin_num = ZEND_MM_SRUN_BIN_NUM(info);
+ int old_bin_num = ZEND_MM_SRUN_BIN_NUM(info);
old_size = bin_data_size[old_bin_num];
- bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size);
- if (old_bin_num == bin_num) {
+ if (size <= ZEND_MM_MAX_SMALL_SIZE) {
+ int bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size);
+ if (old_bin_num == bin_num) {
#if ZEND_DEBUG
- dbg = zend_mm_get_debug_info(heap, ptr);
- dbg->size = real_size;
- dbg->filename = __zend_filename;
- dbg->orig_filename = __zend_orig_filename;
- dbg->lineno = __zend_lineno;
- dbg->orig_lineno = __zend_orig_lineno;
+ dbg = zend_mm_get_debug_info(heap, ptr);
+ dbg->size = real_size;
+ dbg->filename = __zend_filename;
+ dbg->orig_filename = __zend_orig_filename;
+ dbg->lineno = __zend_lineno;
+ dbg->orig_lineno = __zend_orig_lineno;
#endif
- return ptr;
+ return ptr;
+ }
}
} else /* if (info & ZEND_MM_IS_LARGE_RUN) */ {
ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted");
diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c
index 6678876c96..81615e3080 100644
--- a/ext/bz2/bz2.c
+++ b/ext/bz2/bz2.c
@@ -595,16 +595,26 @@ static PHP_FUNCTION(bzdecompress)
/* compression is better then 2:1, need to allocate more memory */
bzs.avail_out = source_len;
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
+ if (size > SIZE_MAX) {
+ /* no reason to continue if we're going to drop it anyway */
+ break;
+ }
dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size );
bzs.next_out = dest + size;
}
if (error == BZ_STREAM_END || error == BZ_OK) {
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
- dest = safe_erealloc(dest, 1, (size_t) size, 1);
- dest[size] = '\0';
- RETVAL_STRINGL(dest, (int) size);
- efree(dest);
+ if (size > SIZE_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX);
+ efree(dest);
+ RETVAL_LONG(BZ_MEM_ERROR);
+ } else {
+ dest = safe_erealloc(dest, 1, (size_t) size, 1);
+ dest[size] = '\0';
+ RETVAL_STRINGL(dest, (size_t) size);
+ efree(dest);
+ }
} else { /* real error */
efree(dest);
RETVAL_LONG(error);
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index a20d60ca36..08846808fc 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -3530,7 +3530,7 @@ PHP_FUNCTION(curl_reset)
PHP_FUNCTION(curl_escape)
{
char *str = NULL, *res = NULL;
- size_t str_len = 0;
+ size_t str_len = 0;
zval *zid;
php_curl *ch;
@@ -3542,6 +3542,10 @@ PHP_FUNCTION(curl_escape)
RETURN_FALSE;
}
+ if (ZEND_SIZE_T_INT_OVFL(str_len)) {
+ RETURN_FALSE;
+ }
+
if ((res = curl_easy_escape(ch->cp, str, str_len))) {
RETVAL_STRING(res);
curl_free(res);
@@ -3569,7 +3573,7 @@ PHP_FUNCTION(curl_unescape)
RETURN_FALSE;
}
- if (str_len > INT_MAX) {
+ if (ZEND_SIZE_T_INT_OVFL(str_len)) {
RETURN_FALSE;
}
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index f62f77a60f..91aeb7dc7b 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -3758,8 +3758,11 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse
fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size);
if (fgot < ImageInfo->Thumbnail.size) {
EXIF_ERRLOG_THUMBEOF(ImageInfo)
+ efree(ImageInfo->Thumbnail.data);
+ ImageInfo->Thumbnail.data = NULL;
+ } else {
+ exif_thumbnail_build(ImageInfo);
}
- exif_thumbnail_build(ImageInfo);
}
#ifdef EXIF_DEBUG
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read next IFD (THUMBNAIL) done");
diff --git a/ext/exif/tests/bug72627.phpt b/ext/exif/tests/bug72627.phpt
new file mode 100644
index 0000000000..bb6a1fae99
--- /dev/null
+++ b/ext/exif/tests/bug72627.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Bug #72627 (Memory Leakage In exif_process_IFD_in_TIFF)
+--SKIPIF--
+<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
+--FILE--
+<?php
+ $exif = exif_read_data(__DIR__ . '/bug72627.tiff',0,0,true);
+ var_dump($exif);
+?>
+--EXPECTF--
+Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d
+
+Warning: exif_read_data(%s): Error in TIFF: filesize(x04E2) less than start of IFD dir(x829A0004) in %sbug72627.php on line %d
+
+Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d
+array(11) {
+ ["FileName"]=>
+ string(13) "bug72627.tiff"
+ ["FileDateTime"]=>
+ int(%d)
+ ["FileSize"]=>
+ int(1250)
+ ["FileType"]=>
+ int(7)
+ ["MimeType"]=>
+ string(10) "image/tiff"
+ ["SectionsFound"]=>
+ string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF"
+ ["COMPUTED"]=>
+ array(10) {
+ ["html"]=>
+ string(24) "width="128" height="132""
+ ["Height"]=>
+ int(132)
+ ["Width"]=>
+ int(128)
+ ["IsColor"]=>
+ int(0)
+ ["ByteOrderMotorola"]=>
+ int(0)
+ ["ApertureFNumber"]=>
+ string(5) "f/1.0"
+ ["Thumbnail.FileType"]=>
+ int(2)
+ ["Thumbnail.MimeType"]=>
+ string(10) "image/jpeg"
+ ["Thumbnail.Height"]=>
+ int(132)
+ ["Thumbnail.Width"]=>
+ int(128)
+ }
+ ["XResolution"]=>
+ string(21) "1414812756/1414812756"
+ ["THUMBNAIL"]=>
+ array(5) {
+ ["ImageWidth"]=>
+ int(128)
+ ["ImageLength"]=>
+ int(132)
+ ["JPEGInterchangeFormat"]=>
+ int(1280)
+ ["JPEGInterchangeFormatLength"]=>
+ int(100)
+ ["THUMBNAIL"]=>
+ NULL
+ }
+ ["ExposureTime"]=>
+ string(21) "1414812756/1414812756"
+ ["FNumber"]=>
+ string(21) "1414812756/1414812756"
+}
diff --git a/ext/exif/tests/bug72627.tiff b/ext/exif/tests/bug72627.tiff
new file mode 100644
index 0000000000..229190a604
--- /dev/null
+++ b/ext/exif/tests/bug72627.tiff
Binary files differ
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index d0eea0bd0b..d2655a6022 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -1537,11 +1537,11 @@ PHP_FUNCTION(imagetruecolortopalette)
RETURN_FALSE;
}
- if (ncolors <= 0) {
- php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero");
+ if (ncolors <= 0 || ZEND_LONG_INT_OVFL(ncolors)) {
+ php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero and no more than %d", INT_MAX);
RETURN_FALSE;
}
- gdImageTrueColorToPalette(im, dither, ncolors);
+ gdImageTrueColorToPalette(im, dither, (int)ncolors);
RETURN_TRUE;
}
@@ -3039,6 +3039,11 @@ PHP_FUNCTION(imagegammacorrect)
return;
}
+ if ( input <= 0.0 || output <= 0.0 ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Gamma values should be positive");
+ RETURN_FALSE;
+ }
+
if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
RETURN_FALSE;
}
diff --git a/ext/gd/tests/bug72697.phpt b/ext/gd/tests/bug72697.phpt
new file mode 100644
index 0000000000..6110385fcb
--- /dev/null
+++ b/ext/gd/tests/bug72697.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #72697: select_colors write out-of-bounds
+--SKIPIF--
+<?php
+if (!function_exists("imagecreatetruecolor")) die("skip");
+if (PHP_INT_MAX !== 9223372036854775807) die("skip for 64-bit long systems only");
+?>
+--FILE--
+<?php
+
+$img=imagecreatetruecolor(10, 10);
+imagetruecolortopalette($img, false, PHP_INT_MAX / 8);
+?>
+DONE
+--EXPECTF--
+Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than 2147483647 in %sbug72697.php on line %d
+DONE \ No newline at end of file
diff --git a/ext/gd/tests/bug72730.phpt b/ext/gd/tests/bug72730.phpt
new file mode 100644
index 0000000000..e7c13cb5e9
--- /dev/null
+++ b/ext/gd/tests/bug72730.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #72730: imagegammacorrect allows arbitrary write access
+--SKIPIF--
+<?php
+if (!function_exists("imagecreatetruecolor")) die("skip");
+?>
+--FILE--
+<?php
+$img = imagecreatetruecolor(1, 1);
+imagegammacorrect($img, -1, 1337);
+?>
+DONE
+--EXPECTF--
+Warning: imagegammacorrect(): Gamma values should be positive in %sbug72730.php on line %d
+DONE \ No newline at end of file
diff --git a/ext/gd/tests/imagetruecolortopalette_error3.phpt b/ext/gd/tests/imagetruecolortopalette_error3.phpt
index de3a62d0a5..46e3f487e0 100644
--- a/ext/gd/tests/imagetruecolortopalette_error3.phpt
+++ b/ext/gd/tests/imagetruecolortopalette_error3.phpt
@@ -25,4 +25,4 @@ Warning: imagetruecolortopalette() expects parameter 3 to be integer, resource g
Warning: imagetruecolortopalette() expects parameter 3 to be integer, array given in %s on line %d
-Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d \ No newline at end of file
+Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s on line %d
diff --git a/ext/gd/tests/imagetruecolortopalette_error4.phpt b/ext/gd/tests/imagetruecolortopalette_error4.phpt
index b9661e3b85..f0e18b86be 100644
--- a/ext/gd/tests/imagetruecolortopalette_error4.phpt
+++ b/ext/gd/tests/imagetruecolortopalette_error4.phpt
@@ -16,6 +16,6 @@ imagetruecolortopalette($image, true, -1);
?>
--EXPECTF--
-Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d
+Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s line %d
-Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d \ No newline at end of file
+Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s line %d
diff --git a/ext/mcrypt/mcrypt.c b/ext/mcrypt/mcrypt.c
index cf9c2ccdf1..c2c60c2b3c 100644
--- a/ext/mcrypt/mcrypt.c
+++ b/ext/mcrypt/mcrypt.c
@@ -633,6 +633,10 @@ PHP_FUNCTION(mcrypt_generic)
RETURN_FALSE
}
+ if (data_len > INT_MAX) {
+ php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
+ RETURN_FALSE;
+ }
/* Check blocksize */
if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
block_size = mcrypt_enc_get_block_size(pm->td);
@@ -645,10 +649,6 @@ PHP_FUNCTION(mcrypt_generic)
memset(ZSTR_VAL(data_str), 0, data_size);
memcpy(ZSTR_VAL(data_str), data, data_len);
} else { /* It's not a block algorithm */
- if (data_len > INT_MAX) {
- php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
- RETURN_FALSE;
- }
data_size = (int)data_len;
data_str = zend_string_alloc(data_size, 0);
memset(ZSTR_VAL(data_str), 0, data_size);
@@ -688,6 +688,10 @@ PHP_FUNCTION(mdecrypt_generic)
}
/* Check blocksize */
+ if (data_len > INT_MAX) {
+ php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
+ RETURN_FALSE;
+ }
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 = ((((int)data_len - 1) / block_size) + 1) * block_size;
@@ -699,10 +703,6 @@ PHP_FUNCTION(mdecrypt_generic)
memset(data_s, 0, data_size);
memcpy(data_s, data, data_len);
} else { /* It's not a block algorithm */
- if (data_len > INT_MAX) {
- php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
- RETURN_FALSE;
- }
data_size = (int)data_len;
data_s = emalloc(data_size + 1);
memset(data_s, 0, data_size);
diff --git a/ext/session/session.c b/ext/session/session.c
index 1247a99804..b303b90653 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -765,12 +765,19 @@ PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */
const char *endptr = val + vallen;
zval session_vars;
php_unserialize_data_t var_hash;
+ int result;
zend_string *var_name = zend_string_init("_SESSION", sizeof("_SESSION") - 1, 0);
ZVAL_NULL(&session_vars);
PHP_VAR_UNSERIALIZE_INIT(var_hash);
- php_var_unserialize(&session_vars, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash);
+ result = php_var_unserialize(
+ &session_vars, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash);
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ if (!result) {
+ zval_ptr_dtor(&session_vars);
+ ZVAL_NULL(&session_vars);
+ }
+
if (!Z_ISUNDEF(PS(http_session_vars))) {
zval_ptr_dtor(&PS(http_session_vars));
}
@@ -823,11 +830,13 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
int namelen;
zend_string *name;
php_unserialize_data_t var_hash;
+ int skip = 0;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
for (p = val; p < endptr; ) {
zval *tmp;
+ skip = 0;
namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF);
if (namelen < 0 || namelen > PS_BIN_MAX || (p + namelen) >= endptr) {
@@ -844,8 +853,7 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
if ((tmp = zend_hash_find(&EG(symbol_table), name))) {
if ((Z_TYPE_P(tmp) == IS_ARRAY &&
Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) {
- zend_string_release(name);
- continue;
+ skip = 1;
}
}
@@ -854,7 +862,9 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
current = var_tmp_var(&var_hash);
if (php_var_unserialize(current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash)) {
ZVAL_PTR(&rv, current);
- php_set_session_var(name, &rv, &var_hash );
+ if (!skip) {
+ php_set_session_var(name, &rv, &var_hash);
+ }
} else {
zend_string_release(name);
php_session_normalize_vars();
@@ -916,6 +926,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
zend_string *name;
int has_value, retval = SUCCESS;
php_unserialize_data_t var_hash;
+ int skip = 0;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
@@ -924,6 +935,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
while (p < endptr) {
zval *tmp;
q = p;
+ skip = 0;
while (*q != PS_DELIMITER) {
if (++q >= endptr) goto break_outer_loop;
}
@@ -941,7 +953,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
if ((tmp = zend_hash_find(&EG(symbol_table), name))) {
if ((Z_TYPE_P(tmp) == IS_ARRAY &&
Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) {
- goto skip;
+ skip = 1;
}
}
@@ -950,16 +962,19 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
current = var_tmp_var(&var_hash);
if (php_var_unserialize(current, (const unsigned char **)&q, (const unsigned char *)endptr, &var_hash)) {
ZVAL_PTR(&rv, current);
- php_set_session_var(name, &rv, &var_hash);
+ if (!skip) {
+ php_set_session_var(name, &rv, &var_hash);
+ }
} else {
zend_string_release(name);
retval = FAILURE;
goto break_outer_loop;
}
} else {
- PS_ADD_VARL(name);
+ if(!skip) {
+ PS_ADD_VARL(name);
+ }
}
-skip:
zend_string_release(name);
p = q;
diff --git a/ext/session/tests/bug72681.phpt b/ext/session/tests/bug72681.phpt
new file mode 100644
index 0000000000..ceca6ecc33
--- /dev/null
+++ b/ext/session/tests/bug72681.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #72681: PHP Session Data Injection Vulnerability
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+ini_set('session.serialize_handler', 'php');
+session_start();
+$GLOBALS['ryat'] = $GLOBALS;
+$_SESSION['ryat'] = 'ryat|O:8:"stdClass":0:{}';
+session_write_close();
+session_start();
+var_dump($_SESSION);
+?>
+--EXPECT--
+array(0) {
+}
diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
index b32b845c73..cabfa9e7df 100644
--- a/ext/snmp/snmp.c
+++ b/ext/snmp/snmp.c
@@ -1008,7 +1008,7 @@ static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_qu
php_error_docref(NULL, E_WARNING, "Got empty OID array");
return FALSE;
}
- objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_P(oid)));
+ objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(Z_ARRVAL_P(oid)), 0);
if (objid_query->vars == NULL) {
php_error_docref(NULL, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno));
efree(objid_query->vars);
diff --git a/ext/standard/base64.c b/ext/standard/base64.c
index 64f21044e7..cd6bac0b3d 100644
--- a/ext/standard/base64.c
+++ b/ext/standard/base64.c
@@ -59,7 +59,7 @@ PHPAPI zend_string *php_base64_encode(const unsigned char *str, size_t length) /
unsigned char *p;
zend_string *result;
- result = zend_string_alloc(((length + 2) / 3) * 4 * sizeof(char), 0);
+ result = zend_string_safe_alloc(((length + 2) / 3), 4 * sizeof(char), 0, 0);
p = (unsigned char *)ZSTR_VAL(result);
while (length > 2) { /* keep going until we have less than 24 bits */
diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c
index 3b129ed5da..a5e00a6df9 100644
--- a/ext/standard/ftp_fopen_wrapper.c
+++ b/ext/standard/ftp_fopen_wrapper.c
@@ -188,7 +188,8 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char
/* get the response */
result = GET_FTP_RESULT(stream);
if (result != 334) {
- use_ssl = 0;
+ php_stream_wrapper_log_error(wrapper, options, "Server doesn't support FTPS.");
+ goto connect_errexit;
} else {
/* we must reuse the old SSL session id */
/* if we talk to an old ftpd-ssl */
diff --git a/ext/standard/php_smart_string.h b/ext/standard/php_smart_string.h
index 58c319a5a5..7038cff9bb 100644
--- a/ext/standard/php_smart_string.h
+++ b/ext/standard/php_smart_string.h
@@ -52,19 +52,22 @@
#define SMART_STRING_DO_REALLOC(d, what) \
(d)->c = SMART_STRING_REALLOC((d)->c, (d)->a + 1, (what))
-#define smart_string_alloc4(d, n, what, newlen) do { \
+#define smart_string_alloc4(d, n, what, newlen) do { \
if (!(d)->c) { \
(d)->len = 0; \
newlen = (n); \
- (d)->a = newlen < SMART_STRING_START_SIZE \
- ? SMART_STRING_START_SIZE \
- : newlen + SMART_STRING_PREALLOC; \
- SMART_STRING_DO_REALLOC(d, what); \
+ (d)->a = newlen < SMART_STRING_START_SIZE \
+ ? SMART_STRING_START_SIZE \
+ : newlen + SMART_STRING_PREALLOC; \
+ SMART_STRING_DO_REALLOC(d, what); \
} else { \
+ if(UNEXPECTED(n > SIZE_MAX - (d)->len)) { \
+ zend_error(E_ERROR, "String size overflow"); \
+ } \
newlen = (d)->len + (n); \
if (newlen >= (d)->a) { \
- (d)->a = newlen + SMART_STRING_PREALLOC; \
- SMART_STRING_DO_REALLOC(d, what); \
+ (d)->a = newlen + SMART_STRING_PREALLOC; \
+ SMART_STRING_DO_REALLOC(d, what); \
} \
} \
} while (0)
diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c
index a55b1e5edc..be352cbf80 100644
--- a/ext/standard/quot_print.c
+++ b/ext/standard/quot_print.c
@@ -275,7 +275,7 @@ PHP_FUNCTION(quoted_printable_encode)
RETURN_EMPTY_STRING();
}
- new_str = php_quot_print_encode((unsigned char *)ZSTR_VAL(str), (size_t)ZSTR_LEN(str));
+ new_str = php_quot_print_encode((unsigned char *)ZSTR_VAL(str), ZSTR_LEN(str));
RETURN_STR(new_str);
}
/* }}} */
diff --git a/ext/standard/tests/serialize/bug72663.phpt b/ext/standard/tests/serialize/bug72663.phpt
new file mode 100644
index 0000000000..c50591ca96
--- /dev/null
+++ b/ext/standard/tests/serialize/bug72663.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Bug #72663 (1): Don't call __destruct if __wakeup not called or fails
+--FILE--
+<?php
+
+class Test1 {
+ public function __wakeup() {
+ echo "Wakeup\n";
+ }
+ public function __destruct() {
+ echo "Dtor\n";
+ }
+}
+
+class Test2 {
+ public function __wakeup() {
+ throw new Exception('Unserialization forbidden');
+ }
+ public function __destruct() {
+ echo "Dtor\n";
+ }
+}
+
+// Unserialize object with error in properties
+$s = 'O:5:"Test1":1:{s:10:"";}';
+var_dump(unserialize($s));
+
+// Variation: Object is turned into a reference
+$s = 'O:5:"Test1":2:{i:0;R:1;s:10:"";}';
+var_dump(unserialize($s));
+
+// Unserialize object with throwing __wakeup
+$s = 'O:5:"Test2":0:{}';
+try {
+ var_dump(unserialize($s));
+} catch (Exception $e) {
+ echo "Caught\n";
+}
+//
+// Variation: Object is turned into a reference
+$s = 'O:5:"Test2":1:{i:0;R:1;}';
+try {
+ var_dump(unserialize($s));
+} catch (Exception $e) {
+ echo "Caught\n";
+}
+
+?>
+--EXPECTF--
+Notice: unserialize(): Error at offset 17 of 24 bytes in %s on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 25 of 32 bytes in %s on line %d
+bool(false)
+Caught
+Caught
diff --git a/ext/standard/tests/serialize/bug72663_2.phpt b/ext/standard/tests/serialize/bug72663_2.phpt
new file mode 100644
index 0000000000..8825dc5efc
--- /dev/null
+++ b/ext/standard/tests/serialize/bug72663_2.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #72663 (2): Don't allow references into failed unserialize
+--FILE--
+<?php
+
+class obj implements Serializable {
+ public $data;
+ function serialize() {
+ return serialize($this->data);
+ }
+ function unserialize($data) {
+ $this->data = unserialize($data);
+ }
+}
+
+$inner = 'a:1:{i:0;O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:4;}';
+$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}';
+var_dump(unserialize($exploit));
+
+?>
+--EXPECTF--
+Notice: unserialize(): Unexpected end of serialized data in %s on line %d
+
+Notice: unserialize(): Error at offset 46 of 47 bytes in %s on line %d
+
+Notice: unserialize(): Error at offset 79 of 80 bytes in %s on line %d
+bool(false)
diff --git a/ext/standard/tests/serialize/bug72663_3.phpt b/ext/standard/tests/serialize/bug72663_3.phpt
new file mode 100644
index 0000000000..37d67706f2
--- /dev/null
+++ b/ext/standard/tests/serialize/bug72663_3.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #72663 (3): If unserialization fails, don't initialize the session with the result
+--SKIPIF--
+<?php if (!extension_loaded('session')) die('skip Session extension required'); ?>
+--INI--
+session.serialize_handler=php_serialize
+--FILE--
+<?php
+session_start();
+$sess = 'O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:1;}';
+session_decode($sess);
+var_dump($_SESSION);
+?>
+--EXPECTF--
+Notice: session_decode(): Unexpected end of serialized data in %s on line %d
+array(0) {
+}
diff --git a/ext/standard/tests/streams/bug72853.phpt b/ext/standard/tests/streams/bug72853.phpt
new file mode 100644
index 0000000000..48bd60e7a6
--- /dev/null
+++ b/ext/standard/tests/streams/bug72853.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Bug #72853 (stream_set_blocking doesn't work)
+--SKIPIF--
+<?php
+if(substr(PHP_OS, 0, 3) == 'WIN' ) {
+ die('skip not for windows');
+}
+?>
+--FILE--
+<?php
+
+$descs = array(
+ 0 => array('pipe', 'r'), // stdin
+ 1 => array('pipe', 'w'), // stdout
+);
+
+$p = proc_open("ls", $descs, $pipes, '.', NULL, NULL);
+
+stream_set_blocking($pipes[1], false);
+var_dump(stream_get_meta_data($pipes[1]));
+stream_set_blocking($pipes[1], true);
+while ($outs = fgets($pipes[1], 1024)) {
+}
+var_dump(stream_get_meta_data($pipes[1]));
+proc_close($p);
+?>
+--EXPECTF--
+array(7) {
+ ["timed_out"]=>
+ bool(false)
+ ["blocked"]=>
+ bool(false)
+ ["eof"]=>
+ bool(false)
+ ["stream_type"]=>
+ string(5) "STDIO"
+ ["mode"]=>
+ string(1) "r"
+ ["unread_bytes"]=>
+ int(0)
+ ["seekable"]=>
+ bool(false)
+}
+array(7) {
+ ["timed_out"]=>
+ bool(false)
+ ["blocked"]=>
+ bool(true)
+ ["eof"]=>
+ bool(true)
+ ["stream_type"]=>
+ string(5) "STDIO"
+ ["mode"]=>
+ string(1) "r"
+ ["unread_bytes"]=>
+ int(0)
+ ["seekable"]=>
+ bool(false)
+}
diff --git a/ext/standard/tests/strings/bug70436.phpt b/ext/standard/tests/strings/bug70436.phpt
new file mode 100644
index 0000000000..c62e468726
--- /dev/null
+++ b/ext/standard/tests/strings/bug70436.phpt
@@ -0,0 +1,65 @@
+--TEST--
+Bug #70436: Use After Free Vulnerability in unserialize()
+--FILE--
+<?php
+
+class obj implements Serializable
+{
+ var $data;
+
+ function serialize()
+ {
+ return serialize($this->data);
+ }
+
+ function unserialize($data)
+ {
+ $this->data = unserialize($data);
+ }
+}
+
+$fakezval = ptr2str(1122334455);
+$fakezval .= ptr2str(0);
+$fakezval .= "\x00\x00\x00\x00";
+$fakezval .= "\x01";
+$fakezval .= "\x00";
+$fakezval .= "\x00\x00";
+
+$inner = 'C:3:"obj":3:{ryat';
+$exploit = 'a:4:{i:0;i:1;i:1;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:2;s:'.strlen($fakezval).':"'.$fakezval.'";i:3;R:5;}';
+
+$data = unserialize($exploit);
+
+var_dump($data);
+
+function ptr2str($ptr)
+{
+ $out = '';
+
+ for ($i = 0; $i < 8; $i++) {
+ $out .= chr($ptr & 0xff);
+ $ptr >>= 8;
+ }
+
+ return $out;
+}
+?>
+DONE
+--EXPECTF--
+Notice: unserialize(): Error at offset 0 of 3 bytes in %sbug70436.php on line %d
+
+Notice: unserialize(): Error at offset 17 of 17 bytes in %sbug70436.php on line %d
+array(4) {
+ [0]=>
+ int(1)
+ [1]=>
+ object(obj)#%d (1) {
+ ["data"]=>
+ bool(false)
+ }
+ [2]=>
+ string(24) "%s"
+ [3]=>
+ bool(false)
+}
+DONE \ No newline at end of file
diff --git a/ext/standard/tests/strings/bug72663.phpt b/ext/standard/tests/strings/bug72663.phpt
new file mode 100644
index 0000000000..e61f939d4d
--- /dev/null
+++ b/ext/standard/tests/strings/bug72663.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
+--FILE--
+<?php
+class obj implements Serializable {
+ var $data;
+ function serialize() {
+ return serialize($this->data);
+ }
+ function unserialize($data) {
+ $this->data = unserialize($data);
+ }
+}
+
+$inner = 'a:1:{i:0;O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:4;}';
+$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}';
+
+$data = unserialize($exploit);
+echo $data[1];
+?>
+DONE
+--EXPECTF--
+Notice: unserialize(): Unexpected end of serialized data in %sbug72663.php on line %d
+
+Notice: unserialize(): Error at offset 46 of 47 bytes in %sbug72663.php on line %d
+DONE \ No newline at end of file
diff --git a/ext/standard/tests/strings/bug72663_2.phpt b/ext/standard/tests/strings/bug72663_2.phpt
new file mode 100644
index 0000000000..ac605e9fd2
--- /dev/null
+++ b/ext/standard/tests/strings/bug72663_2.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
+--FILE--
+<?php
+
+ini_set('session.serialize_handler', 'php_serialize');
+session_start();
+$sess = 'O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:1;}';
+session_decode($sess);
+var_dump($_SESSION);
+?>
+DONE
+--EXPECTF--
+Notice: session_decode(): Unexpected end of serialized data in %sbug72663_2.php on line %d
+array(0) {
+}
+DONE \ No newline at end of file
diff --git a/ext/standard/tests/strings/bug72663_3.phpt b/ext/standard/tests/strings/bug72663_3.phpt
new file mode 100644
index 0000000000..f7d66efd17
--- /dev/null
+++ b/ext/standard/tests/strings/bug72663_3.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
+--XFAIL--
+Memory leak, TBF later.
+--FILE--
+<?php
+class obj {
+ var $ryat;
+ function __wakeup() {
+ $this->ryat = str_repeat('A', 0x112);
+ }
+}
+
+$poc = 'O:8:"stdClass":1:{i:0;O:3:"obj":1:{s:4:"ryat";R:1;';
+unserialize($poc);
+?>
+DONE
+--EXPECTF--
+Notice: unserialize(): Error at offset 51 of 50 bytes in %sbug72663_3.php on line %d
+DONE
diff --git a/ext/standard/uuencode.c b/ext/standard/uuencode.c
index e443337ec4..787569e430 100644
--- a/ext/standard/uuencode.c
+++ b/ext/standard/uuencode.c
@@ -71,8 +71,10 @@ PHPAPI zend_string *php_uuencode(char *src, size_t src_len) /* {{{ */
char *p, *s, *e, *ee;
zend_string *dest;
- /* encoded length is ~ 38% greater than the original */
- dest = zend_string_alloc((size_t)ceil(src_len * 1.38) + 46, 0);
+ /* encoded length is ~ 38% greater than the original
+ Use 1.5 for easier calculation.
+ */
+ dest = zend_string_safe_alloc(src_len/2, 3, 46, 0);
p = ZSTR_VAL(dest);
s = src;
e = src + src_len;
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c
index f96fdb40d6..d59231cf89 100644
--- a/ext/standard/var_unserializer.c
+++ b/ext/standard/var_unserializer.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.16 */
+/* Generated by re2c 0.13.5 */
#line 1 "ext/standard/var_unserializer.re"
/*
+----------------------------------------------------------------------+
@@ -336,6 +336,8 @@ static inline size_t parse_uiv(const unsigned char *p)
#define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes
#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
+
static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
{
while (elements-- > 0) {
@@ -344,7 +346,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
ZVAL_UNDEF(&key);
- if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) {
+ if (!php_var_unserialize_internal(&key, p, max, NULL, classes)) {
zval_dtor(&key);
return 0;
}
@@ -400,7 +402,7 @@ string_key:
}
}
- if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) {
+ if (!php_var_unserialize_internal(data, p, max, var_hash, classes)) {
zval_dtor(&key);
return 0;
}
@@ -490,23 +492,32 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
zval retval;
zval fname;
HashTable *ht;
+ zend_bool has_wakeup;
if (Z_TYPE_P(rval) != IS_OBJECT) {
return 0;
}
+ has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
+ && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
+
ht = Z_OBJPROP_P(rval);
zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
+ if (has_wakeup) {
+ ZVAL_DEREF(rval);
+ GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
+ }
return 0;
}
ZVAL_DEREF(rval);
- if (Z_OBJCE_P(rval) != PHP_IC_ENTRY &&
- zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) {
+ if (has_wakeup) {
ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1);
BG(serialize_lock)++;
- call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL);
+ if (call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
+ GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
+ }
BG(serialize_lock)--;
zval_dtor(&fname);
zval_dtor(&retval);
@@ -517,7 +528,6 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
}
return finish_nested_data(UNSERIALIZE_PASSTHRU);
-
}
#ifdef PHP_WIN32
# pragma optimize("", on)
@@ -529,9 +539,35 @@ PHPAPI int php_var_unserialize(zval *rval, const unsigned char **p, const unsign
return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU);
}
-
PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
{
+ var_entries *orig_var_entries = (*var_hash)->last;
+ zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
+ int result;
+
+ result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
+
+ if (!result) {
+ /* If the unserialization failed, mark all elements that have been added to var_hash
+ * as NULL. This will forbid their use by other unserialize() calls in the same
+ * unserialization context. */
+ var_entries *e = orig_var_entries;
+ zend_long s = orig_used_slots;
+ while (e) {
+ for (; s < e->used_slots; s++) {
+ e->data[s] = NULL;
+ }
+
+ e = e->next;
+ s = 0;
+ }
+ }
+
+ return result;
+}
+
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
+{
const unsigned char *cursor, *limit, *marker, *start;
zval *rval_ref;
@@ -549,7 +585,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
start = cursor;
-#line 553 "ext/standard/var_unserializer.c"
+#line 589 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
@@ -586,510 +622,111 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
+
if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
yych = *YYCURSOR;
switch (yych) {
case 'C':
- case 'O': goto yy4;
+ case 'O': goto yy13;
case 'N': goto yy5;
- case 'R': goto yy6;
- case 'S': goto yy7;
- case 'a': goto yy8;
- case 'b': goto yy9;
- case 'd': goto yy10;
- case 'i': goto yy11;
+ case 'R': goto yy2;
+ case 'S': goto yy10;
+ case 'a': goto yy11;
+ case 'b': goto yy6;
+ case 'd': goto yy8;
+ case 'i': goto yy7;
case 'o': goto yy12;
- case 'r': goto yy13;
- case 's': goto yy14;
- case '}': goto yy15;
- default: goto yy2;
+ case 'r': goto yy4;
+ case 's': goto yy9;
+ case '}': goto yy14;
+ default: goto yy16;
}
yy2:
- ++YYCURSOR;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yych == ':') goto yy95;
yy3:
-#line 919 "ext/standard/var_unserializer.re"
+#line 955 "ext/standard/var_unserializer.re"
{ return 0; }
-#line 613 "ext/standard/var_unserializer.c"
+#line 651 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy17;
+ if (yych == ':') goto yy89;
goto yy3;
yy5:
yych = *++YYCURSOR;
- if (yych == ';') goto yy19;
+ if (yych == ';') goto yy87;
goto yy3;
yy6:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy21;
+ if (yych == ':') goto yy83;
goto yy3;
yy7:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy22;
+ if (yych == ':') goto yy77;
goto yy3;
yy8:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy23;
+ if (yych == ':') goto yy53;
goto yy3;
yy9:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy24;
+ if (yych == ':') goto yy46;
goto yy3;
yy10:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy25;
+ if (yych == ':') goto yy39;
goto yy3;
yy11:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy26;
+ if (yych == ':') goto yy32;
goto yy3;
yy12:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy27;
+ if (yych == ':') goto yy25;
goto yy3;
yy13:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy28;
+ if (yych == ':') goto yy17;
goto yy3;
yy14:
- yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy29;
- goto yy3;
-yy15:
++YYCURSOR;
-#line 913 "ext/standard/var_unserializer.re"
+#line 949 "ext/standard/var_unserializer.re"
{
/* this is the case where we have less data than planned */
php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
return 0; /* not sure if it should be 0 or 1 here? */
}
-#line 666 "ext/standard/var_unserializer.c"
+#line 700 "ext/standard/var_unserializer.c"
+yy16:
+ yych = *++YYCURSOR;
+ goto yy3;
yy17:
yych = *++YYCURSOR;
if (yybm[0+yych] & 128) {
- goto yy31;
+ goto yy20;
}
- if (yych == '+') goto yy30;
+ if (yych == '+') goto yy19;
yy18:
YYCURSOR = YYMARKER;
goto yy3;
yy19:
- ++YYCURSOR;
-#line 608 "ext/standard/var_unserializer.re"
- {
- *p = YYCURSOR;
- ZVAL_NULL(rval);
- return 1;
-}
-#line 684 "ext/standard/var_unserializer.c"
-yy21:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych == '+') goto yy33;
- goto yy18;
- } else {
- if (yych <= '-') goto yy33;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy34;
- goto yy18;
- }
-yy22:
- yych = *++YYCURSOR;
- if (yych == '+') goto yy36;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy37;
- goto yy18;
-yy23:
- yych = *++YYCURSOR;
- if (yych == '+') goto yy39;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy40;
- goto yy18;
-yy24:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '1') goto yy42;
- goto yy18;
-yy25:
- yych = *++YYCURSOR;
- if (yych <= '/') {
- if (yych <= ',') {
- if (yych == '+') goto yy43;
- goto yy18;
- } else {
- if (yych <= '-') goto yy44;
- if (yych <= '.') goto yy45;
- goto yy18;
- }
- } else {
- if (yych <= 'I') {
- if (yych <= '9') goto yy46;
- if (yych <= 'H') goto yy18;
- goto yy48;
- } else {
- if (yych == 'N') goto yy49;
- goto yy18;
- }
- }
-yy26:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych == '+') goto yy50;
- goto yy18;
- } else {
- if (yych <= '-') goto yy50;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy51;
- goto yy18;
- }
-yy27:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych == '+') goto yy53;
- goto yy18;
- } else {
- if (yych <= '-') goto yy53;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy54;
- goto yy18;
- }
-yy28:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych == '+') goto yy56;
- goto yy18;
- } else {
- if (yych <= '-') goto yy56;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy57;
- goto yy18;
- }
-yy29:
- yych = *++YYCURSOR;
- if (yych == '+') goto yy59;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy60;
- goto yy18;
-yy30:
yych = *++YYCURSOR;
if (yybm[0+yych] & 128) {
- goto yy31;
+ goto yy20;
}
goto yy18;
-yy31:
+yy20:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
if (yybm[0+yych] & 128) {
- goto yy31;
- }
- if (yych <= '/') goto yy18;
- if (yych <= ':') goto yy62;
- goto yy18;
-yy33:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy34:
- ++YYCURSOR;
- if (YYLIMIT <= YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy34;
- if (yych == ';') goto yy63;
- goto yy18;
-yy36:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy37:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy37;
- if (yych <= ':') goto yy65;
- goto yy18;
-yy39:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy40:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy40;
- if (yych <= ':') goto yy66;
- goto yy18;
-yy42:
- yych = *++YYCURSOR;
- if (yych == ';') goto yy67;
- goto yy18;
-yy43:
- yych = *++YYCURSOR;
- if (yych == '.') goto yy45;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy46;
- goto yy18;
-yy44:
- yych = *++YYCURSOR;
- if (yych <= '/') {
- if (yych != '.') goto yy18;
- } else {
- if (yych <= '9') goto yy46;
- if (yych == 'I') goto yy48;
- goto yy18;
- }
-yy45:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy69;
- goto yy18;
-yy46:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
- yych = *YYCURSOR;
- if (yych <= ':') {
- if (yych <= '.') {
- if (yych <= '-') goto yy18;
- goto yy69;
- } else {
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy46;
- goto yy18;
- }
- } else {
- if (yych <= 'E') {
- if (yych <= ';') goto yy71;
- if (yych <= 'D') goto yy18;
- goto yy73;
- } else {
- if (yych == 'e') goto yy73;
- goto yy18;
- }
- }
-yy48:
- yych = *++YYCURSOR;
- if (yych == 'N') goto yy74;
- goto yy18;
-yy49:
- yych = *++YYCURSOR;
- if (yych == 'A') goto yy75;
- goto yy18;
-yy50:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy51:
- ++YYCURSOR;
- if (YYLIMIT <= YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy51;
- if (yych == ';') goto yy76;
- goto yy18;
-yy53:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy54:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy54;
- if (yych <= ':') goto yy78;
- goto yy18;
-yy56:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy57:
- ++YYCURSOR;
- if (YYLIMIT <= YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy57;
- if (yych == ';') goto yy79;
- goto yy18;
-yy59:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy60:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy60;
- if (yych <= ':') goto yy81;
- goto yy18;
-yy62:
- yych = *++YYCURSOR;
- if (yych == '"') goto yy82;
- goto yy18;
-yy63:
- ++YYCURSOR;
-#line 557 "ext/standard/var_unserializer.re"
- {
- zend_long id;
-
- *p = YYCURSOR;
- if (!var_hash) return 0;
-
- id = parse_iv(start + 2) - 1;
- if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
- return 0;
- }
-
- zval_ptr_dtor(rval);
- if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
- ZVAL_UNDEF(rval);
- return 1;
- }
- if (Z_ISREF_P(rval_ref)) {
- ZVAL_COPY(rval, rval_ref);
- } else {
- ZVAL_NEW_REF(rval_ref, rval_ref);
- ZVAL_COPY(rval, rval_ref);
- }
-
- return 1;
-}
-#line 960 "ext/standard/var_unserializer.c"
-yy65:
- yych = *++YYCURSOR;
- if (yych == '"') goto yy84;
- goto yy18;
-yy66:
- yych = *++YYCURSOR;
- if (yych == '{') goto yy86;
- goto yy18;
-yy67:
- ++YYCURSOR;
-#line 614 "ext/standard/var_unserializer.re"
- {
- *p = YYCURSOR;
- ZVAL_BOOL(rval, parse_iv(start + 2));
- return 1;
-}
-#line 977 "ext/standard/var_unserializer.c"
-yy69:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
- yych = *YYCURSOR;
- if (yych <= ';') {
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy69;
- if (yych <= ':') goto yy18;
- } else {
- if (yych <= 'E') {
- if (yych <= 'D') goto yy18;
- goto yy73;
- } else {
- if (yych == 'e') goto yy73;
- goto yy18;
- }
- }
-yy71:
- ++YYCURSOR;
-#line 662 "ext/standard/var_unserializer.re"
- {
-#if SIZEOF_ZEND_LONG == 4
-use_double:
-#endif
- *p = YYCURSOR;
- ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
- return 1;
-}
-#line 1006 "ext/standard/var_unserializer.c"
-yy73:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych == '+') goto yy88;
- goto yy18;
- } else {
- if (yych <= '-') goto yy88;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy89;
- goto yy18;
- }
-yy74:
- yych = *++YYCURSOR;
- if (yych == 'F') goto yy91;
- goto yy18;
-yy75:
- yych = *++YYCURSOR;
- if (yych == 'N') goto yy91;
- goto yy18;
-yy76:
- ++YYCURSOR;
-#line 620 "ext/standard/var_unserializer.re"
- {
-#if SIZEOF_ZEND_LONG == 4
- int digits = YYCURSOR - start - 3;
-
- if (start[2] == '-' || start[2] == '+') {
- digits--;
- }
-
- /* Use double for large zend_long values that were serialized on a 64-bit system */
- if (digits >= MAX_LENGTH_OF_LONG - 1) {
- if (digits == MAX_LENGTH_OF_LONG - 1) {
- int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
-
- if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
- goto use_double;
- }
- } else {
- goto use_double;
- }
- }
-#endif
- *p = YYCURSOR;
- ZVAL_LONG(rval, parse_iv(start + 2));
- return 1;
-}
-#line 1054 "ext/standard/var_unserializer.c"
-yy78:
- yych = *++YYCURSOR;
- if (yych == '"') goto yy92;
- goto yy18;
-yy79:
- ++YYCURSOR;
-#line 583 "ext/standard/var_unserializer.re"
- {
- zend_long id;
-
- *p = YYCURSOR;
- if (!var_hash) return 0;
-
- id = parse_iv(start + 2) - 1;
- if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
- return 0;
- }
-
- if (rval_ref == rval) {
- return 0;
- }
-
- if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
- ZVAL_UNDEF(rval);
- return 1;
+ goto yy20;
}
-
- ZVAL_COPY(rval, rval_ref);
-
- return 1;
-}
-#line 1086 "ext/standard/var_unserializer.c"
-yy81:
+ if (yych != ':') goto yy18;
yych = *++YYCURSOR;
- if (yych == '"') goto yy94;
- goto yy18;
-yy82:
+ if (yych != '"') goto yy18;
++YYCURSOR;
-#line 768 "ext/standard/var_unserializer.re"
+#line 804 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
zend_long elements;
@@ -1234,10 +871,105 @@ yy82:
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
-#line 1238 "ext/standard/var_unserializer.c"
-yy84:
+#line 875 "ext/standard/var_unserializer.c"
+yy25:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych != '+') goto yy18;
+ } else {
+ if (yych <= '-') goto yy26;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy27;
+ goto yy18;
+ }
+yy26:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy27:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy27;
+ if (yych >= ';') goto yy18;
+ yych = *++YYCURSOR;
+ if (yych != '"') goto yy18;
+ ++YYCURSOR;
+#line 797 "ext/standard/var_unserializer.re"
+ {
+ if (!var_hash) return 0;
+
+ return object_common2(UNSERIALIZE_PASSTHRU,
+ object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
+}
+#line 907 "ext/standard/var_unserializer.c"
+yy32:
+ yych = *++YYCURSOR;
+ if (yych == '+') goto yy33;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy34;
+ goto yy18;
+yy33:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy34:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy34;
+ if (yych >= ';') goto yy18;
+ yych = *++YYCURSOR;
+ if (yych != '{') goto yy18;
+ ++YYCURSOR;
+#line 773 "ext/standard/var_unserializer.re"
+ {
+ zend_long elements = parse_iv(start + 2);
+ /* use iv() not uiv() in order to check data range */
+ *p = YYCURSOR;
+ if (!var_hash) return 0;
+
+ if (elements < 0) {
+ return 0;
+ }
+
+ array_init_size(rval, elements);
+ if (elements) {
+ /* we can't convert from packed to hash during unserialization, because
+ reference to some zvals might be keept in var_hash (to support references) */
+ zend_hash_real_init(Z_ARRVAL_P(rval), 0);
+ }
+
+ if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
+ return 0;
+ }
+
+ return finish_nested_data(UNSERIALIZE_PASSTHRU);
+}
+#line 952 "ext/standard/var_unserializer.c"
+yy39:
+ yych = *++YYCURSOR;
+ if (yych == '+') goto yy40;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy41;
+ goto yy18;
+yy40:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy41:
++YYCURSOR;
-#line 703 "ext/standard/var_unserializer.re"
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy41;
+ if (yych >= ';') goto yy18;
+ yych = *++YYCURSOR;
+ if (yych != '"') goto yy18;
+ ++YYCURSOR;
+#line 739 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
zend_string *str;
@@ -1271,127 +1003,407 @@ yy84:
ZVAL_STR(rval, str);
return 1;
}
-#line 1275 "ext/standard/var_unserializer.c"
-yy86:
+#line 1007 "ext/standard/var_unserializer.c"
+yy46:
+ yych = *++YYCURSOR;
+ if (yych == '+') goto yy47;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy48;
+ goto yy18;
+yy47:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy48:
++YYCURSOR;
-#line 737 "ext/standard/var_unserializer.re"
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy48;
+ if (yych >= ';') goto yy18;
+ yych = *++YYCURSOR;
+ if (yych != '"') goto yy18;
+ ++YYCURSOR;
+#line 707 "ext/standard/var_unserializer.re"
{
- zend_long elements = parse_iv(start + 2);
- /* use iv() not uiv() in order to check data range */
- *p = YYCURSOR;
- if (!var_hash) return 0;
+ size_t len, maxlen;
+ char *str;
- if (elements < 0) {
+ len = parse_uiv(start + 2);
+ maxlen = max - YYCURSOR;
+ if (maxlen < len) {
+ *p = start + 2;
return 0;
}
- array_init_size(rval, elements);
- if (elements) {
- /* we can't convert from packed to hash during unserialization, because
- reference to some zvals might be keept in var_hash (to support references) */
- zend_hash_real_init(Z_ARRVAL_P(rval), 0);
+ str = (char*)YYCURSOR;
+
+ YYCURSOR += len;
+
+ if (*(YYCURSOR) != '"') {
+ *p = YYCURSOR;
+ return 0;
}
- if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
+ if (*(YYCURSOR + 1) != ';') {
+ *p = YYCURSOR + 1;
return 0;
}
- return finish_nested_data(UNSERIALIZE_PASSTHRU);
+ YYCURSOR += 2;
+ *p = YYCURSOR;
+
+ ZVAL_STRINGL(rval, str, len);
+ return 1;
+}
+#line 1060 "ext/standard/var_unserializer.c"
+yy53:
+ yych = *++YYCURSOR;
+ if (yych <= '/') {
+ if (yych <= ',') {
+ if (yych == '+') goto yy57;
+ goto yy18;
+ } else {
+ if (yych <= '-') goto yy55;
+ if (yych <= '.') goto yy60;
+ goto yy18;
+ }
+ } else {
+ if (yych <= 'I') {
+ if (yych <= '9') goto yy58;
+ if (yych <= 'H') goto yy18;
+ goto yy56;
+ } else {
+ if (yych != 'N') goto yy18;
+ }
+ }
+ yych = *++YYCURSOR;
+ if (yych == 'A') goto yy76;
+ goto yy18;
+yy55:
+ yych = *++YYCURSOR;
+ if (yych <= '/') {
+ if (yych == '.') goto yy60;
+ goto yy18;
+ } else {
+ if (yych <= '9') goto yy58;
+ if (yych != 'I') goto yy18;
+ }
+yy56:
+ yych = *++YYCURSOR;
+ if (yych == 'N') goto yy72;
+ goto yy18;
+yy57:
+ yych = *++YYCURSOR;
+ if (yych == '.') goto yy60;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy58:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ if (yych <= ':') {
+ if (yych <= '.') {
+ if (yych <= '-') goto yy18;
+ goto yy70;
+ } else {
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy58;
+ goto yy18;
+ }
+ } else {
+ if (yych <= 'E') {
+ if (yych <= ';') goto yy63;
+ if (yych <= 'D') goto yy18;
+ goto yy65;
+ } else {
+ if (yych == 'e') goto yy65;
+ goto yy18;
+ }
+ }
+yy60:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy61:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ if (yych <= ';') {
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy61;
+ if (yych <= ':') goto yy18;
+ } else {
+ if (yych <= 'E') {
+ if (yych <= 'D') goto yy18;
+ goto yy65;
+ } else {
+ if (yych == 'e') goto yy65;
+ goto yy18;
+ }
+ }
+yy63:
+ ++YYCURSOR;
+#line 698 "ext/standard/var_unserializer.re"
+ {
+#if SIZEOF_ZEND_LONG == 4
+use_double:
+#endif
+ *p = YYCURSOR;
+ ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
+ return 1;
}
-#line 1302 "ext/standard/var_unserializer.c"
-yy88:
+#line 1157 "ext/standard/var_unserializer.c"
+yy65:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych != '+') goto yy18;
+ } else {
+ if (yych <= '-') goto yy66;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy67;
+ goto yy18;
+ }
+yy66:
yych = *++YYCURSOR;
if (yych <= ',') {
- if (yych == '+') goto yy96;
+ if (yych == '+') goto yy69;
goto yy18;
} else {
- if (yych <= '-') goto yy96;
+ if (yych <= '-') goto yy69;
if (yych <= '/') goto yy18;
if (yych >= ':') goto yy18;
}
-yy89:
+yy67:
++YYCURSOR;
if (YYLIMIT <= YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy89;
- if (yych == ';') goto yy71;
+ if (yych <= '9') goto yy67;
+ if (yych == ';') goto yy63;
goto yy18;
-yy91:
+yy69:
yych = *++YYCURSOR;
- if (yych == ';') goto yy97;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy67;
goto yy18;
-yy92:
+yy70:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ if (yych <= ';') {
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy70;
+ if (yych <= ':') goto yy18;
+ goto yy63;
+ } else {
+ if (yych <= 'E') {
+ if (yych <= 'D') goto yy18;
+ goto yy65;
+ } else {
+ if (yych == 'e') goto yy65;
+ goto yy18;
+ }
+ }
+yy72:
+ yych = *++YYCURSOR;
+ if (yych != 'F') goto yy18;
+yy73:
+ yych = *++YYCURSOR;
+ if (yych != ';') goto yy18;
++YYCURSOR;
-#line 761 "ext/standard/var_unserializer.re"
+#line 682 "ext/standard/var_unserializer.re"
{
- if (!var_hash) return 0;
+ *p = YYCURSOR;
- return object_common2(UNSERIALIZE_PASSTHRU,
- object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
+ if (!strncmp((char*)start + 2, "NAN", 3)) {
+ ZVAL_DOUBLE(rval, php_get_nan());
+ } else if (!strncmp((char*)start + 2, "INF", 3)) {
+ ZVAL_DOUBLE(rval, php_get_inf());
+ } else if (!strncmp((char*)start + 2, "-INF", 4)) {
+ ZVAL_DOUBLE(rval, -php_get_inf());
+ } else {
+ ZVAL_NULL(rval);
+ }
+
+ return 1;
}
-#line 1334 "ext/standard/var_unserializer.c"
-yy94:
+#line 1232 "ext/standard/var_unserializer.c"
+yy76:
+ yych = *++YYCURSOR;
+ if (yych == 'N') goto yy73;
+ goto yy18;
+yy77:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych != '+') goto yy18;
+ } else {
+ if (yych <= '-') goto yy78;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy79;
+ goto yy18;
+ }
+yy78:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy79:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy79;
+ if (yych != ';') goto yy18;
++YYCURSOR;
-#line 671 "ext/standard/var_unserializer.re"
+#line 656 "ext/standard/var_unserializer.re"
{
- size_t len, maxlen;
- char *str;
+#if SIZEOF_ZEND_LONG == 4
+ int digits = YYCURSOR - start - 3;
- len = parse_uiv(start + 2);
- maxlen = max - YYCURSOR;
- if (maxlen < len) {
- *p = start + 2;
- return 0;
+ if (start[2] == '-' || start[2] == '+') {
+ digits--;
}
- str = (char*)YYCURSOR;
+ /* Use double for large zend_long values that were serialized on a 64-bit system */
+ if (digits >= MAX_LENGTH_OF_LONG - 1) {
+ if (digits == MAX_LENGTH_OF_LONG - 1) {
+ int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
- YYCURSOR += len;
+ if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
+ goto use_double;
+ }
+ } else {
+ goto use_double;
+ }
+ }
+#endif
+ *p = YYCURSOR;
+ ZVAL_LONG(rval, parse_iv(start + 2));
+ return 1;
+}
+#line 1285 "ext/standard/var_unserializer.c"
+yy83:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= '2') goto yy18;
+ yych = *++YYCURSOR;
+ if (yych != ';') goto yy18;
+ ++YYCURSOR;
+#line 650 "ext/standard/var_unserializer.re"
+ {
+ *p = YYCURSOR;
+ ZVAL_BOOL(rval, parse_iv(start + 2));
+ return 1;
+}
+#line 1299 "ext/standard/var_unserializer.c"
+yy87:
+ ++YYCURSOR;
+#line 644 "ext/standard/var_unserializer.re"
+ {
+ *p = YYCURSOR;
+ ZVAL_NULL(rval);
+ return 1;
+}
+#line 1308 "ext/standard/var_unserializer.c"
+yy89:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych != '+') goto yy18;
+ } else {
+ if (yych <= '-') goto yy90;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy91;
+ goto yy18;
+ }
+yy90:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy91:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy91;
+ if (yych != ';') goto yy18;
+ ++YYCURSOR;
+#line 619 "ext/standard/var_unserializer.re"
+ {
+ zend_long id;
- if (*(YYCURSOR) != '"') {
- *p = YYCURSOR;
+ *p = YYCURSOR;
+ if (!var_hash) return 0;
+
+ id = parse_iv(start + 2) - 1;
+ if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
return 0;
}
- if (*(YYCURSOR + 1) != ';') {
- *p = YYCURSOR + 1;
+ if (rval_ref == rval) {
return 0;
}
- YYCURSOR += 2;
- *p = YYCURSOR;
+ if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+ ZVAL_UNDEF(rval);
+ return 1;
+ }
+
+ ZVAL_COPY(rval, rval_ref);
- ZVAL_STRINGL(rval, str, len);
return 1;
}
-#line 1369 "ext/standard/var_unserializer.c"
+#line 1356 "ext/standard/var_unserializer.c"
+yy95:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych != '+') goto yy18;
+ } else {
+ if (yych <= '-') goto yy96;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy97;
+ goto yy18;
+ }
yy96:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy89;
- goto yy18;
+ if (yych >= ':') goto yy18;
yy97:
++YYCURSOR;
-#line 646 "ext/standard/var_unserializer.re"
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy97;
+ if (yych != ';') goto yy18;
+ ++YYCURSOR;
+#line 593 "ext/standard/var_unserializer.re"
{
- *p = YYCURSOR;
+ zend_long id;
- if (!strncmp((char*)start + 2, "NAN", 3)) {
- ZVAL_DOUBLE(rval, php_get_nan());
- } else if (!strncmp((char*)start + 2, "INF", 3)) {
- ZVAL_DOUBLE(rval, php_get_inf());
- } else if (!strncmp((char*)start + 2, "-INF", 4)) {
- ZVAL_DOUBLE(rval, -php_get_inf());
+ *p = YYCURSOR;
+ if (!var_hash) return 0;
+
+ id = parse_iv(start + 2) - 1;
+ if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+ return 0;
+ }
+
+ zval_ptr_dtor(rval);
+ if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+ ZVAL_UNDEF(rval);
+ return 1;
+ }
+ if (Z_ISREF_P(rval_ref)) {
+ ZVAL_COPY(rval, rval_ref);
} else {
- ZVAL_NULL(rval);
+ ZVAL_NEW_REF(rval_ref, rval_ref);
+ ZVAL_COPY(rval, rval_ref);
}
return 1;
}
-#line 1393 "ext/standard/var_unserializer.c"
+#line 1405 "ext/standard/var_unserializer.c"
}
-#line 921 "ext/standard/var_unserializer.re"
+#line 957 "ext/standard/var_unserializer.re"
return 0;
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re
index 4ba8f75f3b..90762a41d0 100644
--- a/ext/standard/var_unserializer.re
+++ b/ext/standard/var_unserializer.re
@@ -340,6 +340,8 @@ static inline size_t parse_uiv(const unsigned char *p)
#define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes
#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
+
static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
{
while (elements-- > 0) {
@@ -348,7 +350,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
ZVAL_UNDEF(&key);
- if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) {
+ if (!php_var_unserialize_internal(&key, p, max, NULL, classes)) {
zval_dtor(&key);
return 0;
}
@@ -404,7 +406,7 @@ string_key:
}
}
- if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) {
+ if (!php_var_unserialize_internal(data, p, max, var_hash, classes)) {
zval_dtor(&key);
return 0;
}
@@ -494,23 +496,32 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
zval retval;
zval fname;
HashTable *ht;
+ zend_bool has_wakeup;
if (Z_TYPE_P(rval) != IS_OBJECT) {
return 0;
}
+ has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
+ && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
+
ht = Z_OBJPROP_P(rval);
zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
+ if (has_wakeup) {
+ ZVAL_DEREF(rval);
+ GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
+ }
return 0;
}
ZVAL_DEREF(rval);
- if (Z_OBJCE_P(rval) != PHP_IC_ENTRY &&
- zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) {
+ if (has_wakeup) {
ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1);
BG(serialize_lock)++;
- call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL);
+ if (call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
+ GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
+ }
BG(serialize_lock)--;
zval_dtor(&fname);
zval_dtor(&retval);
@@ -521,7 +532,6 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
}
return finish_nested_data(UNSERIALIZE_PASSTHRU);
-
}
#ifdef PHP_WIN32
# pragma optimize("", on)
@@ -533,9 +543,35 @@ PHPAPI int php_var_unserialize(zval *rval, const unsigned char **p, const unsign
return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU);
}
-
PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
{
+ var_entries *orig_var_entries = (*var_hash)->last;
+ zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
+ int result;
+
+ result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
+
+ if (!result) {
+ /* If the unserialization failed, mark all elements that have been added to var_hash
+ * as NULL. This will forbid their use by other unserialize() calls in the same
+ * unserialization context. */
+ var_entries *e = orig_var_entries;
+ zend_long s = orig_used_slots;
+ while (e) {
+ for (; s < e->used_slots; s++) {
+ e->data[s] = NULL;
+ }
+
+ e = e->next;
+ s = 0;
+ }
+ }
+
+ return result;
+}
+
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
+{
const unsigned char *cursor, *limit, *marker, *start;
zval *rval_ref;
diff --git a/ext/wddx/tests/bug72142.phpt b/ext/wddx/tests/bug72142.phpt
index 3976bb2554..0c93ecc970 100644
--- a/ext/wddx/tests/bug72142.phpt
+++ b/ext/wddx/tests/bug72142.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #72142: WDDX Packet Injection Vulnerability in wddx_serialize_value()
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
--FILE--
<?php
diff --git a/ext/wddx/tests/bug72749.phpt b/ext/wddx/tests/bug72749.phpt
new file mode 100644
index 0000000000..ee17d0f229
--- /dev/null
+++ b/ext/wddx/tests/bug72749.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #72749: wddx_deserialize allows illegal memory access
+--SKIPIF--
+<?php
+if (!extension_loaded('wddx')) {
+ die('skip. wddx not available');
+}
+?>
+--FILE--
+<?php
+$xml = <<<XML
+<?xml version='1.0'?>
+<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
+<wddxPacket version='1.0'>
+<header/>
+ <data>
+ <struct>
+ <var name='aDateTime3'>
+ <dateTime>2\r2004-09-10T05:52:49+00</dateTime>
+ </var>
+ </struct>
+ </data>
+</wddxPacket>
+XML;
+
+$array = wddx_deserialize($xml);
+var_dump($array);
+?>
+--EXPECT--
+array(1) {
+ ["aDateTime3"]=>
+ string(24) "2
+2004-09-10T05:52:49+00"
+}
diff --git a/ext/wddx/tests/bug72750.phpt b/ext/wddx/tests/bug72750.phpt
new file mode 100644
index 0000000000..3a6794df28
--- /dev/null
+++ b/ext/wddx/tests/bug72750.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #72750: wddx_deserialize null dereference
+--SKIPIF--
+<?php
+if (!extension_loaded('wddx')) {
+ die('skip. wddx not available');
+}
+?>
+--FILE--
+<?php
+
+$xml = <<< XML
+<?xml version='1.0'?>
+<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
+<wddxPacket version='1.0'>
+<header/>
+ <data>
+ <struct>
+ <var name='aBinary'>
+ <binary length='11'>\\tYmluYXJRhdGE=</binary>
+ </var>
+ </struct>
+ </data>
+</wddxPacket>
+XML;
+
+$array = wddx_deserialize($xml);
+var_dump($array);
+?>
+--EXPECT--
+array(1) {
+ ["aBinary"]=>
+ string(0) ""
+}
diff --git a/ext/wddx/tests/bug72790.phpt b/ext/wddx/tests/bug72790.phpt
new file mode 100644
index 0000000000..5bc4478401
--- /dev/null
+++ b/ext/wddx/tests/bug72790.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug 72790: wddx_deserialize null dereference with invalid xml
+--SKIPIF--
+<?php
+if (!extension_loaded('wddx')) {
+ die('skip. wddx not available');
+}
+?>
+--FILE--
+<?php
+
+$xml = <<< XML
+<?xml version='1.0' ?>
+<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
+<wddxPacket version='1.0'>
+ |array>
+ <var name="XXXX">
+ <boolean value="this">
+ </boolean>
+ </var>
+ <var name="YYYY">
+ <var name="UUUU">
+ <var name="EZEZ">
+ </var>
+ </var>
+ </var>
+ </array>
+</wddxPacket>
+XML;
+
+$array = wddx_deserialize($xml);
+var_dump($array);
+?>
+--EXPECTF--
+Notice: Undefined variable: array in %s%ebug72790.php on line %d
+NULL
diff --git a/ext/wddx/tests/bug72799.phpt b/ext/wddx/tests/bug72799.phpt
new file mode 100644
index 0000000000..53ac95bd6a
--- /dev/null
+++ b/ext/wddx/tests/bug72799.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #72799: wddx_deserialize null dereference in php_wddx_pop_element
+--SKIPIF--
+<?php
+if (!extension_loaded('wddx')) {
+ die('skip. wddx not available');
+}
+?>
+--FILE--
+<?php
+
+$xml = <<<XML
+<?xml version='1.0'?>
+<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
+<wddxPacket version="1.0">
+ <var name="XXXX">
+ <boolean value="1">
+ <dateTime>1998-06-12T04:32:12+00</dateTime>
+ </boolean>
+ </var>
+</wddxPacket>
+XML;
+
+$array = wddx_deserialize($xml);
+var_dump($array);
+?>
+--EXPECTF--
+Notice: Undefined variable: array in %s%ebug72799.php on line 16
+NULL
diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c
index d2171b47c3..2d68406be9 100644
--- a/ext/wddx/wddx.c
+++ b/ext/wddx/wddx.c
@@ -886,10 +886,10 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
if (Z_TYPE(ent1->data) == IS_UNDEF) {
if (stack->top > 1) {
stack->top--;
+ efree(ent1);
} else {
stack->done = 1;
}
- efree(ent1);
return;
}
@@ -897,7 +897,11 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
zend_string *new_str = php_base64_decode(
(unsigned char *)Z_STRVAL(ent1->data), Z_STRLEN(ent1->data));
zval_ptr_dtor(&ent1->data);
- ZVAL_STR(&ent1->data, new_str);
+ if (new_str) {
+ ZVAL_STR(&ent1->data, new_str);
+ } else {
+ ZVAL_EMPTY_STRING(&ent1->data);
+ }
}
/* Call __wakeup() method on the object. */
@@ -917,7 +921,7 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
wddx_stack_top(stack, (void**)&ent2);
/* if non-existent field */
- if (ent2->type == ST_FIELD && Z_ISUNDEF(ent2->data)) {
+ if (Z_ISUNDEF(ent2->data)) {
zval_ptr_dtor(&ent1->data);
efree(ent1);
return;
@@ -1030,16 +1034,23 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
case ST_DATETIME: {
char *tmp;
- tmp = emalloc(len + 1);
- memcpy(tmp, (char *)s, len);
+ if (Z_TYPE(ent->data) == IS_STRING) {
+ tmp = safe_emalloc(Z_STRLEN(ent->data), 1, (size_t)len + 1);
+ memcpy(tmp, Z_STRVAL(ent->data), Z_STRLEN(ent->data));
+ memcpy(tmp + Z_STRLEN(ent->data), s, len);
+ len += Z_STRLEN(ent->data);
+ zval_dtor(&ent->data);
+ } else {
+ tmp = emalloc(len + 1);
+ memcpy(tmp, (char *)s, len);
+ }
tmp[len] = '\0';
- Z_LVAL(ent->data) = php_parse_date(tmp, NULL);
+ ZVAL_LONG(&ent->data, php_parse_date(tmp, NULL));
/* date out of range < 1969 or > 2038 */
if (Z_LVAL(ent->data) == -1) {
- ZVAL_STRINGL(&ent->data, (char *)s, len);
+ ZVAL_STRINGL(&ent->data, (char *)tmp, len);
}
- efree(tmp);
}
break;
@@ -1073,8 +1084,12 @@ int php_wddx_deserialize_ex(const char *value, size_t vallen, zval *return_value
if (stack.top == 1) {
wddx_stack_top(&stack, (void**)&ent);
- ZVAL_COPY(return_value, &ent->data);
- retval = SUCCESS;
+ if (Z_ISUNDEF(ent->data)) {
+ retval = FAILURE;
+ } else {
+ ZVAL_COPY(return_value, &ent->data);
+ retval = SUCCESS;
+ }
} else {
retval = FAILURE;
}
diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c
index c3646ee0fd..bf78db3bdf 100644
--- a/main/fopen_wrappers.c
+++ b/main/fopen_wrappers.c
@@ -144,7 +144,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
char *path_file;
int resolved_basedir_len;
int resolved_name_len;
- int path_len;
+ size_t path_len;
int nesting_level = 0;
/* Special case basedir==".": Use script-directory */
@@ -153,7 +153,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir));
}
- path_len = (int)strlen(path);
+ path_len = strlen(path);
if (path_len > (MAXPATHLEN - 1)) {
/* empty and too long paths are invalid */
return -1;
@@ -164,7 +164,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
return -1;
}
- path_len = (int)strlen(resolved_name);
+ path_len = strlen(resolved_name);
memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
while (VCWD_REALPATH(path_tmp, resolved_name) == NULL) {
diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c
index 7ede3718b5..69dd25acc5 100644
--- a/main/streams/plain_wrapper.c
+++ b/main/streams/plain_wrapper.c
@@ -857,7 +857,19 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
data->is_pipe_blocking = value;
return PHP_STREAM_OPTION_RETURN_OK;
#endif
+ case PHP_STREAM_OPTION_META_DATA_API:
+ if (fd == -1)
+ return -1;
+#ifdef O_NONBLOCK
+ flags = fcntl(fd, F_GETFL, 0);
+ add_assoc_bool((zval*)ptrparam, "timed_out", 0);
+ add_assoc_bool((zval*)ptrparam, "blocked", (flags & O_NONBLOCK)? 0 : 1);
+ add_assoc_bool((zval*)ptrparam, "eof", stream->eof);
+
+ return PHP_STREAM_OPTION_RETURN_OK;
+#endif
+ return -1;
default:
return PHP_STREAM_OPTION_RETURN_NOTIMPL;
}