com php-src: Fixed bug #67072 Echoing unserialized "SplFileObject" crash: NEWS ext/standard/tests/serialize/005.phpt
ext/standard/tests/serialize/bug67072.phpt ext/standard/var_u nserializer.c ext/standard/var_unserializer.re
| From: | Anatol Belski | Date: | Thu, 17 Apr 2014 08:48:14 +0000 |
| Subject: | com php-src: Fixed bug #67072 Echoing unserialized "SplFileObject" crash: NEWS ext/standard/tests/serialize/005.phpt ext/standard/tests/serialize/bug67072.phpt ext/standard/var_u nserializer.c ext/standard/var_unserializer.re |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-76927@lists.php.net to get a copy of this message | ||
Commit: 5328d4289946e260232f3195ba2e0f0eb173d5ef
Author: Anatol Belski <ab@php.net> Thu, 17 Apr 2014 10:48:14 +0200
Parents: 7a5f1663c6775bbdaf870e4c71ef8813d5d13179
Branches: PHP-5.4 PHP-5.5 PHP-5.6 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=5328d4289946e260232f3195ba2e0f0eb173d5ef
Log:
Fixed bug #67072 Echoing unserialized "SplFileObject" crash
The actual issue lays in the unserializer code which doesn't honor
the unserialize callback. By contrast, the serialize callback is
respected. This leads to the situation that even if a class has
disabled the serialization explicitly, user could still construct
a vulnerable string which would result bad things when trying
to unserialize.
This conserns also the classes implementing Serializable as well
as some core classes disabling serialize/unserialize callbacks
explicitly (PDO, SimpleXML, SplFileInfo and co). As of now, the
flow is first to call the unserialize callback (if available),
then call __wakeup. If the unserialize callback returns with no
success, no object is instantiated. This makes the scheme used
by internal classes effective, to disable unserialize just assign
zend_class_unserialize_deny as callback.
Bugs:
https://bugs.php.net/67072
Changed paths:
M NEWS
M ext/standard/tests/serialize/005.phpt
A ext/standard/tests/serialize/bug67072.phpt
M ext/standard/var_unserializer.c
M ext/standard/var_unserializer.re
diff --git a/NEWS b/NEWS index 4c2a97e..2ba98b0 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug #67081 (DOMDocumentType->internalSubset returns entire DOCTYPE tag, not only the subset). (Anatol) +- Standard: + . Fixed bug #67072 (Echoing unserialized "SplFileObject" crash). (Anatol) + + ?? ??? 2014, PHP 5.4.28 - Core: diff --git a/ext/standard/tests/serialize/005.phpt b/ext/standard/tests/serialize/005.phpt index e7b23db..87a3fb3 100644 --- a/ext/standard/tests/serialize/005.phpt +++ b/ext/standard/tests/serialize/005.phpt @@ -156,6 +156,7 @@ object(TestNAOld)#%d (0) { } ===NANew=== unserializer(TestNANew) +TestNew::unserialize() TestNew::__wakeup() object(TestNANew)#%d (0) { } diff --git a/ext/standard/tests/serialize/bug67072.phpt b/ext/standard/tests/serialize/bug67072.phpt new file mode 100644 index 0000000..3e7d33b --- /dev/null +++ b/ext/standard/tests/serialize/bug67072.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #67072 Echoing unserialized "SplFileObject" crash +--FILE-- +<?php + echo unserialize('O:13:"SplFileObject":1:{s:9:"*filename";s:15:"/home/flag/flag";}'); +?> +===DONE== +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' with message 'Unserialization of 'SplFileObject' is not allowed' in %sbug67072.php:2 +Stack trace: +#0 %sbug67072.php(2): unserialize('O:13:"SplFileOb...') +#1 {main} + thrown in %sbug67072.php on line 2 diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index e39a350..8db00c2 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,10 +1,10 @@ -/* Generated by re2c 0.13.5 on Mon Jul 29 17:57:26 2013 */ +/* Generated by re2c 0.13.5 on Thu Apr 17 10:03:26 2014 */ #line 1 "ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2014 The PHP Group | + | Copyright (c) 1997-2013 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -396,7 +396,12 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) (*p) += 2; - object_init_ex(*rval, ce); + if (ce->unserialize == NULL) { + object_init_ex(*rval, ce); + } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, elements, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) { + return 0; + } + return elements; } @@ -408,6 +413,10 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) zval *retval_ptr = NULL; zval fname; + if (Z_TYPE_PP(rval) != IS_OBJECT) { + return 0; + } + if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { return 0; } @@ -457,7 +466,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 461 "ext/standard/var_unserializer.c" +#line 470 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -517,9 +526,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 812 "ext/standard/var_unserializer.re" +#line 821 "ext/standard/var_unserializer.re" { return 0; } -#line 523 "ext/standard/var_unserializer.c" +#line 532 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -562,13 +571,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 806 "ext/standard/var_unserializer.re" +#line 815 "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 572 "ext/standard/var_unserializer.c" +#line 581 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -598,7 +607,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 660 "ext/standard/var_unserializer.re" +#line 669 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -744,7 +753,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 748 "ext/standard/var_unserializer.c" +#line 757 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -769,7 +778,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 652 "ext/standard/var_unserializer.re" +#line 661 "ext/standard/var_unserializer.re" { INIT_PZVAL(*rval); @@ -777,7 +786,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 781 "ext/standard/var_unserializer.c" +#line 790 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -798,7 +807,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 632 "ext/standard/var_unserializer.re" +#line 641 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -818,7 +827,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 822 "ext/standard/var_unserializer.c" +#line 831 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -839,7 +848,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 603 "ext/standard/var_unserializer.re" +#line 612 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -868,7 +877,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 872 "ext/standard/var_unserializer.c" +#line 881 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -889,7 +898,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 575 "ext/standard/var_unserializer.re" +#line 584 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -917,7 +926,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 921 "ext/standard/var_unserializer.c" +#line 930 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1005,7 +1014,7 @@ yy61: } yy63: ++YYCURSOR; -#line 565 "ext/standard/var_unserializer.re" +#line 574 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1015,7 +1024,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1019 "ext/standard/var_unserializer.c" +#line 1028 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1074,7 +1083,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 550 "ext/standard/var_unserializer.re" +#line 559 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1089,7 +1098,7 @@ yy73: return 1; } -#line 1093 "ext/standard/var_unserializer.c" +#line 1102 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1116,7 +1125,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 523 "ext/standard/var_unserializer.re" +#line 532 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1143,7 +1152,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1147 "ext/standard/var_unserializer.c" +#line 1156 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1151,24 +1160,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 516 "ext/standard/var_unserializer.re" +#line 525 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1162 "ext/standard/var_unserializer.c" +#line 1171 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 509 "ext/standard/var_unserializer.re" +#line 518 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1172 "ext/standard/var_unserializer.c" +#line 1181 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1191,7 +1200,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 486 "ext/standard/var_unserializer.re" +#line 495 "ext/standard/var_unserializer.re" { long id; @@ -1214,7 +1223,7 @@ yy91: return 1; } -#line 1218 "ext/standard/var_unserializer.c" +#line 1227 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1237,7 +1246,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 465 "ext/standard/var_unserializer.re" +#line 474 "ext/standard/var_unserializer.re" { long id; @@ -1258,9 +1267,9 @@ yy97: return 1; } -#line 1262 "ext/standard/var_unserializer.c" +#line 1271 "ext/standard/var_unserializer.c" } -#line 814 "ext/standard/var_unserializer.re" +#line 823 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 76c501e..1f71bb7 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -400,7 +400,12 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) (*p) += 2; - object_init_ex(*rval, ce); + if (ce->unserialize == NULL) { + object_init_ex(*rval, ce); + } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, elements, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) { + return 0; + } + return elements; } @@ -412,6 +417,10 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) zval *retval_ptr = NULL; zval fname; + if (Z_TYPE_PP(rval) != IS_OBJECT) { + return 0; + } + if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { return 0; }
diff --git a/NEWS b/NEWS index 4c2a97e..2ba98b0 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug #67081 (DOMDocumentType->internalSubset returns entire DOCTYPE tag, not only the subset). (Anatol) +- Standard: + . Fixed bug #67072 (Echoing unserialized "SplFileObject" crash). (Anatol) + + ?? ??? 2014, PHP 5.4.28 - Core: diff --git a/ext/standard/tests/serialize/005.phpt b/ext/standard/tests/serialize/005.phpt index e7b23db..87a3fb3 100644 --- a/ext/standard/tests/serialize/005.phpt +++ b/ext/standard/tests/serialize/005.phpt @@ -156,6 +156,7 @@ object(TestNAOld)#%d (0) { } ===NANew=== unserializer(TestNANew) +TestNew::unserialize() TestNew::__wakeup() object(TestNANew)#%d (0) { } diff --git a/ext/standard/tests/serialize/bug67072.phpt b/ext/standard/tests/serialize/bug67072.phpt new file mode 100644 index 0000000..3e7d33b --- /dev/null +++ b/ext/standard/tests/serialize/bug67072.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #67072 Echoing unserialized "SplFileObject" crash +--FILE-- +<?php + echo unserialize('O:13:"SplFileObject":1:{s:9:"*filename";s:15:"/home/flag/flag";}'); +?> +===DONE== +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' with message 'Unserialization of 'SplFileObject' is not allowed' in %sbug67072.php:2 +Stack trace: +#0 %sbug67072.php(2): unserialize('O:13:"SplFileOb...') +#1 {main} + thrown in %sbug67072.php on line 2 diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index e39a350..8db00c2 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,10 +1,10 @@ -/* Generated by re2c 0.13.5 on Mon Jul 29 17:57:26 2013 */ +/* Generated by re2c 0.13.5 on Thu Apr 17 10:03:26 2014 */ #line 1 "ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2014 The PHP Group | + | Copyright (c) 1997-2013 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -396,7 +396,12 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) (*p) += 2; - object_init_ex(*rval, ce); + if (ce->unserialize == NULL) { + object_init_ex(*rval, ce); + } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, elements, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) { + return 0; + } + return elements; } @@ -408,6 +413,10 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) zval *retval_ptr = NULL; zval fname; + if (Z_TYPE_PP(rval) != IS_OBJECT) { + return 0; + } + if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { return 0; } @@ -457,7 +466,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 461 "ext/standard/var_unserializer.c" +#line 470 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -517,9 +526,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 812 "ext/standard/var_unserializer.re" +#line 821 "ext/standard/var_unserializer.re" { return 0; } -#line 523 "ext/standard/var_unserializer.c" +#line 532 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -562,13 +571,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 806 "ext/standard/var_unserializer.re" +#line 815 "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 572 "ext/standard/var_unserializer.c" +#line 581 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -598,7 +607,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 660 "ext/standard/var_unserializer.re" +#line 669 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -744,7 +753,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 748 "ext/standard/var_unserializer.c" +#line 757 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -769,7 +778,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 652 "ext/standard/var_unserializer.re" +#line 661 "ext/standard/var_unserializer.re" { INIT_PZVAL(*rval); @@ -777,7 +786,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 781 "ext/standard/var_unserializer.c" +#line 790 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -798,7 +807,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 632 "ext/standard/var_unserializer.re" +#line 641 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -818,7 +827,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 822 "ext/standard/var_unserializer.c" +#line 831 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -839,7 +848,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 603 "ext/standard/var_unserializer.re" +#line 612 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -868,7 +877,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 872 "ext/standard/var_unserializer.c" +#line 881 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -889,7 +898,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 575 "ext/standard/var_unserializer.re" +#line 584 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -917,7 +926,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 921 "ext/standard/var_unserializer.c" +#line 930 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1005,7 +1014,7 @@ yy61: } yy63: ++YYCURSOR; -#line 565 "ext/standard/var_unserializer.re" +#line 574 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1015,7 +1024,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1019 "ext/standard/var_unserializer.c" +#line 1028 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1074,7 +1083,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 550 "ext/standard/var_unserializer.re" +#line 559 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1089,7 +1098,7 @@ yy73: return 1; } -#line 1093 "ext/standard/var_unserializer.c" +#line 1102 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1116,7 +1125,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 523 "ext/standard/var_unserializer.re" +#line 532 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1143,7 +1152,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1147 "ext/standard/var_unserializer.c" +#line 1156 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1151,24 +1160,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 516 "ext/standard/var_unserializer.re" +#line 525 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1162 "ext/standard/var_unserializer.c" +#line 1171 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 509 "ext/standard/var_unserializer.re" +#line 518 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1172 "ext/standard/var_unserializer.c" +#line 1181 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1191,7 +1200,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 486 "ext/standard/var_unserializer.re" +#line 495 "ext/standard/var_unserializer.re" { long id; @@ -1214,7 +1223,7 @@ yy91: return 1; } -#line 1218 "ext/standard/var_unserializer.c" +#line 1227 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1237,7 +1246,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 465 "ext/standard/var_unserializer.re" +#line 474 "ext/standard/var_unserializer.re" { long id; @@ -1258,9 +1267,9 @@ yy97: return 1; } -#line 1262 "ext/standard/var_unserializer.c" +#line 1271 "ext/standard/var_unserializer.c" } -#line 814 "ext/standard/var_unserializer.re" +#line 823 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 76c501e..1f71bb7 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -400,7 +400,12 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) (*p) += 2; - object_init_ex(*rval, ce); + if (ce->unserialize == NULL) { + object_init_ex(*rval, ce); + } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, elements, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) { + return 0; + } + return elements; } @@ -412,6 +417,10 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) zval *retval_ptr = NULL; zval fname; + if (Z_TYPE_PP(rval) != IS_OBJECT) { + return 0; + } + if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { return 0; }