From 2dca8671e4590917a52a4cd9cb57951b412e2f95 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pedro=20Magalh=C3=A3es?= Date: Thu, 3 May 2018 21:25:12 +0100 Subject: [PATCH] Fix #76300 - Dont attempt to change visibility of a parent private --- ext/standard/tests/serialize/bug76300.phpt | 29 ++++++++++ ext/standard/var_unserializer.c | 61 +++++++++++----------- ext/standard/var_unserializer.re | 1 + 3 files changed, 61 insertions(+), 30 deletions(-) create mode 100644 ext/standard/tests/serialize/bug76300.phpt diff --git a/ext/standard/tests/serialize/bug76300.phpt b/ext/standard/tests/serialize/bug76300.phpt new file mode 100644 index 0000000000..13e50f0332 --- /dev/null +++ b/ext/standard/tests/serialize/bug76300.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #76300: Unserialize of extended protected member broken +--FILE-- +id = $id; + } +} +class Derived extends Base { + protected $id; + public function __construct($id) + { + parent::__construct($id + 20); + $this->id = $id; + } +} +$a = new Derived(44); +$s = serialize($a); +$u = unserialize($s); +print_r($u); +--EXPECT-- +Derived Object +( + [id:protected] => 44 + [id:Base:private] => 64 +) diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 679d9c6d8b..108887580f 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -429,6 +429,7 @@ string_key: unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0); if (Z_TYPE_P(rval) == IS_OBJECT + && (unmangled_class == NULL || !strcmp(unmangled_class, "*") || !strcasecmp(unmangled_class, ZSTR_VAL(Z_OBJCE_P(rval)->name))) && ((existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled)) != NULL) && (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) { if (existing_propinfo->flags & ZEND_ACC_PROTECTED) { @@ -644,7 +645,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER) start = cursor; -#line 648 "ext/standard/var_unserializer.c" +#line 649 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -702,9 +703,9 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER) yy2: ++YYCURSOR; yy3: -#line 1035 "ext/standard/var_unserializer.re" +#line 1036 "ext/standard/var_unserializer.re" { return 0; } -#line 708 "ext/standard/var_unserializer.c" +#line 709 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy17; @@ -751,13 +752,13 @@ yy14: goto yy3; yy15: ++YYCURSOR; -#line 1029 "ext/standard/var_unserializer.re" +#line 1030 "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"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 761 "ext/standard/var_unserializer.c" +#line 762 "ext/standard/var_unserializer.c" yy17: yych = *++YYCURSOR; if (yybm[0+yych] & 128) { @@ -768,13 +769,13 @@ yy18: goto yy3; yy19: ++YYCURSOR; -#line 701 "ext/standard/var_unserializer.re" +#line 702 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_NULL(rval); return 1; } -#line 778 "ext/standard/var_unserializer.c" +#line 779 "ext/standard/var_unserializer.c" yy21: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -973,7 +974,7 @@ yy55: goto yy18; yy56: ++YYCURSOR; -#line 652 "ext/standard/var_unserializer.re" +#line 653 "ext/standard/var_unserializer.re" { zend_long id; @@ -998,7 +999,7 @@ yy56: return 1; } -#line 1002 "ext/standard/var_unserializer.c" +#line 1003 "ext/standard/var_unserializer.c" yy58: yych = *++YYCURSOR; if (yych == '"') goto yy77; @@ -1009,13 +1010,13 @@ yy59: goto yy18; yy60: ++YYCURSOR; -#line 707 "ext/standard/var_unserializer.re" +#line 708 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_BOOL(rval, parse_iv(start + 2)); return 1; } -#line 1019 "ext/standard/var_unserializer.c" +#line 1020 "ext/standard/var_unserializer.c" yy62: ++YYCURSOR; if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); @@ -1035,7 +1036,7 @@ yy62: } yy64: ++YYCURSOR; -#line 755 "ext/standard/var_unserializer.re" +#line 756 "ext/standard/var_unserializer.re" { #if SIZEOF_ZEND_LONG == 4 use_double: @@ -1044,7 +1045,7 @@ use_double: ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1048 "ext/standard/var_unserializer.c" +#line 1049 "ext/standard/var_unserializer.c" yy66: yych = *++YYCURSOR; if (yych <= ',') { @@ -1066,7 +1067,7 @@ yy68: goto yy18; yy69: ++YYCURSOR; -#line 713 "ext/standard/var_unserializer.re" +#line 714 "ext/standard/var_unserializer.re" { #if SIZEOF_ZEND_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1092,14 +1093,14 @@ yy69: ZVAL_LONG(rval, parse_iv(start + 2)); return 1; } -#line 1096 "ext/standard/var_unserializer.c" +#line 1097 "ext/standard/var_unserializer.c" yy71: yych = *++YYCURSOR; if (yych == '"') goto yy85; goto yy18; yy72: ++YYCURSOR; -#line 677 "ext/standard/var_unserializer.re" +#line 678 "ext/standard/var_unserializer.re" { zend_long id; @@ -1123,14 +1124,14 @@ yy72: return 1; } -#line 1127 "ext/standard/var_unserializer.c" +#line 1128 "ext/standard/var_unserializer.c" yy74: yych = *++YYCURSOR; if (yych == '"') goto yy87; goto yy18; yy75: ++YYCURSOR; -#line 877 "ext/standard/var_unserializer.re" +#line 878 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; zend_long elements; @@ -1282,10 +1283,10 @@ yy75: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 1286 "ext/standard/var_unserializer.c" +#line 1287 "ext/standard/var_unserializer.c" yy77: ++YYCURSOR; -#line 802 "ext/standard/var_unserializer.re" +#line 803 "ext/standard/var_unserializer.re" { size_t len, maxlen; zend_string *str; @@ -1319,10 +1320,10 @@ yy77: ZVAL_STR(rval, str); return 1; } -#line 1323 "ext/standard/var_unserializer.c" +#line 1324 "ext/standard/var_unserializer.c" yy79: ++YYCURSOR; -#line 836 "ext/standard/var_unserializer.re" +#line 837 "ext/standard/var_unserializer.re" { zend_long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -1352,7 +1353,7 @@ yy79: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 1356 "ext/standard/var_unserializer.c" +#line 1357 "ext/standard/var_unserializer.c" yy81: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1371,7 +1372,7 @@ yy84: goto yy18; yy85: ++YYCURSOR; -#line 866 "ext/standard/var_unserializer.re" +#line 867 "ext/standard/var_unserializer.re" { zend_long elements; if (!var_hash) return 0; @@ -1382,10 +1383,10 @@ yy85: } return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 1386 "ext/standard/var_unserializer.c" +#line 1387 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 764 "ext/standard/var_unserializer.re" +#line 765 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -1423,10 +1424,10 @@ yy87: } return 1; } -#line 1427 "ext/standard/var_unserializer.c" +#line 1428 "ext/standard/var_unserializer.c" yy89: ++YYCURSOR; -#line 739 "ext/standard/var_unserializer.re" +#line 740 "ext/standard/var_unserializer.re" { *p = YYCURSOR; @@ -1442,9 +1443,9 @@ yy89: return 1; } -#line 1446 "ext/standard/var_unserializer.c" +#line 1447 "ext/standard/var_unserializer.c" } -#line 1037 "ext/standard/var_unserializer.re" +#line 1038 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 5d4503b394..af42222677 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -433,6 +433,7 @@ string_key: unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0); if (Z_TYPE_P(rval) == IS_OBJECT + && (unmangled_class == NULL || !strcmp(unmangled_class, "*") || !strcasecmp(unmangled_class, ZSTR_VAL(Z_OBJCE_P(rval)->name))) && ((existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled)) != NULL) && (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) { if (existing_propinfo->flags & ZEND_ACC_PROTECTED) { -- 2.40.0