Skip to content

Instantly share code, notes, and snippets.

/72663.diff Secret

Created Aug 7, 2016
Embed
What would you like to do?
Patch for 72663
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
You can’t perform that action at this time.