diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 56c47b7f84ec6..cdc0b69fbf290 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -215,7 +215,7 @@ ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, } zend_end_try(); } } - + /* re-read the object from the object store as the store might have been reallocated in the dtor */ obj = &EG(objects_store).object_buckets[handle].bucket.obj; @@ -306,8 +306,8 @@ ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC) { zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle]; - - obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);; + + obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject); obj_bucket->destructor_called = 1; } diff --git a/ext/standard/tests/serialize/bug73052.phpt b/ext/standard/tests/serialize/bug73052.phpt new file mode 100644 index 0000000000000..63b484bf14d25 --- /dev/null +++ b/ext/standard/tests/serialize/bug73052.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #73052: Memory Corruption in During Deserialized-object Destruction +--FILE-- +ryat = null; + } +} + +$poc = 'O:3:"obj":1:{'; +var_dump(unserialize($poc)); +?> +--EXPECTF-- +Notice: unserialize(): Error at offset 13 of 13 bytes in %sbug73052.php on line %d +bool(false) diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index c8e6f8a0ca9aa..549149267eb2f 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -437,6 +437,7 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) /* We've got partially constructed object on our hands here. Wipe it. */ if(Z_TYPE_PP(rval) == IS_OBJECT) { zend_hash_clean(Z_OBJPROP_PP(rval)); + zend_object_store_ctor_failed(*rval TSRMLS_CC); } ZVAL_NULL(*rval); return 0; @@ -491,7 +492,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 495 "ext/standard/var_unserializer.c" +#line 496 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -551,9 +552,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 860 "ext/standard/var_unserializer.re" +#line 861 "ext/standard/var_unserializer.re" { return 0; } -#line 557 "ext/standard/var_unserializer.c" +#line 558 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -596,13 +597,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) goto yy3; yy14: ++YYCURSOR; -#line 854 "ext/standard/var_unserializer.re" +#line 855 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 606 "ext/standard/var_unserializer.c" +#line 607 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -633,7 +634,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 707 "ext/standard/var_unserializer.re" +#line 708 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -780,7 +781,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 784 "ext/standard/var_unserializer.c" +#line 785 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -805,7 +806,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 698 "ext/standard/var_unserializer.re" +#line 699 "ext/standard/var_unserializer.re" { if (!var_hash) return 0; @@ -814,7 +815,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 818 "ext/standard/var_unserializer.c" +#line 819 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -835,7 +836,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 677 "ext/standard/var_unserializer.re" +#line 678 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -856,7 +857,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 860 "ext/standard/var_unserializer.c" +#line 861 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -877,7 +878,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 642 "ext/standard/var_unserializer.re" +#line 643 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -912,7 +913,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 916 "ext/standard/var_unserializer.c" +#line 917 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -933,7 +934,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 609 "ext/standard/var_unserializer.re" +#line 610 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -966,7 +967,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 970 "ext/standard/var_unserializer.c" +#line 971 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1054,7 +1055,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) } yy63: ++YYCURSOR; -#line 599 "ext/standard/var_unserializer.re" +#line 600 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1064,7 +1065,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1068 "ext/standard/var_unserializer.c" +#line 1069 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1123,7 +1124,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 584 "ext/standard/var_unserializer.re" +#line 585 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1138,7 +1139,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) return 1; } -#line 1142 "ext/standard/var_unserializer.c" +#line 1143 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1165,7 +1166,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 557 "ext/standard/var_unserializer.re" +#line 558 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1192,7 +1193,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1196 "ext/standard/var_unserializer.c" +#line 1197 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1200,24 +1201,24 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 550 "ext/standard/var_unserializer.re" +#line 551 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1211 "ext/standard/var_unserializer.c" +#line 1212 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 543 "ext/standard/var_unserializer.re" +#line 544 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1221 "ext/standard/var_unserializer.c" +#line 1222 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1240,7 +1241,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 520 "ext/standard/var_unserializer.re" +#line 521 "ext/standard/var_unserializer.re" { long id; @@ -1263,7 +1264,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) return 1; } -#line 1267 "ext/standard/var_unserializer.c" +#line 1268 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1286,7 +1287,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 499 "ext/standard/var_unserializer.re" +#line 500 "ext/standard/var_unserializer.re" { long id; @@ -1307,9 +1308,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) return 1; } -#line 1311 "ext/standard/var_unserializer.c" +#line 1312 "ext/standard/var_unserializer.c" } -#line 862 "ext/standard/var_unserializer.re" +#line 863 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 11b93c522b226..ce84bf5eb40cc 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -441,6 +441,7 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) /* We've got partially constructed object on our hands here. Wipe it. */ if(Z_TYPE_PP(rval) == IS_OBJECT) { zend_hash_clean(Z_OBJPROP_PP(rval)); + zend_object_store_ctor_failed(*rval TSRMLS_CC); } ZVAL_NULL(*rval); return 0;