/72663.diff Secret
Created
August 7, 2016 22:34
Patch for 72663
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit a309b6eb04310119d55ec00e64496ec7b78d6132 | |
Author: Stanislav Malyshev <stas@php.net> | |
Date: Sun Aug 7 15:33:29 2016 -0700 | |
Improve fix for #72663 | |
diff --git a/ext/standard/tests/strings/bug72663_3.phpt b/ext/standard/tests/strings/bug72663_3.phpt | |
new file mode 100644 | |
index 0000000..e336bc8 | |
--- /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 1d459ae..c8e6f8a 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. */ | |
+ 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 c1c18c9..11b93c5 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. */ | |
+ 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); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment