diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | ext/standard/tests/serialize/bug70213.phpt | 30 | ||||
-rw-r--r-- | ext/standard/var_unserializer.c | 32 | ||||
-rw-r--r-- | ext/standard/var_unserializer.re | 2 |
4 files changed, 53 insertions, 15 deletions
@@ -13,6 +13,10 @@ PHP NEWS . Reverted fix for bug #73530 (Unsetting result set may reset other result set). (cmb) +- Standard: + . Fixed bug #70213 (Unserialize context shared on double class lookup). + (Taoguang Chen) + 08 Dec 2016, PHP 5.6.29 - Mbstring: diff --git a/ext/standard/tests/serialize/bug70213.phpt b/ext/standard/tests/serialize/bug70213.phpt new file mode 100644 index 0000000000..c01d362be0 --- /dev/null +++ b/ext/standard/tests/serialize/bug70213.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #70213: Unserialize context shared on double class lookup +--FILE-- +<?php + +ini_set('unserialize_callback_func', 'evil'); + +function evil() { + function __autoload($arg) { + var_dump(unserialize('R:1;')); + } +} + +var_dump(unserialize('a:2:{i:0;i:42;i:1;O:4:"evil":0:{}}')); + +?> +--EXPECTF-- +Notice: unserialize(): Error at offset 4 of 4 bytes in %s on line %d +bool(false) + +Warning: unserialize(): Function evil() hasn't defined the class it was called for in %s on line %d +array(2) { + [0]=> + int(42) + [1]=> + object(__PHP_Incomplete_Class)#1 (1) { + ["__PHP_Incomplete_Class_Name"]=> + string(4) "evil" + } +} diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index efb0942b05..79d98e5a24 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -557,7 +557,7 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 875 "ext/standard/var_unserializer.re" +#line 877 "ext/standard/var_unserializer.re" { return 0; } #line 563 "ext/standard/var_unserializer.c" yy4: @@ -602,7 +602,7 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 869 "ext/standard/var_unserializer.re" +#line 871 "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"); @@ -750,6 +750,7 @@ yy20: } /* The callback function may have defined the class */ + BG(serialize_lock)++; if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } else { @@ -757,6 +758,7 @@ yy20: incomplete_class = 1; ce = PHP_IC_ENTRY; } + BG(serialize_lock)--; zval_ptr_dtor(&user_func); zval_ptr_dtor(&arg_func_name); @@ -791,7 +793,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 795 "ext/standard/var_unserializer.c" +#line 797 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -829,7 +831,7 @@ yy27: } return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 833 "ext/standard/var_unserializer.c" +#line 835 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -871,7 +873,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 875 "ext/standard/var_unserializer.c" +#line 877 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -927,7 +929,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 931 "ext/standard/var_unserializer.c" +#line 933 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -981,7 +983,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 985 "ext/standard/var_unserializer.c" +#line 987 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1079,7 +1081,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1083 "ext/standard/var_unserializer.c" +#line 1085 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1153,7 +1155,7 @@ yy73: return 1; } -#line 1157 "ext/standard/var_unserializer.c" +#line 1159 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1207,7 +1209,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1211 "ext/standard/var_unserializer.c" +#line 1213 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1222,7 +1224,7 @@ yy83: ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1226 "ext/standard/var_unserializer.c" +#line 1228 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; #line 549 "ext/standard/var_unserializer.re" @@ -1232,7 +1234,7 @@ yy87: ZVAL_NULL(*rval); return 1; } -#line 1236 "ext/standard/var_unserializer.c" +#line 1238 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1278,7 +1280,7 @@ yy91: return 1; } -#line 1282 "ext/standard/var_unserializer.c" +#line 1284 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1322,9 +1324,9 @@ yy97: return 1; } -#line 1326 "ext/standard/var_unserializer.c" +#line 1328 "ext/standard/var_unserializer.c" } -#line 877 "ext/standard/var_unserializer.re" +#line 879 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 4cdf313735..7fbab9f2f0 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -824,6 +824,7 @@ object ":" uiv ":" ["] { } /* The callback function may have defined the class */ + BG(serialize_lock)++; if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } else { @@ -831,6 +832,7 @@ object ":" uiv ":" ["] { incomplete_class = 1; ce = PHP_IC_ENTRY; } + BG(serialize_lock)--; zval_ptr_dtor(&user_func); zval_ptr_dtor(&arg_func_name); |