From a5014d7c58e66f2270c86b573ac9fabd40559de9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 30 Nov 2017 13:13:42 +0300 Subject: [PATCH] Avoid visibility checks for classes without predefined properties --- ext/standard/var_unserializer.c | 129 ++++++++++++++++--------------- ext/standard/var_unserializer.re | 65 ++++++++-------- 2 files changed, 98 insertions(+), 96 deletions(-) diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 42be189874..ceafd50205 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -436,60 +436,61 @@ numeric_key: } else { if (EXPECTED(Z_TYPE(key) == IS_STRING)) { string_key: - { + if (Z_TYPE_P(rval) == IS_OBJECT + && zend_hash_num_elements(&Z_OBJCE_P(rval)->properties_info) > 0) { zend_property_info *existing_propinfo; zend_string *new_key; const char *unmangled_class = NULL; const char *unmangled_prop; size_t unmangled_prop_len; + zend_string *unmangled; if (UNEXPECTED(zend_unmangle_property_name_ex(Z_STR(key), &unmangled_class, &unmangled_prop, &unmangled_prop_len) == FAILURE)) { zval_ptr_dtor(&key); return 0; } - if (Z_TYPE_P(rval) == IS_OBJECT) { - zend_string *unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0); + unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0); - if (((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) { + existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled); + if ((existing_propinfo != NULL) + && (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) { + if (existing_propinfo->flags & ZEND_ACC_PROTECTED) { + new_key = zend_mangle_property_name( + "*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0); + zend_string_release(unmangled); + } else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) { + if (unmangled_class != NULL && strcmp(unmangled_class, "*") != 0) { new_key = zend_mangle_property_name( - "*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0); - zend_string_release(unmangled); - } else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) { - if (unmangled_class != NULL && strcmp(unmangled_class, "*") != 0) { - new_key = zend_mangle_property_name( - unmangled_class, strlen(unmangled_class), - ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), - 0); - } else { - new_key = zend_mangle_property_name( - ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name), + unmangled_class, strlen(unmangled_class), ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0); - } - zend_string_release(unmangled); } else { - ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC); - new_key = unmangled; + new_key = zend_mangle_property_name( + ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name), + ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), + 0); } - zend_string_release(Z_STR(key)); - ZVAL_STR(&key, new_key); - } else { zend_string_release(unmangled); + } else { + ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC); + new_key = unmangled; } + zend_string_release(Z_STR(key)); + ZVAL_STR(&key, new_key); + } else { + zend_string_release(unmangled); } + } - if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) { - if (Z_TYPE_P(old_data) == IS_INDIRECT) { - old_data = Z_INDIRECT_P(old_data); - } - var_push_dtor(var_hash, old_data); - data = zend_hash_update_ind(ht, Z_STR(key), &d); - } else { - data = zend_hash_add_new(ht, Z_STR(key), &d); + if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) { + if (Z_TYPE_P(old_data) == IS_INDIRECT) { + old_data = Z_INDIRECT_P(old_data); } + var_push_dtor(var_hash, old_data); + data = zend_hash_update_ind(ht, Z_STR(key), &d); + } else { + data = zend_hash_add_new(ht, Z_STR(key), &d); } } else if (Z_TYPE(key) == IS_LONG) { /* object properties should include no integers */ @@ -667,7 +668,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key) start = cursor; -#line 671 "ext/standard/var_unserializer.c" +#line 672 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -725,9 +726,9 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key) yy2: ++YYCURSOR; yy3: -#line 1070 "ext/standard/var_unserializer.re" +#line 1071 "ext/standard/var_unserializer.re" { return 0; } -#line 731 "ext/standard/var_unserializer.c" +#line 732 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy17; @@ -774,13 +775,13 @@ yy14: goto yy3; yy15: ++YYCURSOR; -#line 1064 "ext/standard/var_unserializer.re" +#line 1065 "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 784 "ext/standard/var_unserializer.c" +#line 785 "ext/standard/var_unserializer.c" yy17: yych = *++YYCURSOR; if (yybm[0+yych] & 128) { @@ -791,13 +792,13 @@ yy18: goto yy3; yy19: ++YYCURSOR; -#line 725 "ext/standard/var_unserializer.re" +#line 726 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_NULL(rval); return 1; } -#line 801 "ext/standard/var_unserializer.c" +#line 802 "ext/standard/var_unserializer.c" yy21: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1001,7 +1002,7 @@ yy56: goto yy18; yy57: ++YYCURSOR; -#line 675 "ext/standard/var_unserializer.re" +#line 676 "ext/standard/var_unserializer.re" { zend_long id; @@ -1026,7 +1027,7 @@ yy57: return 1; } -#line 1030 "ext/standard/var_unserializer.c" +#line 1031 "ext/standard/var_unserializer.c" yy59: yych = *++YYCURSOR; if (yych == '"') goto yy80; @@ -1037,22 +1038,22 @@ yy60: goto yy18; yy61: ++YYCURSOR; -#line 731 "ext/standard/var_unserializer.re" +#line 732 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_FALSE(rval); return 1; } -#line 1047 "ext/standard/var_unserializer.c" +#line 1048 "ext/standard/var_unserializer.c" yy63: ++YYCURSOR; -#line 737 "ext/standard/var_unserializer.re" +#line 738 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_TRUE(rval); return 1; } -#line 1056 "ext/standard/var_unserializer.c" +#line 1057 "ext/standard/var_unserializer.c" yy65: ++YYCURSOR; if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); @@ -1072,7 +1073,7 @@ yy65: } yy67: ++YYCURSOR; -#line 785 "ext/standard/var_unserializer.re" +#line 786 "ext/standard/var_unserializer.re" { #if SIZEOF_ZEND_LONG == 4 use_double: @@ -1081,7 +1082,7 @@ use_double: ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1085 "ext/standard/var_unserializer.c" +#line 1086 "ext/standard/var_unserializer.c" yy69: yych = *++YYCURSOR; if (yych <= ',') { @@ -1103,7 +1104,7 @@ yy71: goto yy18; yy72: ++YYCURSOR; -#line 743 "ext/standard/var_unserializer.re" +#line 744 "ext/standard/var_unserializer.re" { #if SIZEOF_ZEND_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1129,14 +1130,14 @@ yy72: ZVAL_LONG(rval, parse_iv(start + 2)); return 1; } -#line 1133 "ext/standard/var_unserializer.c" +#line 1134 "ext/standard/var_unserializer.c" yy74: yych = *++YYCURSOR; if (yych == '"') goto yy88; goto yy18; yy75: ++YYCURSOR; -#line 700 "ext/standard/var_unserializer.re" +#line 701 "ext/standard/var_unserializer.re" { zend_long id; @@ -1161,14 +1162,14 @@ yy75: return 1; } -#line 1165 "ext/standard/var_unserializer.c" +#line 1166 "ext/standard/var_unserializer.c" yy77: yych = *++YYCURSOR; if (yych == '"') goto yy90; goto yy18; yy78: ++YYCURSOR; -#line 912 "ext/standard/var_unserializer.re" +#line 913 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; zend_long elements; @@ -1320,10 +1321,10 @@ yy78: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 1324 "ext/standard/var_unserializer.c" +#line 1325 "ext/standard/var_unserializer.c" yy80: ++YYCURSOR; -#line 834 "ext/standard/var_unserializer.re" +#line 835 "ext/standard/var_unserializer.re" { size_t len, maxlen; zend_string *str; @@ -1357,10 +1358,10 @@ yy80: ZVAL_STR(rval, str); return 1; } -#line 1361 "ext/standard/var_unserializer.c" +#line 1362 "ext/standard/var_unserializer.c" yy82: ++YYCURSOR; -#line 868 "ext/standard/var_unserializer.re" +#line 869 "ext/standard/var_unserializer.re" { zend_long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -1393,7 +1394,7 @@ yy82: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 1397 "ext/standard/var_unserializer.c" +#line 1398 "ext/standard/var_unserializer.c" yy84: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1412,7 +1413,7 @@ yy87: goto yy18; yy88: ++YYCURSOR; -#line 901 "ext/standard/var_unserializer.re" +#line 902 "ext/standard/var_unserializer.re" { zend_long elements; if (!var_hash) return 0; @@ -1423,10 +1424,10 @@ yy88: } return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 1427 "ext/standard/var_unserializer.c" +#line 1428 "ext/standard/var_unserializer.c" yy90: ++YYCURSOR; -#line 794 "ext/standard/var_unserializer.re" +#line 795 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -1466,10 +1467,10 @@ yy90: } return 1; } -#line 1470 "ext/standard/var_unserializer.c" +#line 1471 "ext/standard/var_unserializer.c" yy92: ++YYCURSOR; -#line 769 "ext/standard/var_unserializer.re" +#line 770 "ext/standard/var_unserializer.re" { *p = YYCURSOR; @@ -1485,9 +1486,9 @@ yy92: return 1; } -#line 1489 "ext/standard/var_unserializer.c" +#line 1490 "ext/standard/var_unserializer.c" } -#line 1072 "ext/standard/var_unserializer.re" +#line 1073 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 6c9c36fec0..67348af0ba 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -440,60 +440,61 @@ numeric_key: } else { if (EXPECTED(Z_TYPE(key) == IS_STRING)) { string_key: - { + if (Z_TYPE_P(rval) == IS_OBJECT + && zend_hash_num_elements(&Z_OBJCE_P(rval)->properties_info) > 0) { zend_property_info *existing_propinfo; zend_string *new_key; const char *unmangled_class = NULL; const char *unmangled_prop; size_t unmangled_prop_len; + zend_string *unmangled; if (UNEXPECTED(zend_unmangle_property_name_ex(Z_STR(key), &unmangled_class, &unmangled_prop, &unmangled_prop_len) == FAILURE)) { zval_ptr_dtor(&key); return 0; } - if (Z_TYPE_P(rval) == IS_OBJECT) { - zend_string *unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0); + unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0); - if (((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) { + existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled); + if ((existing_propinfo != NULL) + && (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) { + if (existing_propinfo->flags & ZEND_ACC_PROTECTED) { + new_key = zend_mangle_property_name( + "*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0); + zend_string_release(unmangled); + } else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) { + if (unmangled_class != NULL && strcmp(unmangled_class, "*") != 0) { new_key = zend_mangle_property_name( - "*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0); - zend_string_release(unmangled); - } else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) { - if (unmangled_class != NULL && strcmp(unmangled_class, "*") != 0) { - new_key = zend_mangle_property_name( - unmangled_class, strlen(unmangled_class), - ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), - 0); - } else { - new_key = zend_mangle_property_name( - ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name), + unmangled_class, strlen(unmangled_class), ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0); - } - zend_string_release(unmangled); } else { - ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC); - new_key = unmangled; + new_key = zend_mangle_property_name( + ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name), + ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), + 0); } - zend_string_release(Z_STR(key)); - ZVAL_STR(&key, new_key); - } else { zend_string_release(unmangled); + } else { + ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC); + new_key = unmangled; } + zend_string_release(Z_STR(key)); + ZVAL_STR(&key, new_key); + } else { + zend_string_release(unmangled); } + } - if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) { - if (Z_TYPE_P(old_data) == IS_INDIRECT) { - old_data = Z_INDIRECT_P(old_data); - } - var_push_dtor(var_hash, old_data); - data = zend_hash_update_ind(ht, Z_STR(key), &d); - } else { - data = zend_hash_add_new(ht, Z_STR(key), &d); + if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) { + if (Z_TYPE_P(old_data) == IS_INDIRECT) { + old_data = Z_INDIRECT_P(old_data); } + var_push_dtor(var_hash, old_data); + data = zend_hash_update_ind(ht, Z_STR(key), &d); + } else { + data = zend_hash_add_new(ht, Z_STR(key), &d); } } else if (Z_TYPE(key) == IS_LONG) { /* object properties should include no integers */ -- 2.50.1