]> granicus.if.org Git - php/commitdiff
Try to intern unserualized string keys
authorDmitry Stogov <dmitry@zend.com>
Wed, 29 Nov 2017 16:00:57 +0000 (19:00 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 29 Nov 2017 16:00:57 +0000 (19:00 +0300)
ext/standard/var_unserializer.c
ext/standard/var_unserializer.re

index 34140a2bb29e2a848bf0ff24f54d3f310ee7ed7a..42be1898745d7dc7f7e8f4727d078b840a0591fc 100644 (file)
@@ -389,7 +389,7 @@ static inline size_t parse_uiv(const unsigned char *p)
 #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash
 #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash
 
-static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key);
 
 static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
 {
@@ -399,7 +399,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
 
                ZVAL_UNDEF(&key);
 
-               if (!php_var_unserialize_internal(&key, p, max, NULL)) {
+               if (!php_var_unserialize_internal(&key, p, max, NULL, 1)) {
                        zval_ptr_dtor(&key);
                        return 0;
                }
@@ -438,7 +438,7 @@ numeric_key:
 string_key:
                                {
                                        zend_property_info *existing_propinfo;
-                                       zend_string *new_key, *unmangled;
+                                       zend_string *new_key;
                                        const char *unmangled_class = NULL; 
                                        const char *unmangled_prop;
                                        size_t unmangled_prop_len;
@@ -448,35 +448,37 @@ string_key:
                                                return 0;
                                        }
 
-                                       unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0);
-                                       if (Z_TYPE_P(rval) == IS_OBJECT
-                                                       && ((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) {
-                                                       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) {
+                                       if (Z_TYPE_P(rval) == IS_OBJECT) {
+                                               zend_string *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) {
                                                                new_key = zend_mangle_property_name(
-                                                                       unmangled_class, strlen(unmangled_class),
-                                                                       ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
-                                                                       0);
+                                                                       "*", 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),
+                                                                               ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
+                                                                               0);
+                                                               }
+                                                               zend_string_release(unmangled);
                                                        } else {
-                                                               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_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
+                                                               new_key = unmangled;
                                                        }
-                                                       zend_string_release(unmangled);
+                                                       zend_string_release(Z_STR(key));
+                                                       ZVAL_STR(&key, new_key);
                                                } else {
-                                                       ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
-                                                       new_key = unmangled;
+                                                       zend_string_release(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) {
@@ -499,7 +501,7 @@ string_key:
                        }
                }
 
-               if (!php_var_unserialize_internal(data, p, max, var_hash)) {
+               if (!php_var_unserialize_internal(data, p, max, var_hash, 0)) {
                        zval_ptr_dtor(&key);
                        return 0;
                }
@@ -625,7 +627,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
        zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
        int result;
 
-       result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
+       result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU, 0);
 
        if (!result) {
                /* If the unserialization failed, mark all elements that have been added to var_hash
@@ -646,7 +648,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
        return result;
 }
 
-static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key)
 {
        const unsigned char *cursor, *limit, *marker, *start;
        zval *rval_ref;
@@ -665,7 +667,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
        start = cursor;
 
 
-#line 669 "ext/standard/var_unserializer.c"
+#line 671 "ext/standard/var_unserializer.c"
 {
        YYCTYPE yych;
        static const unsigned char yybm[] = {
@@ -723,9 +725,9 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
 yy2:
        ++YYCURSOR;
 yy3:
-#line 1066 "ext/standard/var_unserializer.re"
+#line 1070 "ext/standard/var_unserializer.re"
        { return 0; }
-#line 729 "ext/standard/var_unserializer.c"
+#line 731 "ext/standard/var_unserializer.c"
 yy4:
        yych = *(YYMARKER = ++YYCURSOR);
        if (yych == ':') goto yy17;
@@ -772,13 +774,13 @@ yy14:
        goto yy3;
 yy15:
        ++YYCURSOR;
-#line 1060 "ext/standard/var_unserializer.re"
+#line 1064 "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 782 "ext/standard/var_unserializer.c"
+#line 784 "ext/standard/var_unserializer.c"
 yy17:
        yych = *++YYCURSOR;
        if (yybm[0+yych] & 128) {
@@ -789,13 +791,13 @@ yy18:
        goto yy3;
 yy19:
        ++YYCURSOR;
-#line 723 "ext/standard/var_unserializer.re"
+#line 725 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
        ZVAL_NULL(rval);
        return 1;
 }
-#line 799 "ext/standard/var_unserializer.c"
+#line 801 "ext/standard/var_unserializer.c"
 yy21:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
@@ -999,7 +1001,7 @@ yy56:
        goto yy18;
 yy57:
        ++YYCURSOR;
-#line 673 "ext/standard/var_unserializer.re"
+#line 675 "ext/standard/var_unserializer.re"
        {
        zend_long id;
 
@@ -1024,7 +1026,7 @@ yy57:
 
        return 1;
 }
-#line 1028 "ext/standard/var_unserializer.c"
+#line 1030 "ext/standard/var_unserializer.c"
 yy59:
        yych = *++YYCURSOR;
        if (yych == '"') goto yy80;
@@ -1035,22 +1037,22 @@ yy60:
        goto yy18;
 yy61:
        ++YYCURSOR;
-#line 729 "ext/standard/var_unserializer.re"
+#line 731 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
        ZVAL_FALSE(rval);
        return 1;
 }
-#line 1045 "ext/standard/var_unserializer.c"
+#line 1047 "ext/standard/var_unserializer.c"
 yy63:
        ++YYCURSOR;
-#line 735 "ext/standard/var_unserializer.re"
+#line 737 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
        ZVAL_TRUE(rval);
        return 1;
 }
-#line 1054 "ext/standard/var_unserializer.c"
+#line 1056 "ext/standard/var_unserializer.c"
 yy65:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
@@ -1070,7 +1072,7 @@ yy65:
        }
 yy67:
        ++YYCURSOR;
-#line 783 "ext/standard/var_unserializer.re"
+#line 785 "ext/standard/var_unserializer.re"
        {
 #if SIZEOF_ZEND_LONG == 4
 use_double:
@@ -1079,7 +1081,7 @@ use_double:
        ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
        return 1;
 }
-#line 1083 "ext/standard/var_unserializer.c"
+#line 1085 "ext/standard/var_unserializer.c"
 yy69:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -1101,7 +1103,7 @@ yy71:
        goto yy18;
 yy72:
        ++YYCURSOR;
-#line 741 "ext/standard/var_unserializer.re"
+#line 743 "ext/standard/var_unserializer.re"
        {
 #if SIZEOF_ZEND_LONG == 4
        int digits = YYCURSOR - start - 3;
@@ -1127,14 +1129,14 @@ yy72:
        ZVAL_LONG(rval, parse_iv(start + 2));
        return 1;
 }
-#line 1131 "ext/standard/var_unserializer.c"
+#line 1133 "ext/standard/var_unserializer.c"
 yy74:
        yych = *++YYCURSOR;
        if (yych == '"') goto yy88;
        goto yy18;
 yy75:
        ++YYCURSOR;
-#line 698 "ext/standard/var_unserializer.re"
+#line 700 "ext/standard/var_unserializer.re"
        {
        zend_long id;
 
@@ -1159,14 +1161,14 @@ yy75:
 
        return 1;
 }
-#line 1163 "ext/standard/var_unserializer.c"
+#line 1165 "ext/standard/var_unserializer.c"
 yy77:
        yych = *++YYCURSOR;
        if (yych == '"') goto yy90;
        goto yy18;
 yy78:
        ++YYCURSOR;
-#line 908 "ext/standard/var_unserializer.re"
+#line 912 "ext/standard/var_unserializer.re"
        {
        size_t len, len2, len3, maxlen;
        zend_long elements;
@@ -1318,10 +1320,10 @@ yy78:
 
        return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 1322 "ext/standard/var_unserializer.c"
+#line 1324 "ext/standard/var_unserializer.c"
 yy80:
        ++YYCURSOR;
-#line 830 "ext/standard/var_unserializer.re"
+#line 834 "ext/standard/var_unserializer.re"
        {
        size_t len, maxlen;
        zend_string *str;
@@ -1355,10 +1357,10 @@ yy80:
        ZVAL_STR(rval, str);
        return 1;
 }
-#line 1359 "ext/standard/var_unserializer.c"
+#line 1361 "ext/standard/var_unserializer.c"
 yy82:
        ++YYCURSOR;
-#line 864 "ext/standard/var_unserializer.re"
+#line 868 "ext/standard/var_unserializer.re"
        {
        zend_long elements = parse_iv(start + 2);
        /* use iv() not uiv() in order to check data range */
@@ -1391,7 +1393,7 @@ yy82:
 
        return finish_nested_data(UNSERIALIZE_PASSTHRU);
 }
-#line 1395 "ext/standard/var_unserializer.c"
+#line 1397 "ext/standard/var_unserializer.c"
 yy84:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
@@ -1410,7 +1412,7 @@ yy87:
        goto yy18;
 yy88:
        ++YYCURSOR;
-#line 897 "ext/standard/var_unserializer.re"
+#line 901 "ext/standard/var_unserializer.re"
        {
        zend_long elements;
     if (!var_hash) return 0;
@@ -1421,10 +1423,10 @@ yy88:
        }
        return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 1425 "ext/standard/var_unserializer.c"
+#line 1427 "ext/standard/var_unserializer.c"
 yy90:
        ++YYCURSOR;
-#line 792 "ext/standard/var_unserializer.re"
+#line 794 "ext/standard/var_unserializer.re"
        {
        size_t len, maxlen;
        char *str;
@@ -1457,15 +1459,17 @@ yy90:
                ZVAL_EMPTY_STRING(rval);
        } else if (len == 1) {
                ZVAL_INTERNED_STR(rval, ZSTR_CHAR((zend_uchar)*str));
+       } else if (as_key) {
+               ZVAL_STR(rval, zend_string_init_interned(str, len, 0));
        } else {
                ZVAL_STRINGL(rval, str, len);
        }
        return 1;
 }
-#line 1466 "ext/standard/var_unserializer.c"
+#line 1470 "ext/standard/var_unserializer.c"
 yy92:
        ++YYCURSOR;
-#line 767 "ext/standard/var_unserializer.re"
+#line 769 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
 
@@ -1481,9 +1485,9 @@ yy92:
 
        return 1;
 }
-#line 1485 "ext/standard/var_unserializer.c"
+#line 1489 "ext/standard/var_unserializer.c"
 }
-#line 1068 "ext/standard/var_unserializer.re"
+#line 1072 "ext/standard/var_unserializer.re"
 
 
        return 0;
index 86d35027468f8a974efffdcb4a9ff5f5627ba315..6c9c36fec0502705cf0d25239ef1c21acb2ad1dd 100644 (file)
@@ -393,7 +393,7 @@ static inline size_t parse_uiv(const unsigned char *p)
 #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash
 #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash
 
-static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key);
 
 static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
 {
@@ -403,7 +403,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
 
                ZVAL_UNDEF(&key);
 
-               if (!php_var_unserialize_internal(&key, p, max, NULL)) {
+               if (!php_var_unserialize_internal(&key, p, max, NULL, 1)) {
                        zval_ptr_dtor(&key);
                        return 0;
                }
@@ -442,7 +442,7 @@ numeric_key:
 string_key:
                                {
                                        zend_property_info *existing_propinfo;
-                                       zend_string *new_key, *unmangled;
+                                       zend_string *new_key;
                                        const char *unmangled_class = NULL; 
                                        const char *unmangled_prop;
                                        size_t unmangled_prop_len;
@@ -452,35 +452,37 @@ string_key:
                                                return 0;
                                        }
 
-                                       unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0);
-                                       if (Z_TYPE_P(rval) == IS_OBJECT
-                                                       && ((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) {
-                                                       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) {
+                                       if (Z_TYPE_P(rval) == IS_OBJECT) {
+                                               zend_string *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) {
                                                                new_key = zend_mangle_property_name(
-                                                                       unmangled_class, strlen(unmangled_class),
-                                                                       ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
-                                                                       0);
+                                                                       "*", 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),
+                                                                               ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
+                                                                               0);
+                                                               }
+                                                               zend_string_release(unmangled);
                                                        } else {
-                                                               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_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
+                                                               new_key = unmangled;
                                                        }
-                                                       zend_string_release(unmangled);
+                                                       zend_string_release(Z_STR(key));
+                                                       ZVAL_STR(&key, new_key);
                                                } else {
-                                                       ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
-                                                       new_key = unmangled;
+                                                       zend_string_release(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) {
@@ -503,7 +505,7 @@ string_key:
                        }
                }
 
-               if (!php_var_unserialize_internal(data, p, max, var_hash)) {
+               if (!php_var_unserialize_internal(data, p, max, var_hash, 0)) {
                        zval_ptr_dtor(&key);
                        return 0;
                }
@@ -629,7 +631,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
        zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
        int result;
 
-       result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
+       result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU, 0);
 
        if (!result) {
                /* If the unserialization failed, mark all elements that have been added to var_hash
@@ -650,7 +652,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
        return result;
 }
 
-static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key)
 {
        const unsigned char *cursor, *limit, *marker, *start;
        zval *rval_ref;
@@ -821,6 +823,8 @@ use_double:
                ZVAL_EMPTY_STRING(rval);
        } else if (len == 1) {
                ZVAL_INTERNED_STR(rval, ZSTR_CHAR((zend_uchar)*str));
+       } else if (as_key) {
+               ZVAL_STR(rval, zend_string_init_interned(str, len, 0));
        } else {
                ZVAL_STRINGL(rval, str, len);
        }