summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2017-01-01 14:13:29 +0100
committerNikita Popov <nikic@php.net>2017-01-01 14:13:29 +0100
commit878b8f046593085365466f20c756a2d429164707 (patch)
tree02d3be09cfda20dfbffbe4c6d2405a7f066f4149
parent2a340423236938b8c6962f245f0ba99a6345d2f3 (diff)
parent9f560baef5eacbe3fdb6a23a2d4e1996a30a2d2c (diff)
downloadphp-git-878b8f046593085365466f20c756a2d429164707.tar.gz
Merge branch 'PHP-7.0' into PHP-7.1
-rw-r--r--NEWS6
-rw-r--r--ext/standard/tests/serialize/bug70213.phpt30
-rw-r--r--ext/standard/var_unserializer.c20
-rw-r--r--ext/standard/var_unserializer.re2
4 files changed, 47 insertions, 11 deletions
diff --git a/NEWS b/NEWS
index d06b6c4ae3..3a87745959 100644
--- a/NEWS
+++ b/NEWS
@@ -53,8 +53,10 @@ PHP NEWS
set). (cmb)
- Standard:
- . Fixed bug #73594 (dns_get_record does not populate $additional out parameter).
- (Bruce Weirdan)
+ . Fixed bug #73594 (dns_get_record does not populate $additional out
+ parameter). (Bruce Weirdan)
+ . Fixed bug #70213 (Unserialize context shared on double class lookup).
+ (Taoguang Chen)
- Zlib
. Fixed bug #73373 (deflate_add does not verify that output was not truncated).
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 f3b997a6ef..4e2bee3c9e 100644
--- a/ext/standard/var_unserializer.c
+++ b/ext/standard/var_unserializer.c
@@ -647,7 +647,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
yy2:
++YYCURSOR;
yy3:
-#line 959 "ext/standard/var_unserializer.re"
+#line 961 "ext/standard/var_unserializer.re"
{ return 0; }
#line 653 "ext/standard/var_unserializer.c"
yy4:
@@ -696,7 +696,7 @@ yy14:
goto yy3;
yy15:
++YYCURSOR;
-#line 953 "ext/standard/var_unserializer.re"
+#line 955 "ext/standard/var_unserializer.re"
{
/* this is the case where we have less data than planned */
php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
@@ -1240,11 +1240,13 @@ yy82:
}
/* The callback function may have defined the class */
+ BG(serialize_lock)++;
if ((ce = zend_lookup_class(class_name)) == NULL) {
php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
incomplete_class = 1;
ce = PHP_IC_ENTRY;
}
+ BG(serialize_lock)--;
zval_ptr_dtor(&user_func);
zval_ptr_dtor(&args[0]);
@@ -1274,7 +1276,7 @@ yy82:
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
-#line 1278 "ext/standard/var_unserializer.c"
+#line 1280 "ext/standard/var_unserializer.c"
yy84:
++YYCURSOR;
#line 743 "ext/standard/var_unserializer.re"
@@ -1311,7 +1313,7 @@ yy84:
ZVAL_STR(rval, str);
return 1;
}
-#line 1315 "ext/standard/var_unserializer.c"
+#line 1317 "ext/standard/var_unserializer.c"
yy86:
++YYCURSOR;
#line 777 "ext/standard/var_unserializer.re"
@@ -1338,7 +1340,7 @@ yy86:
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
-#line 1342 "ext/standard/var_unserializer.c"
+#line 1344 "ext/standard/var_unserializer.c"
yy88:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1370,7 +1372,7 @@ yy92:
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
-#line 1374 "ext/standard/var_unserializer.c"
+#line 1376 "ext/standard/var_unserializer.c"
yy94:
++YYCURSOR;
#line 711 "ext/standard/var_unserializer.re"
@@ -1405,7 +1407,7 @@ yy94:
ZVAL_STRINGL(rval, str, len);
return 1;
}
-#line 1409 "ext/standard/var_unserializer.c"
+#line 1411 "ext/standard/var_unserializer.c"
yy96:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
@@ -1429,9 +1431,9 @@ yy97:
return 1;
}
-#line 1433 "ext/standard/var_unserializer.c"
+#line 1435 "ext/standard/var_unserializer.c"
}
-#line 961 "ext/standard/var_unserializer.re"
+#line 963 "ext/standard/var_unserializer.re"
return 0;
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re
index 6d53cb6249..4f127773ef 100644
--- a/ext/standard/var_unserializer.re
+++ b/ext/standard/var_unserializer.re
@@ -915,11 +915,13 @@ object ":" uiv ":" ["] {
}
/* The callback function may have defined the class */
+ BG(serialize_lock)++;
if ((ce = zend_lookup_class(class_name)) == NULL) {
php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
incomplete_class = 1;
ce = PHP_IC_ENTRY;
}
+ BG(serialize_lock)--;
zval_ptr_dtor(&user_func);
zval_ptr_dtor(&args[0]);