]> granicus.if.org Git - php/commitdiff
Improved unserialize()
authorDmitry Stogov <dmitry@zend.com>
Mon, 22 Dec 2014 23:49:33 +0000 (02:49 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 22 Dec 2014 23:49:33 +0000 (02:49 +0300)
ext/standard/var_unserializer.c
ext/standard/var_unserializer.re

index bcd00a6eba284bdedd4f67197cb9eb94ddc6ff62..54155e3168b1803e60c305cb089ca2fc0c12966a 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.7.5 */
+/* Generated by re2c 0.13.5 */
 #line 1 "ext/standard/var_unserializer.re"
 /*
   +----------------------------------------------------------------------+
@@ -322,10 +322,11 @@ 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, HashTable *classes
 #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes
 
-static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
+static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
 {
        while (elements-- > 0) {
                zval key, *data, d, *old_data;
+               zend_ulong idx;
 
                ZVAL_UNDEF(&key);
 
@@ -334,41 +335,55 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend
                        return 0;
                }
 
-               if (Z_TYPE(key) != IS_LONG && Z_TYPE(key) != IS_STRING) {
-                       zval_dtor(&key);
-                       return 0;
-               }
-
                data = NULL;
                ZVAL_UNDEF(&d);
 
                if (!objprops) {
-                       switch (Z_TYPE(key)) {
-                       case IS_LONG:
-                               if ((old_data = zend_hash_index_find(ht, Z_LVAL(key))) != NULL) {
+                       if (Z_TYPE(key) == IS_LONG) {
+                               idx = Z_LVAL(key);
+numeric_key:
+                               if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
                                        //??? update hash
                                        var_push_dtor(var_hash, old_data);
+                                       data = zend_hash_index_update(ht, idx, &d);
+                               } else {
+                                       data = zend_hash_index_add_new(ht, idx, &d);
+                               }
+                       } else if (Z_TYPE(key) == IS_STRING) {
+                               if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
+                                       goto numeric_key; 
                                }
-                               data = zend_hash_index_update(ht, Z_LVAL(key), &d);
-                               break;
-                       case IS_STRING:
-                               if ((old_data = zend_symtable_find(ht, Z_STR(key))) != NULL) {
+                               if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
                                        //??? update hash
                                        var_push_dtor(var_hash, old_data);
+                                       data = zend_hash_update(ht, Z_STR(key), &d);
+                               } else {
+                                       data = zend_hash_add_new(ht, Z_STR(key), &d);
                                }
-                               data = zend_symtable_update(ht, Z_STR(key), &d);
-                               break;
+                       } else {
+                               zval_dtor(&key);
+                               return 0;
                        }
                } else {
-                       /* object properties should include no integers */
-                       convert_to_string(&key);
-                       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);
+                       if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
+string_key:
+                               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);
                                }
-                               var_push_dtor(var_hash, old_data);
-                       } 
-                       data = zend_hash_update_ind(ht, Z_STR(key), &d);
+                       } else if (Z_TYPE(key) == IS_LONG) {
+                               /* object properties should include no integers */
+                               convert_to_string(&key);
+                               goto string_key;
+                       } else {
+                               zval_dtor(&key);
+                               return 0;
+                       }
                }
                
                zval_dtor(&key);
@@ -507,7 +522,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
        start = cursor;
 
 
-#line 511 "ext/standard/var_unserializer.c"
+#line 526 "ext/standard/var_unserializer.c"
 {
        YYCTYPE yych;
        static const unsigned char yybm[] = {
@@ -567,9 +582,9 @@ yy2:
        yych = *(YYMARKER = ++YYCURSOR);
        if (yych == ':') goto yy95;
 yy3:
-#line 858 "ext/standard/var_unserializer.re"
+#line 873 "ext/standard/var_unserializer.re"
        { return 0; }
-#line 573 "ext/standard/var_unserializer.c"
+#line 588 "ext/standard/var_unserializer.c"
 yy4:
        yych = *(YYMARKER = ++YYCURSOR);
        if (yych == ':') goto yy89;
@@ -612,13 +627,13 @@ yy13:
        goto yy3;
 yy14:
        ++YYCURSOR;
-#line 852 "ext/standard/var_unserializer.re"
+#line 867 "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 622 "ext/standard/var_unserializer.c"
+#line 637 "ext/standard/var_unserializer.c"
 yy16:
        yych = *++YYCURSOR;
        goto yy3;
@@ -644,12 +659,11 @@ yy20:
        if (yybm[0+yych] & 128) {
                goto yy20;
        }
-       if (yych <= '/') goto yy18;
-       if (yych >= ';') goto yy18;
+       if (yych != ':') goto yy18;
        yych = *++YYCURSOR;
        if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 707 "ext/standard/var_unserializer.re"
+#line 722 "ext/standard/var_unserializer.re"
        {
        size_t len, len2, len3, maxlen;
        zend_long elements;
@@ -794,7 +808,7 @@ yy20:
 
        return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 798 "ext/standard/var_unserializer.c"
+#line 812 "ext/standard/var_unserializer.c"
 yy25:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -819,7 +833,7 @@ yy27:
        yych = *++YYCURSOR;
        if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 699 "ext/standard/var_unserializer.re"
+#line 714 "ext/standard/var_unserializer.re"
        {
 
 //???  INIT_PZVAL(rval);
@@ -827,7 +841,7 @@ yy27:
        return object_common2(UNSERIALIZE_PASSTHRU,
                        object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
 }
-#line 831 "ext/standard/var_unserializer.c"
+#line 845 "ext/standard/var_unserializer.c"
 yy32:
        yych = *++YYCURSOR;
        if (yych == '+') goto yy33;
@@ -848,7 +862,7 @@ yy34:
        yych = *++YYCURSOR;
        if (yych != '{') goto yy18;
        ++YYCURSOR;
-#line 678 "ext/standard/var_unserializer.re"
+#line 693 "ext/standard/var_unserializer.re"
        {
        zend_long elements = parse_iv(start + 2);
        /* use iv() not uiv() in order to check data range */
@@ -869,7 +883,7 @@ yy34:
 
        return finish_nested_data(UNSERIALIZE_PASSTHRU);
 }
-#line 873 "ext/standard/var_unserializer.c"
+#line 887 "ext/standard/var_unserializer.c"
 yy39:
        yych = *++YYCURSOR;
        if (yych == '+') goto yy40;
@@ -890,7 +904,7 @@ yy41:
        yych = *++YYCURSOR;
        if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 650 "ext/standard/var_unserializer.re"
+#line 665 "ext/standard/var_unserializer.re"
        {
        size_t len, maxlen;
        zend_string *str;
@@ -918,7 +932,7 @@ yy41:
        ZVAL_STR(rval, str);
        return 1;
 }
-#line 922 "ext/standard/var_unserializer.c"
+#line 936 "ext/standard/var_unserializer.c"
 yy46:
        yych = *++YYCURSOR;
        if (yych == '+') goto yy47;
@@ -939,7 +953,7 @@ yy48:
        yych = *++YYCURSOR;
        if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 623 "ext/standard/var_unserializer.re"
+#line 638 "ext/standard/var_unserializer.re"
        {
        size_t len, maxlen;
        char *str;
@@ -966,7 +980,7 @@ yy48:
        ZVAL_STRINGL(rval, str, len);
        return 1;
 }
-#line 970 "ext/standard/var_unserializer.c"
+#line 984 "ext/standard/var_unserializer.c"
 yy53:
        yych = *++YYCURSOR;
        if (yych <= '/') {
@@ -1054,7 +1068,7 @@ yy61:
        }
 yy63:
        ++YYCURSOR;
-#line 614 "ext/standard/var_unserializer.re"
+#line 629 "ext/standard/var_unserializer.re"
        {
 #if SIZEOF_ZEND_LONG == 4
 use_double:
@@ -1063,7 +1077,7 @@ use_double:
        ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
        return 1;
 }
-#line 1067 "ext/standard/var_unserializer.c"
+#line 1081 "ext/standard/var_unserializer.c"
 yy65:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -1122,7 +1136,7 @@ yy73:
        yych = *++YYCURSOR;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 598 "ext/standard/var_unserializer.re"
+#line 613 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
 
@@ -1138,7 +1152,7 @@ yy73:
 
        return 1;
 }
-#line 1142 "ext/standard/var_unserializer.c"
+#line 1156 "ext/standard/var_unserializer.c"
 yy76:
        yych = *++YYCURSOR;
        if (yych == 'N') goto yy73;
@@ -1165,7 +1179,7 @@ yy79:
        if (yych <= '9') goto yy79;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 572 "ext/standard/var_unserializer.re"
+#line 587 "ext/standard/var_unserializer.re"
        {
 #if SIZEOF_ZEND_LONG == 4
        int digits = YYCURSOR - start - 3;
@@ -1191,7 +1205,7 @@ yy79:
        ZVAL_LONG(rval, parse_iv(start + 2));
        return 1;
 }
-#line 1195 "ext/standard/var_unserializer.c"
+#line 1209 "ext/standard/var_unserializer.c"
 yy83:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
@@ -1199,22 +1213,22 @@ yy83:
        yych = *++YYCURSOR;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 566 "ext/standard/var_unserializer.re"
+#line 581 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
        ZVAL_BOOL(rval, parse_iv(start + 2));
        return 1;
 }
-#line 1209 "ext/standard/var_unserializer.c"
+#line 1223 "ext/standard/var_unserializer.c"
 yy87:
        ++YYCURSOR;
-#line 560 "ext/standard/var_unserializer.re"
+#line 575 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
        ZVAL_NULL(rval);
        return 1;
 }
-#line 1218 "ext/standard/var_unserializer.c"
+#line 1232 "ext/standard/var_unserializer.c"
 yy89:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -1237,7 +1251,7 @@ yy91:
        if (yych <= '9') goto yy91;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 537 "ext/standard/var_unserializer.re"
+#line 552 "ext/standard/var_unserializer.re"
        {
        zend_long id;
 
@@ -1260,7 +1274,7 @@ yy91:
        
        return 1;
 }
-#line 1264 "ext/standard/var_unserializer.c"
+#line 1278 "ext/standard/var_unserializer.c"
 yy95:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -1283,7 +1297,7 @@ yy97:
        if (yych <= '9') goto yy97;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 515 "ext/standard/var_unserializer.re"
+#line 530 "ext/standard/var_unserializer.re"
        {
        zend_long id;
 
@@ -1305,9 +1319,9 @@ yy97:
        
        return 1;
 }
-#line 1309 "ext/standard/var_unserializer.c"
+#line 1323 "ext/standard/var_unserializer.c"
 }
-#line 860 "ext/standard/var_unserializer.re"
+#line 875 "ext/standard/var_unserializer.re"
 
 
        return 0;
index 0efd6347dee33b1d55d5b253b9f263317f45c050..50d5949a2e64b84c6dca0329dff51723cf7ce28f 100644 (file)
@@ -326,10 +326,11 @@ 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, HashTable *classes
 #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes
 
-static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
+static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
 {
        while (elements-- > 0) {
                zval key, *data, d, *old_data;
+               zend_ulong idx;
 
                ZVAL_UNDEF(&key);
 
@@ -338,41 +339,55 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend
                        return 0;
                }
 
-               if (Z_TYPE(key) != IS_LONG && Z_TYPE(key) != IS_STRING) {
-                       zval_dtor(&key);
-                       return 0;
-               }
-
                data = NULL;
                ZVAL_UNDEF(&d);
 
                if (!objprops) {
-                       switch (Z_TYPE(key)) {
-                       case IS_LONG:
-                               if ((old_data = zend_hash_index_find(ht, Z_LVAL(key))) != NULL) {
+                       if (Z_TYPE(key) == IS_LONG) {
+                               idx = Z_LVAL(key);
+numeric_key:
+                               if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
                                        //??? update hash
                                        var_push_dtor(var_hash, old_data);
+                                       data = zend_hash_index_update(ht, idx, &d);
+                               } else {
+                                       data = zend_hash_index_add_new(ht, idx, &d);
+                               }
+                       } else if (Z_TYPE(key) == IS_STRING) {
+                               if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
+                                       goto numeric_key; 
                                }
-                               data = zend_hash_index_update(ht, Z_LVAL(key), &d);
-                               break;
-                       case IS_STRING:
-                               if ((old_data = zend_symtable_find(ht, Z_STR(key))) != NULL) {
+                               if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
                                        //??? update hash
                                        var_push_dtor(var_hash, old_data);
+                                       data = zend_hash_update(ht, Z_STR(key), &d);
+                               } else {
+                                       data = zend_hash_add_new(ht, Z_STR(key), &d);
                                }
-                               data = zend_symtable_update(ht, Z_STR(key), &d);
-                               break;
+                       } else {
+                               zval_dtor(&key);
+                               return 0;
                        }
                } else {
-                       /* object properties should include no integers */
-                       convert_to_string(&key);
-                       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);
+                       if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
+string_key:
+                               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);
                                }
-                               var_push_dtor(var_hash, old_data);
-                       } 
-                       data = zend_hash_update_ind(ht, Z_STR(key), &d);
+                       } else if (Z_TYPE(key) == IS_LONG) {
+                               /* object properties should include no integers */
+                               convert_to_string(&key);
+                               goto string_key;
+                       } else {
+                               zval_dtor(&key);
+                               return 0;
+                       }
                }
                
                zval_dtor(&key);