From: Xinchen Hui Date: Sat, 9 Mar 2013 15:00:58 +0000 (+0800) Subject: Fixed bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) X-Git-Tag: php-5.5.0beta1~48^2~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f52b2e6a6572018eb61ad830206ed172b033232a;p=php Fixed bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) about the __sleep one, since php_serialize_* are all void function, so,,only check exception at the very begining --- diff --git a/NEWS b/NEWS index f8a43f6501..1fbd5a2858 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS ?? ??? 2013, PHP 5.4.13 - Core: + . Fixed bug #64354 (Unserialize array of objects whose class can't + be autoloaded fail). (Laruence) . Fixed bug #64235 (Insteadof not work for class method in 5.4.11). (Laruence) . Fixed bug #64197 (_Offsetof() macro used but not defined on ARM/Clang). diff --git a/ext/standard/tests/serialize/bug64354_1.phpt b/ext/standard/tests/serialize/bug64354_1.phpt new file mode 100644 index 0000000000..e85749bcbe --- /dev/null +++ b/ext/standard/tests/serialize/bug64354_1.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) +--FILE-- +getMessage()); +} + +try { + var_dump(unserialize('a:2:{i:0;O:1:"A":0:{}i:1;O:1:"A":0:{}}')); +} catch (Exception $e) { + var_dump($e->getMessage()); +} +?> +--EXPECTF-- +string(6) "Failed" +string(6) "Failed" diff --git a/ext/standard/tests/serialize/bug64354_2.phpt b/ext/standard/tests/serialize/bug64354_2.phpt new file mode 100644 index 0000000000..41a455b54a --- /dev/null +++ b/ext/standard/tests/serialize/bug64354_2.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) +--FILE-- +getMessage()); +} +?> +--EXPECTF-- +string(6) "Failed" diff --git a/ext/standard/tests/serialize/bug64354_3.phpt b/ext/standard/tests/serialize/bug64354_3.phpt new file mode 100644 index 0000000000..3ce61152d6 --- /dev/null +++ b/ext/standard/tests/serialize/bug64354_3.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) +--FILE-- +getMessage()); +} +?> +--EXPECTF-- +string(6) "Failed" diff --git a/ext/standard/var.c b/ext/standard/var.c index b13edf6615..f76a14cfa6 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -714,6 +714,10 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var ulong *var_already; HashTable *myht; + if (EG(exception)) { + return; + } + if (var_hash && php_add_var_hash(var_hash, struc, (void *) &var_already TSRMLS_CC) == FAILURE) { if (Z_ISREF_P(struc)) { smart_str_appendl(buf, "R:", 2); @@ -800,8 +804,15 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var BG(serialize_lock)++; res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); BG(serialize_lock)--; + + if (EG(exception)) { + if (retval_ptr) { + zval_ptr_dtor(&retval_ptr); + } + return; + } - if (res == SUCCESS && !EG(exception)) { + if (res == SUCCESS) { if (retval_ptr) { if (HASH_OF(retval_ptr)) { php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC); @@ -921,6 +932,11 @@ PHP_FUNCTION(serialize) php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); PHP_VAR_SERIALIZE_DESTROY(var_hash); + if (EG(exception)) { + smart_str_free(&buf); + RETURN_FALSE; + } + if (buf.c) { RETURN_STRINGL(buf.c, buf.len, 0); } else { @@ -951,7 +967,9 @@ PHP_FUNCTION(unserialize) if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) { PHP_VAR_UNSERIALIZE_DESTROY(var_hash); zval_dtor(return_value); - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); + if (!EG(exception)) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); + } RETURN_FALSE; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index bd0b2f6695..d8bae08d2a 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Mon Jan 21 11:34:03 2013 */ +/* Generated by re2c 0.13.5 on Sat Mar 9 22:33:09 2013 */ #line 1 "ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ @@ -396,8 +396,13 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) BG(serialize_lock)--; } - if (retval_ptr) + if (retval_ptr) { zval_ptr_dtor(&retval_ptr); + } + + if (EG(exception)) { + return 0; + } return finish_nested_data(UNSERIALIZE_PASSTHRU); @@ -427,7 +432,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 431 "ext/standard/var_unserializer.c" +#line 436 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -487,9 +492,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 759 "ext/standard/var_unserializer.re" +#line 785 "ext/standard/var_unserializer.re" { return 0; } -#line 493 "ext/standard/var_unserializer.c" +#line 498 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -532,13 +537,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 753 "ext/standard/var_unserializer.re" +#line 779 "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 542 "ext/standard/var_unserializer.c" +#line 547 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -568,7 +573,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 630 "ext/standard/var_unserializer.re" +#line 635 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -623,10 +628,19 @@ yy20: BG(serialize_lock) = 1; if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { BG(serialize_lock) = 0; + if (EG(exception)) { + efree(class_name); + return 0; + } ce = *pce; break; } BG(serialize_lock) = 0; + + if (EG(exception)) { + efree(class_name); + return 0; + } /* Check for unserialize callback */ if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) { @@ -644,6 +658,12 @@ yy20: BG(serialize_lock) = 1; if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) { BG(serialize_lock) = 0; + if (EG(exception)) { + efree(class_name); + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + return 0; + } php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val); incomplete_class = 1; ce = PHP_IC_ENTRY; @@ -655,6 +675,12 @@ yy20: if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } + if (EG(exception)) { + efree(class_name); + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + return 0; + } /* The callback function may have defined the class */ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { @@ -691,7 +717,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 695 "ext/standard/var_unserializer.c" +#line 721 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -716,7 +742,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 622 "ext/standard/var_unserializer.re" +#line 627 "ext/standard/var_unserializer.re" { INIT_PZVAL(*rval); @@ -724,7 +750,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 728 "ext/standard/var_unserializer.c" +#line 754 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -745,7 +771,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 602 "ext/standard/var_unserializer.re" +#line 607 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -765,7 +791,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 769 "ext/standard/var_unserializer.c" +#line 795 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -786,7 +812,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 573 "ext/standard/var_unserializer.re" +#line 578 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -815,7 +841,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 819 "ext/standard/var_unserializer.c" +#line 845 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -836,7 +862,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 545 "ext/standard/var_unserializer.re" +#line 550 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -864,7 +890,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 868 "ext/standard/var_unserializer.c" +#line 894 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -952,7 +978,7 @@ yy61: } yy63: ++YYCURSOR; -#line 535 "ext/standard/var_unserializer.re" +#line 540 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -962,7 +988,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 966 "ext/standard/var_unserializer.c" +#line 992 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1021,7 +1047,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 520 "ext/standard/var_unserializer.re" +#line 525 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1036,7 +1062,7 @@ yy73: return 1; } -#line 1040 "ext/standard/var_unserializer.c" +#line 1066 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1063,7 +1089,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 493 "ext/standard/var_unserializer.re" +#line 498 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1090,7 +1116,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1094 "ext/standard/var_unserializer.c" +#line 1120 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1098,24 +1124,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 486 "ext/standard/var_unserializer.re" +#line 491 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1109 "ext/standard/var_unserializer.c" +#line 1135 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 479 "ext/standard/var_unserializer.re" +#line 484 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1119 "ext/standard/var_unserializer.c" +#line 1145 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1138,7 +1164,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 456 "ext/standard/var_unserializer.re" +#line 461 "ext/standard/var_unserializer.re" { long id; @@ -1161,7 +1187,7 @@ yy91: return 1; } -#line 1165 "ext/standard/var_unserializer.c" +#line 1191 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1184,7 +1210,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 435 "ext/standard/var_unserializer.re" +#line 440 "ext/standard/var_unserializer.re" { long id; @@ -1205,9 +1231,9 @@ yy97: return 1; } -#line 1209 "ext/standard/var_unserializer.c" +#line 1235 "ext/standard/var_unserializer.c" } -#line 761 "ext/standard/var_unserializer.re" +#line 787 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 204995783f..4d99cbfd78 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -400,8 +400,13 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) BG(serialize_lock)--; } - if (retval_ptr) + if (retval_ptr) { zval_ptr_dtor(&retval_ptr); + } + + if (EG(exception)) { + return 0; + } return finish_nested_data(UNSERIALIZE_PASSTHRU); @@ -681,10 +686,19 @@ object ":" uiv ":" ["] { BG(serialize_lock) = 1; if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { BG(serialize_lock) = 0; + if (EG(exception)) { + efree(class_name); + return 0; + } ce = *pce; break; } BG(serialize_lock) = 0; + + if (EG(exception)) { + efree(class_name); + return 0; + } /* Check for unserialize callback */ if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) { @@ -702,6 +716,12 @@ object ":" uiv ":" ["] { BG(serialize_lock) = 1; if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) { BG(serialize_lock) = 0; + if (EG(exception)) { + efree(class_name); + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + return 0; + } php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val); incomplete_class = 1; ce = PHP_IC_ENTRY; @@ -713,6 +733,12 @@ object ":" uiv ":" ["] { if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } + if (EG(exception)) { + efree(class_name); + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + return 0; + } /* The callback function may have defined the class */ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {