diff options
author | Stanislav Malyshev <stas@php.net> | 2016-08-07 15:33:29 -0700 |
---|---|---|
committer | Ferenc Kovacs <tyra3l@gmail.com> | 2016-08-18 12:51:50 +0200 |
commit | 75c0dbdd028ffa20eae5cf3a2fae194961464b8b (patch) | |
tree | ac71288491395bdecf7ec161ee2d5625b7a8fead | |
parent | 27fe2b42fc4a0e82b30dba11e177611ac6a88bf5 (diff) | |
download | php-git-75c0dbdd028ffa20eae5cf3a2fae194961464b8b.tar.gz |
Improve fix for #72663
-rw-r--r-- | ext/standard/tests/strings/bug72663_3.phpt | 18 | ||||
-rw-r--r-- | ext/standard/var_unserializer.c | 68 | ||||
-rw-r--r-- | ext/standard/var_unserializer.re | 8 |
3 files changed, 62 insertions, 32 deletions
diff --git a/ext/standard/tests/strings/bug72663_3.phpt b/ext/standard/tests/strings/bug72663_3.phpt new file mode 100644 index 0000000000..e336bc868d --- /dev/null +++ b/ext/standard/tests/strings/bug72663_3.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization +--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
\ No newline at end of file diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 1d459ae008..c8e6f8a0ca 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -435,11 +435,17 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { /* We've got partially constructed object on our hands here. Wipe it. */ - zend_hash_clean(Z_OBJPROP_PP(rval)); + if(Z_TYPE_PP(rval) == IS_OBJECT) { + zend_hash_clean(Z_OBJPROP_PP(rval)); + } ZVAL_NULL(*rval); return 0; } + if (Z_TYPE_PP(rval) != IS_OBJECT) { + return 0; + } + if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY && zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) { INIT_PZVAL(&fname); @@ -485,7 +491,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 489 "ext/standard/var_unserializer.c" +#line 495 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -545,9 +551,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 854 "ext/standard/var_unserializer.re" +#line 860 "ext/standard/var_unserializer.re" { return 0; } -#line 551 "ext/standard/var_unserializer.c" +#line 557 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -590,13 +596,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 848 "ext/standard/var_unserializer.re" +#line 854 "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 600 "ext/standard/var_unserializer.c" +#line 606 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -627,7 +633,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 701 "ext/standard/var_unserializer.re" +#line 707 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -774,7 +780,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 778 "ext/standard/var_unserializer.c" +#line 784 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -799,7 +805,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 692 "ext/standard/var_unserializer.re" +#line 698 "ext/standard/var_unserializer.re" { if (!var_hash) return 0; @@ -808,7 +814,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 812 "ext/standard/var_unserializer.c" +#line 818 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -829,7 +835,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 671 "ext/standard/var_unserializer.re" +#line 677 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -850,7 +856,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 854 "ext/standard/var_unserializer.c" +#line 860 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -871,7 +877,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 636 "ext/standard/var_unserializer.re" +#line 642 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -906,7 +912,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 910 "ext/standard/var_unserializer.c" +#line 916 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -927,7 +933,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 603 "ext/standard/var_unserializer.re" +#line 609 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -960,7 +966,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 964 "ext/standard/var_unserializer.c" +#line 970 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1048,7 +1054,7 @@ yy61: } yy63: ++YYCURSOR; -#line 593 "ext/standard/var_unserializer.re" +#line 599 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1058,7 +1064,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1062 "ext/standard/var_unserializer.c" +#line 1068 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1117,7 +1123,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 578 "ext/standard/var_unserializer.re" +#line 584 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1132,7 +1138,7 @@ yy73: return 1; } -#line 1136 "ext/standard/var_unserializer.c" +#line 1142 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1159,7 +1165,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 551 "ext/standard/var_unserializer.re" +#line 557 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1186,7 +1192,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1190 "ext/standard/var_unserializer.c" +#line 1196 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1194,24 +1200,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 544 "ext/standard/var_unserializer.re" +#line 550 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1205 "ext/standard/var_unserializer.c" +#line 1211 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 537 "ext/standard/var_unserializer.re" +#line 543 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1215 "ext/standard/var_unserializer.c" +#line 1221 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1234,7 +1240,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 514 "ext/standard/var_unserializer.re" +#line 520 "ext/standard/var_unserializer.re" { long id; @@ -1257,7 +1263,7 @@ yy91: return 1; } -#line 1261 "ext/standard/var_unserializer.c" +#line 1267 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1280,7 +1286,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 493 "ext/standard/var_unserializer.re" +#line 499 "ext/standard/var_unserializer.re" { long id; @@ -1301,9 +1307,9 @@ yy97: return 1; } -#line 1305 "ext/standard/var_unserializer.c" +#line 1311 "ext/standard/var_unserializer.c" } -#line 856 "ext/standard/var_unserializer.re" +#line 862 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index c1c18c9391..11b93c522b 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -439,11 +439,17 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { /* We've got partially constructed object on our hands here. Wipe it. */ - zend_hash_clean(Z_OBJPROP_PP(rval)); + if(Z_TYPE_PP(rval) == IS_OBJECT) { + zend_hash_clean(Z_OBJPROP_PP(rval)); + } ZVAL_NULL(*rval); return 0; } + if (Z_TYPE_PP(rval) != IS_OBJECT) { + return 0; + } + if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY && zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) { INIT_PZVAL(&fname); |