]> granicus.if.org Git - php/commitdiff
Hide (un)serialize data from ABI
authorNikita Popov <nikic@php.net>
Wed, 10 Aug 2016 10:51:48 +0000 (12:51 +0200)
committerNikita Popov <nikic@php.net>
Mon, 15 Aug 2016 20:42:27 +0000 (22:42 +0200)
The (UN)SERIALIZE_INIT/DESTROY macros now go through non-inlined
functions, so any changes to them will apply to extensions without
rebuilds.

Additionally, the (un)serialize_data structures are now no longer
exported.

This means that we are allowed to change these structures in patch
releases without breaking the ABI.

ext/standard/php_var.h
ext/standard/var.c
ext/standard/var_unserializer.c
ext/standard/var_unserializer.re

index 4afefbe95aef9d5f340c69db84daf2185b5e07f7..80208d29ee71f2c91060c88c07ae65ac9b526f9b 100644 (file)
@@ -38,18 +38,6 @@ PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf);
 
 PHPAPI void php_debug_zval_dump(zval *struc, int level);
 
-struct php_serialize_data {
-       HashTable ht;
-       uint32_t n;
-};
-
-struct php_unserialize_data {
-       void *first;
-       void *last;
-       void *first_dtor;
-       void *last_dtor;
-};
-
 typedef struct php_serialize_data *php_serialize_data_t;
 typedef struct php_unserialize_data *php_unserialize_data_t;
 
@@ -59,61 +47,22 @@ PHPAPI int php_var_unserialize_ref(zval *rval, const unsigned char **p, const un
 PHPAPI int php_var_unserialize_intern(zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash);
 PHPAPI int php_var_unserialize_ex(zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes);
 
+PHPAPI php_serialize_data_t php_var_serialize_init(void);
+PHPAPI void php_var_serialize_destroy(php_serialize_data_t d);
+PHPAPI php_unserialize_data_t php_var_unserialize_init(void);
+PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d);
+
 #define PHP_VAR_SERIALIZE_INIT(d) \
-do  { \
-       /* fprintf(stderr, "SERIALIZE_INIT      == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
-       if (BG(serialize_lock) || !BG(serialize).level) { \
-               (d) = (php_serialize_data_t) emalloc(sizeof(struct php_serialize_data)); \
-               zend_hash_init(&(d)->ht, 16, NULL, ZVAL_PTR_DTOR, 0); \
-               (d)->n = 0; \
-               if (!BG(serialize_lock)) { \
-                       BG(serialize).data = d; \
-                       BG(serialize).level = 1; \
-               } \
-       } else { \
-               (d) = BG(serialize).data; \
-               ++BG(serialize).level; \
-       } \
-} while(0)
+       (d) = php_var_serialize_init()
 
 #define PHP_VAR_SERIALIZE_DESTROY(d) \
-do { \
-       /* fprintf(stderr, "SERIALIZE_DESTROY   == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
-       if (BG(serialize_lock) || BG(serialize).level == 1) { \
-               zend_hash_destroy(&(d)->ht); \
-               efree((d)); \
-       } \
-       if (!BG(serialize_lock) && !--BG(serialize).level) { \
-               BG(serialize).data = NULL; \
-       } \
-} while (0)
+       php_var_serialize_destroy(d)
 
 #define PHP_VAR_UNSERIALIZE_INIT(d) \
-do { \
-       /* fprintf(stderr, "UNSERIALIZE_INIT    == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */ \
-       if (BG(serialize_lock) || !BG(unserialize).level) { \
-               (d) = (php_unserialize_data_t)ecalloc(1, sizeof(struct php_unserialize_data)); \
-               if (!BG(serialize_lock)) { \
-                       BG(unserialize).data = (d); \
-                       BG(unserialize).level = 1; \
-               } \
-       } else { \
-               (d) = BG(unserialize).data; \
-               ++BG(unserialize).level; \
-       } \
-} while (0)
+       (d) = php_var_unserialize_init()
 
 #define PHP_VAR_UNSERIALIZE_DESTROY(d) \
-do { \
-       /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */ \
-       if (BG(serialize_lock) || BG(unserialize).level == 1) { \
-               var_destroy(&(d)); \
-               efree((d)); \
-       } \
-       if (!BG(serialize_lock) && !--BG(unserialize).level) { \
-               BG(unserialize).data = NULL; \
-       } \
-} while (0)
+       php_var_unserialize_destroy(d)
 
 PHPAPI void var_replace(php_unserialize_data_t *var_hash, zval *ozval, zval *nzval);
 PHPAPI void var_push_dtor(php_unserialize_data_t *var_hash, zval *val);
index 809161afecad4be3001979d8e7772de7b19a883a..cc033aada7ec43a8e5360ae4c329ec62f52a4e53 100644 (file)
 #include "php_incomplete_class.h"
 /* }}} */
 
+struct php_serialize_data {
+       HashTable ht;
+       uint32_t n;
+};
+
 #define COMMON (is_ref ? "&" : "")
 
 static void php_array_element_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
@@ -993,6 +998,35 @@ PHPAPI void php_var_serialize(smart_str *buf, zval *struc, php_serialize_data_t
 }
 /* }}} */
 
+PHPAPI php_serialize_data_t php_var_serialize_init() {
+       struct php_serialize_data *d;
+       /* fprintf(stderr, "SERIALIZE_INIT      == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */
+       if (BG(serialize_lock) || !BG(serialize).level) {
+               d = emalloc(sizeof(struct php_serialize_data));
+               zend_hash_init(&d->ht, 16, NULL, ZVAL_PTR_DTOR, 0);
+               d->n = 0;
+               if (!BG(serialize_lock)) {
+                       BG(serialize).data = d;
+                       BG(serialize).level = 1;
+               }
+       } else {
+               d = BG(serialize).data;
+               ++BG(serialize).level;
+       }
+       return d;
+}
+
+PHPAPI void php_var_serialize_destroy(php_serialize_data_t d) {
+       /* fprintf(stderr, "SERIALIZE_DESTROY   == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */
+       if (BG(serialize_lock) || BG(serialize).level == 1) {
+               zend_hash_destroy(&d->ht);
+               efree(d);
+       }
+       if (!BG(serialize_lock) && !--BG(serialize).level) {
+               BG(serialize).data = NULL;
+       }
+}
+
 /* {{{ proto string serialize(mixed variable)
    Returns a string representation of variable (which can later be unserialized) */
 PHP_FUNCTION(serialize)
index e2b95174d7058f5d9b4a0a2dd67e28b33ea1e597..f96fdb40d6c008f39a7973c3e1545dc3c2af855b 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 */
+/* Generated by re2c 0.16 */
 #line 1 "ext/standard/var_unserializer.re"
 /*
   +----------------------------------------------------------------------+
 #include "ext/standard/php_var.h"
 #include "php_incomplete_class.h"
 
+struct php_unserialize_data {
+       void *first;
+       void *last;
+       void *first_dtor;
+       void *last_dtor;
+};
+
+PHPAPI php_unserialize_data_t php_var_unserialize_init() {
+       php_unserialize_data_t d;
+       /* fprintf(stderr, "UNSERIALIZE_INIT    == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
+       if (BG(serialize_lock) || !BG(unserialize).level) {
+               d = ecalloc(1, sizeof(struct php_unserialize_data));
+               if (!BG(serialize_lock)) {
+                       BG(unserialize).data = d;
+                       BG(unserialize).level = 1;
+               }
+       } else {
+               d = BG(unserialize).data;
+               ++BG(unserialize).level;
+       }
+       return d;
+}
+
+PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d) {
+       /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
+       if (BG(serialize_lock) || BG(unserialize).level == 1) {
+               var_destroy(&d);
+               efree(d);
+       }
+       if (!BG(serialize_lock) && !--BG(unserialize).level) {
+               BG(unserialize).data = NULL;
+       }
+}
+
+
 /* {{{ reference-handling for unserializer: var_* */
 #define VAR_ENTRIES_MAX 1024
 #define VAR_ENTRIES_DBG 0
@@ -238,7 +273,7 @@ static inline int unserialize_allowed_class(zend_string *class_name, HashTable *
 #define YYMARKER marker
 
 
-#line 246 "ext/standard/var_unserializer.re"
+#line 281 "ext/standard/var_unserializer.re"
 
 
 
@@ -514,7 +549,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
        start = cursor;
 
 
-#line 518 "ext/standard/var_unserializer.c"
+#line 553 "ext/standard/var_unserializer.c"
 {
        YYCTYPE yych;
        static const unsigned char yybm[] = {
@@ -551,529 +586,414 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
                  0,   0,   0,   0,   0,   0,   0,   0, 
                  0,   0,   0,   0,   0,   0,   0,   0, 
        };
-
        if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
        yych = *YYCURSOR;
        switch (yych) {
        case 'C':
-       case 'O':       goto yy13;
+       case 'O':       goto yy4;
        case 'N':       goto yy5;
-       case 'R':       goto yy2;
-       case 'S':       goto yy10;
-       case 'a':       goto yy11;
-       case 'b':       goto yy6;
-       case 'd':       goto yy8;
-       case 'i':       goto yy7;
+       case 'R':       goto yy6;
+       case 'S':       goto yy7;
+       case 'a':       goto yy8;
+       case 'b':       goto yy9;
+       case 'd':       goto yy10;
+       case 'i':       goto yy11;
        case 'o':       goto yy12;
-       case 'r':       goto yy4;
-       case 's':       goto yy9;
-       case '}':       goto yy14;
-       default:        goto yy16;
+       case 'r':       goto yy13;
+       case 's':       goto yy14;
+       case '}':       goto yy15;
+       default:        goto yy2;
        }
 yy2:
-       yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy95;
+       ++YYCURSOR;
 yy3:
-#line 884 "ext/standard/var_unserializer.re"
+#line 919 "ext/standard/var_unserializer.re"
        { return 0; }
-#line 580 "ext/standard/var_unserializer.c"
+#line 613 "ext/standard/var_unserializer.c"
 yy4:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy89;
+       if (yych == ':') goto yy17;
        goto yy3;
 yy5:
        yych = *++YYCURSOR;
-       if (yych == ';') goto yy87;
+       if (yych == ';') goto yy19;
        goto yy3;
 yy6:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy83;
+       if (yych == ':') goto yy21;
        goto yy3;
 yy7:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy77;
+       if (yych == ':') goto yy22;
        goto yy3;
 yy8:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy53;
+       if (yych == ':') goto yy23;
        goto yy3;
 yy9:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy46;
+       if (yych == ':') goto yy24;
        goto yy3;
 yy10:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy39;
+       if (yych == ':') goto yy25;
        goto yy3;
 yy11:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy32;
+       if (yych == ':') goto yy26;
        goto yy3;
 yy12:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy25;
+       if (yych == ':') goto yy27;
        goto yy3;
 yy13:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy17;
+       if (yych == ':') goto yy28;
        goto yy3;
 yy14:
+       yych = *(YYMARKER = ++YYCURSOR);
+       if (yych == ':') goto yy29;
+       goto yy3;
+yy15:
        ++YYCURSOR;
-#line 878 "ext/standard/var_unserializer.re"
+#line 913 "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 629 "ext/standard/var_unserializer.c"
-yy16:
-       yych = *++YYCURSOR;
-       goto yy3;
+#line 666 "ext/standard/var_unserializer.c"
 yy17:
        yych = *++YYCURSOR;
        if (yybm[0+yych] & 128) {
-               goto yy20;
+               goto yy31;
        }
-       if (yych == '+') goto yy19;
+       if (yych == '+') goto yy30;
 yy18:
        YYCURSOR = YYMARKER;
        goto yy3;
 yy19:
+       ++YYCURSOR;
+#line 608 "ext/standard/var_unserializer.re"
+       {
+       *p = YYCURSOR;
+       ZVAL_NULL(rval);
+       return 1;
+}
+#line 684 "ext/standard/var_unserializer.c"
+yy21:
        yych = *++YYCURSOR;
-       if (yybm[0+yych] & 128) {
-               goto yy20;
+       if (yych <= ',') {
+               if (yych == '+') goto yy33;
+               goto yy18;
+       } else {
+               if (yych <= '-') goto yy33;
+               if (yych <= '/') goto yy18;
+               if (yych <= '9') goto yy34;
+               goto yy18;
        }
+yy22:
+       yych = *++YYCURSOR;
+       if (yych == '+') goto yy36;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy37;
        goto yy18;
-yy20:
-       ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
-       yych = *YYCURSOR;
-       if (yybm[0+yych] & 128) {
-               goto yy20;
-       }
-       if (yych != ':') goto yy18;
+yy23:
        yych = *++YYCURSOR;
-       if (yych != '"') goto yy18;
-       ++YYCURSOR;
-#line 733 "ext/standard/var_unserializer.re"
-       {
-       size_t len, len2, len3, maxlen;
-       zend_long elements;
-       char *str;
-       zend_string *class_name;
-       zend_class_entry *ce;
-       int incomplete_class = 0;
-
-       int custom_object = 0;
-
-       zval user_func;
-       zval retval;
-       zval args[1];
-
-    if (!var_hash) return 0;
-       if (*start == 'C') {
-               custom_object = 1;
-       }
-
-       len2 = len = parse_uiv(start + 2);
-       maxlen = max - YYCURSOR;
-       if (maxlen < len || len == 0) {
-               *p = start + 2;
-               return 0;
-       }
-
-       str = (char*)YYCURSOR;
-
-       YYCURSOR += len;
-
-       if (*(YYCURSOR) != '"') {
-               *p = YYCURSOR;
-               return 0;
-       }
-       if (*(YYCURSOR+1) != ':') {
-               *p = YYCURSOR+1;
-               return 0;
-       }
-
-       len3 = strspn(str, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\");
-       if (len3 != len)
-       {
-               *p = YYCURSOR + len3 - len;
-               return 0;
-       }
-
-       class_name = zend_string_init(str, len, 0);
-
-       do {
-               if(!unserialize_allowed_class(class_name, classes)) {
-                       incomplete_class = 1;
-                       ce = PHP_IC_ENTRY;
-                       break;
-               }
-
-               /* Try to find class directly */
-               BG(serialize_lock)++;
-               ce = zend_lookup_class(class_name);
-               if (ce) {
-                       BG(serialize_lock)--;
-                       if (EG(exception)) {
-                               zend_string_release(class_name);
-                               return 0;
-                       }
-                       break;
-               }
-               BG(serialize_lock)--;
-
-               if (EG(exception)) {
-                       zend_string_release(class_name);
-                       return 0;
-               }
-
-               /* Check for unserialize callback */
-               if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
-                       incomplete_class = 1;
-                       ce = PHP_IC_ENTRY;
-                       break;
-               }
-
-               /* Call unserialize callback */
-               ZVAL_STRING(&user_func, PG(unserialize_callback_func));
-
-               ZVAL_STR_COPY(&args[0], class_name);
-               BG(serialize_lock)++;
-               if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
-                       BG(serialize_lock)--;
-                       if (EG(exception)) {
-                               zend_string_release(class_name);
-                               zval_ptr_dtor(&user_func);
-                               zval_ptr_dtor(&args[0]);
-                               return 0;
-                       }
-                       php_error_docref(NULL, E_WARNING, "defined (%s) but not found", Z_STRVAL(user_func));
-                       incomplete_class = 1;
-                       ce = PHP_IC_ENTRY;
-                       zval_ptr_dtor(&user_func);
-                       zval_ptr_dtor(&args[0]);
-                       break;
-               }
-               BG(serialize_lock)--;
-               zval_ptr_dtor(&retval);
-               if (EG(exception)) {
-                       zend_string_release(class_name);
-                       zval_ptr_dtor(&user_func);
-                       zval_ptr_dtor(&args[0]);
-                       return 0;
-               }
-
-               /* The callback function may have defined the class */
-               if ((ce = zend_lookup_class(class_name)) == NULL) {
-                       php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
-                       incomplete_class = 1;
-                       ce = PHP_IC_ENTRY;
+       if (yych == '+') goto yy39;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy40;
+       goto yy18;
+yy24:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '1') goto yy42;
+       goto yy18;
+yy25:
+       yych = *++YYCURSOR;
+       if (yych <= '/') {
+               if (yych <= ',') {
+                       if (yych == '+') goto yy43;
+                       goto yy18;
+               } else {
+                       if (yych <= '-') goto yy44;
+                       if (yych <= '.') goto yy45;
+                       goto yy18;
                }
-
-               zval_ptr_dtor(&user_func);
-               zval_ptr_dtor(&args[0]);
-               break;
-       } while (1);
-
-       *p = YYCURSOR;
-
-       if (custom_object) {
-               int ret;
-
-               ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
-
-               if (ret && incomplete_class) {
-                       php_store_class_name(rval, ZSTR_VAL(class_name), len2);
+       } else {
+               if (yych <= 'I') {
+                       if (yych <= '9') goto yy46;
+                       if (yych <= 'H') goto yy18;
+                       goto yy48;
+               } else {
+                       if (yych == 'N') goto yy49;
+                       goto yy18;
                }
-               zend_string_release(class_name);
-               return ret;
        }
-
-       elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
-
-       if (incomplete_class) {
-               php_store_class_name(rval, ZSTR_VAL(class_name), len2);
+yy26:
+       yych = *++YYCURSOR;
+       if (yych <= ',') {
+               if (yych == '+') goto yy50;
+               goto yy18;
+       } else {
+               if (yych <= '-') goto yy50;
+               if (yych <= '/') goto yy18;
+               if (yych <= '9') goto yy51;
+               goto yy18;
        }
-       zend_string_release(class_name);
-
-       return object_common2(UNSERIALIZE_PASSTHRU, elements);
-}
-#line 804 "ext/standard/var_unserializer.c"
-yy25:
+yy27:
+       yych = *++YYCURSOR;
+       if (yych <= ',') {
+               if (yych == '+') goto yy53;
+               goto yy18;
+       } else {
+               if (yych <= '-') goto yy53;
+               if (yych <= '/') goto yy18;
+               if (yych <= '9') goto yy54;
+               goto yy18;
+       }
+yy28:
        yych = *++YYCURSOR;
        if (yych <= ',') {
-               if (yych != '+') goto yy18;
+               if (yych == '+') goto yy56;
+               goto yy18;
        } else {
-               if (yych <= '-') goto yy26;
+               if (yych <= '-') goto yy56;
                if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy27;
+               if (yych <= '9') goto yy57;
                goto yy18;
        }
-yy26:
+yy29:
        yych = *++YYCURSOR;
+       if (yych == '+') goto yy59;
        if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
-yy27:
+       if (yych <= '9') goto yy60;
+       goto yy18;
+yy30:
+       yych = *++YYCURSOR;
+       if (yybm[0+yych] & 128) {
+               goto yy31;
+       }
+       goto yy18;
+yy31:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
+       if (yybm[0+yych] & 128) {
+               goto yy31;
+       }
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy27;
-       if (yych >= ';') goto yy18;
+       if (yych <= ':') goto yy62;
+       goto yy18;
+yy33:
        yych = *++YYCURSOR;
-       if (yych != '"') goto yy18;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy34:
        ++YYCURSOR;
-#line 726 "ext/standard/var_unserializer.re"
-       {
-    if (!var_hash) return 0;
-
-       return object_common2(UNSERIALIZE_PASSTHRU,
-                       object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
-}
-#line 836 "ext/standard/var_unserializer.c"
-yy32:
-       yych = *++YYCURSOR;
-       if (yych == '+') goto yy33;
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
        if (yych <= '9') goto yy34;
+       if (yych == ';') goto yy63;
        goto yy18;
-yy33:
+yy36:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
        if (yych >= ':') goto yy18;
-yy34:
+yy37:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy34;
-       if (yych >= ';') goto yy18;
+       if (yych <= '9') goto yy37;
+       if (yych <= ':') goto yy65;
+       goto yy18;
+yy39:
        yych = *++YYCURSOR;
-       if (yych != '{') goto yy18;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy40:
        ++YYCURSOR;
-#line 702 "ext/standard/var_unserializer.re"
-       {
-       zend_long elements = parse_iv(start + 2);
-       /* use iv() not uiv() in order to check data range */
-       *p = YYCURSOR;
-    if (!var_hash) return 0;
-
-       if (elements < 0) {
-               return 0;
-       }
-
-       array_init_size(rval, elements);
-       if (elements) {
-               /* we can't convert from packed to hash during unserialization, because
-                  reference to some zvals might be keept in var_hash (to support references) */
-               zend_hash_real_init(Z_ARRVAL_P(rval), 0);
+       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy40;
+       if (yych <= ':') goto yy66;
+       goto yy18;
+yy42:
+       yych = *++YYCURSOR;
+       if (yych == ';') goto yy67;
+       goto yy18;
+yy43:
+       yych = *++YYCURSOR;
+       if (yych == '.') goto yy45;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy46;
+       goto yy18;
+yy44:
+       yych = *++YYCURSOR;
+       if (yych <= '/') {
+               if (yych != '.') goto yy18;
+       } else {
+               if (yych <= '9') goto yy46;
+               if (yych == 'I') goto yy48;
+               goto yy18;
        }
-
-       if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
-               return 0;
+yy45:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy69;
+       goto yy18;
+yy46:
+       ++YYCURSOR;
+       if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+       yych = *YYCURSOR;
+       if (yych <= ':') {
+               if (yych <= '.') {
+                       if (yych <= '-') goto yy18;
+                       goto yy69;
+               } else {
+                       if (yych <= '/') goto yy18;
+                       if (yych <= '9') goto yy46;
+                       goto yy18;
+               }
+       } else {
+               if (yych <= 'E') {
+                       if (yych <= ';') goto yy71;
+                       if (yych <= 'D') goto yy18;
+                       goto yy73;
+               } else {
+                       if (yych == 'e') goto yy73;
+                       goto yy18;
+               }
        }
-
-       return finish_nested_data(UNSERIALIZE_PASSTHRU);
-}
-#line 881 "ext/standard/var_unserializer.c"
-yy39:
+yy48:
        yych = *++YYCURSOR;
-       if (yych == '+') goto yy40;
+       if (yych == 'N') goto yy74;
+       goto yy18;
+yy49:
+       yych = *++YYCURSOR;
+       if (yych == 'A') goto yy75;
+       goto yy18;
+yy50:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy51:
+       ++YYCURSOR;
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy41;
+       if (yych <= '9') goto yy51;
+       if (yych == ';') goto yy76;
        goto yy18;
-yy40:
+yy53:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
        if (yych >= ':') goto yy18;
-yy41:
+yy54:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy41;
-       if (yych >= ';') goto yy18;
+       if (yych <= '9') goto yy54;
+       if (yych <= ':') goto yy78;
+       goto yy18;
+yy56:
        yych = *++YYCURSOR;
-       if (yych != '"') goto yy18;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy57:
        ++YYCURSOR;
-#line 668 "ext/standard/var_unserializer.re"
-       {
-       size_t len, maxlen;
-       zend_string *str;
-
-       len = parse_uiv(start + 2);
-       maxlen = max - YYCURSOR;
-       if (maxlen < len) {
-               *p = start + 2;
-               return 0;
-       }
-
-       if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
-               return 0;
-       }
-
-       if (*(YYCURSOR) != '"') {
-               zend_string_free(str);
-               *p = YYCURSOR;
-               return 0;
-       }
-
-       if (*(YYCURSOR + 1) != ';') {
-               efree(str);
-               *p = YYCURSOR + 1;
-               return 0;
-       }
-
-       YYCURSOR += 2;
-       *p = YYCURSOR;
-
-       ZVAL_STR(rval, str);
-       return 1;
-}
-#line 936 "ext/standard/var_unserializer.c"
-yy46:
-       yych = *++YYCURSOR;
-       if (yych == '+') goto yy47;
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy48;
+       if (yych <= '9') goto yy57;
+       if (yych == ';') goto yy79;
        goto yy18;
-yy47:
+yy59:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
        if (yych >= ':') goto yy18;
-yy48:
+yy60:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy48;
-       if (yych >= ';') goto yy18;
+       if (yych <= '9') goto yy60;
+       if (yych <= ':') goto yy81;
+       goto yy18;
+yy62:
        yych = *++YYCURSOR;
-       if (yych != '"') goto yy18;
+       if (yych == '"') goto yy82;
+       goto yy18;
+yy63:
        ++YYCURSOR;
-#line 636 "ext/standard/var_unserializer.re"
+#line 557 "ext/standard/var_unserializer.re"
        {
-       size_t len, maxlen;
-       char *str;
-
-       len = parse_uiv(start + 2);
-       maxlen = max - YYCURSOR;
-       if (maxlen < len) {
-               *p = start + 2;
-               return 0;
-       }
-
-       str = (char*)YYCURSOR;
+       zend_long id;
 
-       YYCURSOR += len;
+       *p = YYCURSOR;
+       if (!var_hash) return 0;
 
-       if (*(YYCURSOR) != '"') {
-               *p = YYCURSOR;
+       id = parse_iv(start + 2) - 1;
+       if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
                return 0;
        }
 
-       if (*(YYCURSOR + 1) != ';') {
-               *p = YYCURSOR + 1;
-               return 0;
+       zval_ptr_dtor(rval);
+       if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+               ZVAL_UNDEF(rval);
+               return 1;
+       }
+       if (Z_ISREF_P(rval_ref)) {
+               ZVAL_COPY(rval, rval_ref);
+       } else {
+               ZVAL_NEW_REF(rval_ref, rval_ref);
+               ZVAL_COPY(rval, rval_ref);
        }
 
-       YYCURSOR += 2;
-       *p = YYCURSOR;
-
-       ZVAL_STRINGL(rval, str, len);
        return 1;
 }
-#line 989 "ext/standard/var_unserializer.c"
-yy53:
-       yych = *++YYCURSOR;
-       if (yych <= '/') {
-               if (yych <= ',') {
-                       if (yych == '+') goto yy57;
-                       goto yy18;
-               } else {
-                       if (yych <= '-') goto yy55;
-                       if (yych <= '.') goto yy60;
-                       goto yy18;
-               }
-       } else {
-               if (yych <= 'I') {
-                       if (yych <= '9') goto yy58;
-                       if (yych <= 'H') goto yy18;
-                       goto yy56;
-               } else {
-                       if (yych != 'N') goto yy18;
-               }
-       }
+#line 960 "ext/standard/var_unserializer.c"
+yy65:
        yych = *++YYCURSOR;
-       if (yych == 'A') goto yy76;
+       if (yych == '"') goto yy84;
        goto yy18;
-yy55:
-       yych = *++YYCURSOR;
-       if (yych <= '/') {
-               if (yych == '.') goto yy60;
-               goto yy18;
-       } else {
-               if (yych <= '9') goto yy58;
-               if (yych != 'I') goto yy18;
-       }
-yy56:
+yy66:
        yych = *++YYCURSOR;
-       if (yych == 'N') goto yy72;
+       if (yych == '{') goto yy86;
        goto yy18;
-yy57:
-       yych = *++YYCURSOR;
-       if (yych == '.') goto yy60;
-       if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
-yy58:
+yy67:
        ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
-       yych = *YYCURSOR;
-       if (yych <= ':') {
-               if (yych <= '.') {
-                       if (yych <= '-') goto yy18;
-                       goto yy70;
-               } else {
-                       if (yych <= '/') goto yy18;
-                       if (yych <= '9') goto yy58;
-                       goto yy18;
-               }
-       } else {
-               if (yych <= 'E') {
-                       if (yych <= ';') goto yy63;
-                       if (yych <= 'D') goto yy18;
-                       goto yy65;
-               } else {
-                       if (yych == 'e') goto yy65;
-                       goto yy18;
-               }
-       }
-yy60:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
-yy61:
+#line 614 "ext/standard/var_unserializer.re"
+       {
+       *p = YYCURSOR;
+       ZVAL_BOOL(rval, parse_iv(start + 2));
+       return 1;
+}
+#line 977 "ext/standard/var_unserializer.c"
+yy69:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
        yych = *YYCURSOR;
        if (yych <= ';') {
                if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy61;
+               if (yych <= '9') goto yy69;
                if (yych <= ':') goto yy18;
        } else {
                if (yych <= 'E') {
                        if (yych <= 'D') goto yy18;
-                       goto yy65;
+                       goto yy73;
                } else {
-                       if (yych == 'e') goto yy65;
+                       if (yych == 'e') goto yy73;
                        goto yy18;
                }
        }
-yy63:
+yy71:
        ++YYCURSOR;
-#line 627 "ext/standard/var_unserializer.re"
+#line 662 "ext/standard/var_unserializer.re"
        {
 #if SIZEOF_ZEND_LONG == 4
 use_double:
@@ -1082,257 +1002,396 @@ use_double:
        ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
        return 1;
 }
-#line 1086 "ext/standard/var_unserializer.c"
-yy65:
+#line 1006 "ext/standard/var_unserializer.c"
+yy73:
        yych = *++YYCURSOR;
        if (yych <= ',') {
-               if (yych != '+') goto yy18;
+               if (yych == '+') goto yy88;
+               goto yy18;
        } else {
-               if (yych <= '-') goto yy66;
+               if (yych <= '-') goto yy88;
                if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy67;
+               if (yych <= '9') goto yy89;
                goto yy18;
        }
-yy66:
+yy74:
        yych = *++YYCURSOR;
-       if (yych <= ',') {
-               if (yych == '+') goto yy69;
-               goto yy18;
-       } else {
-               if (yych <= '-') goto yy69;
-               if (yych <= '/') goto yy18;
-               if (yych >= ':') goto yy18;
-       }
-yy67:
-       ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy67;
-       if (yych == ';') goto yy63;
+       if (yych == 'F') goto yy91;
        goto yy18;
-yy69:
+yy75:
        yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy67;
+       if (yych == 'N') goto yy91;
        goto yy18;
-yy70:
+yy76:
        ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
-       yych = *YYCURSOR;
-       if (yych <= ';') {
-               if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy70;
-               if (yych <= ':') goto yy18;
-               goto yy63;
-       } else {
-               if (yych <= 'E') {
-                       if (yych <= 'D') goto yy18;
-                       goto yy65;
+#line 620 "ext/standard/var_unserializer.re"
+       {
+#if SIZEOF_ZEND_LONG == 4
+       int digits = YYCURSOR - start - 3;
+
+       if (start[2] == '-' || start[2] == '+') {
+               digits--;
+       }
+
+       /* Use double for large zend_long values that were serialized on a 64-bit system */
+       if (digits >= MAX_LENGTH_OF_LONG - 1) {
+               if (digits == MAX_LENGTH_OF_LONG - 1) {
+                       int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
+
+                       if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
+                               goto use_double;
+                       }
                } else {
-                       if (yych == 'e') goto yy65;
-                       goto yy18;
+                       goto use_double;
                }
        }
-yy72:
-       yych = *++YYCURSOR;
-       if (yych != 'F') goto yy18;
-yy73:
+#endif
+       *p = YYCURSOR;
+       ZVAL_LONG(rval, parse_iv(start + 2));
+       return 1;
+}
+#line 1054 "ext/standard/var_unserializer.c"
+yy78:
        yych = *++YYCURSOR;
-       if (yych != ';') goto yy18;
+       if (yych == '"') goto yy92;
+       goto yy18;
+yy79:
        ++YYCURSOR;
-#line 611 "ext/standard/var_unserializer.re"
+#line 583 "ext/standard/var_unserializer.re"
        {
-       *p = YYCURSOR;
+       zend_long id;
 
-       if (!strncmp((char*)start + 2, "NAN", 3)) {
-               ZVAL_DOUBLE(rval, php_get_nan());
-       } else if (!strncmp((char*)start + 2, "INF", 3)) {
-               ZVAL_DOUBLE(rval, php_get_inf());
-       } else if (!strncmp((char*)start + 2, "-INF", 4)) {
-               ZVAL_DOUBLE(rval, -php_get_inf());
-       } else {
-               ZVAL_NULL(rval);
+       *p = YYCURSOR;
+       if (!var_hash) return 0;
+
+       id = parse_iv(start + 2) - 1;
+       if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+               return 0;
+       }
+
+       if (rval_ref == rval) {
+               return 0;
+       }
+
+       if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+               ZVAL_UNDEF(rval);
+               return 1;
        }
 
+       ZVAL_COPY(rval, rval_ref);
+
        return 1;
 }
-#line 1161 "ext/standard/var_unserializer.c"
-yy76:
+#line 1086 "ext/standard/var_unserializer.c"
+yy81:
        yych = *++YYCURSOR;
-       if (yych == 'N') goto yy73;
+       if (yych == '"') goto yy94;
        goto yy18;
-yy77:
-       yych = *++YYCURSOR;
-       if (yych <= ',') {
-               if (yych != '+') goto yy18;
-       } else {
-               if (yych <= '-') goto yy78;
-               if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy79;
-               goto yy18;
-       }
-yy78:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
-yy79:
-       ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy79;
-       if (yych != ';') goto yy18;
+yy82:
        ++YYCURSOR;
-#line 585 "ext/standard/var_unserializer.re"
+#line 768 "ext/standard/var_unserializer.re"
        {
-#if SIZEOF_ZEND_LONG == 4
-       int digits = YYCURSOR - start - 3;
+       size_t len, len2, len3, maxlen;
+       zend_long elements;
+       char *str;
+       zend_string *class_name;
+       zend_class_entry *ce;
+       int incomplete_class = 0;
 
-       if (start[2] == '-' || start[2] == '+') {
-               digits--;
+       int custom_object = 0;
+
+       zval user_func;
+       zval retval;
+       zval args[1];
+
+    if (!var_hash) return 0;
+       if (*start == 'C') {
+               custom_object = 1;
        }
 
-       /* Use double for large zend_long values that were serialized on a 64-bit system */
-       if (digits >= MAX_LENGTH_OF_LONG - 1) {
-               if (digits == MAX_LENGTH_OF_LONG - 1) {
-                       int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
+       len2 = len = parse_uiv(start + 2);
+       maxlen = max - YYCURSOR;
+       if (maxlen < len || len == 0) {
+               *p = start + 2;
+               return 0;
+       }
 
-                       if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
-                               goto use_double;
+       str = (char*)YYCURSOR;
+
+       YYCURSOR += len;
+
+       if (*(YYCURSOR) != '"') {
+               *p = YYCURSOR;
+               return 0;
+       }
+       if (*(YYCURSOR+1) != ':') {
+               *p = YYCURSOR+1;
+               return 0;
+       }
+
+       len3 = strspn(str, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\");
+       if (len3 != len)
+       {
+               *p = YYCURSOR + len3 - len;
+               return 0;
+       }
+
+       class_name = zend_string_init(str, len, 0);
+
+       do {
+               if(!unserialize_allowed_class(class_name, classes)) {
+                       incomplete_class = 1;
+                       ce = PHP_IC_ENTRY;
+                       break;
+               }
+
+               /* Try to find class directly */
+               BG(serialize_lock)++;
+               ce = zend_lookup_class(class_name);
+               if (ce) {
+                       BG(serialize_lock)--;
+                       if (EG(exception)) {
+                               zend_string_release(class_name);
+                               return 0;
                        }
-               } else {
-                       goto use_double;
+                       break;
                }
-       }
-#endif
+               BG(serialize_lock)--;
+
+               if (EG(exception)) {
+                       zend_string_release(class_name);
+                       return 0;
+               }
+
+               /* Check for unserialize callback */
+               if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
+                       incomplete_class = 1;
+                       ce = PHP_IC_ENTRY;
+                       break;
+               }
+
+               /* Call unserialize callback */
+               ZVAL_STRING(&user_func, PG(unserialize_callback_func));
+
+               ZVAL_STR_COPY(&args[0], class_name);
+               BG(serialize_lock)++;
+               if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
+                       BG(serialize_lock)--;
+                       if (EG(exception)) {
+                               zend_string_release(class_name);
+                               zval_ptr_dtor(&user_func);
+                               zval_ptr_dtor(&args[0]);
+                               return 0;
+                       }
+                       php_error_docref(NULL, E_WARNING, "defined (%s) but not found", Z_STRVAL(user_func));
+                       incomplete_class = 1;
+                       ce = PHP_IC_ENTRY;
+                       zval_ptr_dtor(&user_func);
+                       zval_ptr_dtor(&args[0]);
+                       break;
+               }
+               BG(serialize_lock)--;
+               zval_ptr_dtor(&retval);
+               if (EG(exception)) {
+                       zend_string_release(class_name);
+                       zval_ptr_dtor(&user_func);
+                       zval_ptr_dtor(&args[0]);
+                       return 0;
+               }
+
+               /* The callback function may have defined the class */
+               if ((ce = zend_lookup_class(class_name)) == NULL) {
+                       php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
+                       incomplete_class = 1;
+                       ce = PHP_IC_ENTRY;
+               }
+
+               zval_ptr_dtor(&user_func);
+               zval_ptr_dtor(&args[0]);
+               break;
+       } while (1);
+
        *p = YYCURSOR;
-       ZVAL_LONG(rval, parse_iv(start + 2));
-       return 1;
+
+       if (custom_object) {
+               int ret;
+
+               ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
+
+               if (ret && incomplete_class) {
+                       php_store_class_name(rval, ZSTR_VAL(class_name), len2);
+               }
+               zend_string_release(class_name);
+               return ret;
+       }
+
+       elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
+
+       if (incomplete_class) {
+               php_store_class_name(rval, ZSTR_VAL(class_name), len2);
+       }
+       zend_string_release(class_name);
+
+       return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 1214 "ext/standard/var_unserializer.c"
-yy83:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych >= '2') goto yy18;
-       yych = *++YYCURSOR;
-       if (yych != ';') goto yy18;
+#line 1238 "ext/standard/var_unserializer.c"
+yy84:
        ++YYCURSOR;
-#line 579 "ext/standard/var_unserializer.re"
+#line 703 "ext/standard/var_unserializer.re"
        {
+       size_t len, maxlen;
+       zend_string *str;
+
+       len = parse_uiv(start + 2);
+       maxlen = max - YYCURSOR;
+       if (maxlen < len) {
+               *p = start + 2;
+               return 0;
+       }
+
+       if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
+               return 0;
+       }
+
+       if (*(YYCURSOR) != '"') {
+               zend_string_free(str);
+               *p = YYCURSOR;
+               return 0;
+       }
+
+       if (*(YYCURSOR + 1) != ';') {
+               efree(str);
+               *p = YYCURSOR + 1;
+               return 0;
+       }
+
+       YYCURSOR += 2;
        *p = YYCURSOR;
-       ZVAL_BOOL(rval, parse_iv(start + 2));
+
+       ZVAL_STR(rval, str);
        return 1;
 }
-#line 1228 "ext/standard/var_unserializer.c"
-yy87:
+#line 1275 "ext/standard/var_unserializer.c"
+yy86:
        ++YYCURSOR;
-#line 573 "ext/standard/var_unserializer.re"
+#line 737 "ext/standard/var_unserializer.re"
        {
+       zend_long elements = parse_iv(start + 2);
+       /* use iv() not uiv() in order to check data range */
        *p = YYCURSOR;
-       ZVAL_NULL(rval);
-       return 1;
+    if (!var_hash) return 0;
+
+       if (elements < 0) {
+               return 0;
+       }
+
+       array_init_size(rval, elements);
+       if (elements) {
+               /* we can't convert from packed to hash during unserialization, because
+                  reference to some zvals might be keept in var_hash (to support references) */
+               zend_hash_real_init(Z_ARRVAL_P(rval), 0);
+       }
+
+       if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
+               return 0;
+       }
+
+       return finish_nested_data(UNSERIALIZE_PASSTHRU);
 }
-#line 1237 "ext/standard/var_unserializer.c"
-yy89:
+#line 1302 "ext/standard/var_unserializer.c"
+yy88:
        yych = *++YYCURSOR;
        if (yych <= ',') {
-               if (yych != '+') goto yy18;
+               if (yych == '+') goto yy96;
+               goto yy18;
        } else {
-               if (yych <= '-') goto yy90;
+               if (yych <= '-') goto yy96;
                if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy91;
-               goto yy18;
+               if (yych >= ':') goto yy18;
        }
-yy90:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
-yy91:
+yy89:
        ++YYCURSOR;
        if (YYLIMIT <= YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy91;
-       if (yych != ';') goto yy18;
+       if (yych <= '9') goto yy89;
+       if (yych == ';') goto yy71;
+       goto yy18;
+yy91:
+       yych = *++YYCURSOR;
+       if (yych == ';') goto yy97;
+       goto yy18;
+yy92:
        ++YYCURSOR;
-#line 548 "ext/standard/var_unserializer.re"
+#line 761 "ext/standard/var_unserializer.re"
        {
-       zend_long id;
+    if (!var_hash) return 0;
 
-       *p = YYCURSOR;
-       if (!var_hash) return 0;
+       return object_common2(UNSERIALIZE_PASSTHRU,
+                       object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
+}
+#line 1334 "ext/standard/var_unserializer.c"
+yy94:
+       ++YYCURSOR;
+#line 671 "ext/standard/var_unserializer.re"
+       {
+       size_t len, maxlen;
+       char *str;
 
-       id = parse_iv(start + 2) - 1;
-       if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+       len = parse_uiv(start + 2);
+       maxlen = max - YYCURSOR;
+       if (maxlen < len) {
+               *p = start + 2;
                return 0;
        }
 
-       if (rval_ref == rval) {
+       str = (char*)YYCURSOR;
+
+       YYCURSOR += len;
+
+       if (*(YYCURSOR) != '"') {
+               *p = YYCURSOR;
                return 0;
        }
 
-       if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
-               ZVAL_UNDEF(rval);
-               return 1;
+       if (*(YYCURSOR + 1) != ';') {
+               *p = YYCURSOR + 1;
+               return 0;
        }
 
-       ZVAL_COPY(rval, rval_ref);
+       YYCURSOR += 2;
+       *p = YYCURSOR;
 
+       ZVAL_STRINGL(rval, str, len);
        return 1;
 }
-#line 1285 "ext/standard/var_unserializer.c"
-yy95:
-       yych = *++YYCURSOR;
-       if (yych <= ',') {
-               if (yych != '+') goto yy18;
-       } else {
-               if (yych <= '-') goto yy96;
-               if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy97;
-               goto yy18;
-       }
+#line 1369 "ext/standard/var_unserializer.c"
 yy96:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
+       if (yych <= '9') goto yy89;
+       goto yy18;
 yy97:
        ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy97;
-       if (yych != ';') goto yy18;
-       ++YYCURSOR;
-#line 522 "ext/standard/var_unserializer.re"
+#line 646 "ext/standard/var_unserializer.re"
        {
-       zend_long id;
-
-       *p = YYCURSOR;
-       if (!var_hash) return 0;
-
-       id = parse_iv(start + 2) - 1;
-       if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
-               return 0;
-       }
+       *p = YYCURSOR;
 
-       zval_ptr_dtor(rval);
-       if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
-               ZVAL_UNDEF(rval);
-               return 1;
-       }
-       if (Z_ISREF_P(rval_ref)) {
-               ZVAL_COPY(rval, rval_ref);
+       if (!strncmp((char*)start + 2, "NAN", 3)) {
+               ZVAL_DOUBLE(rval, php_get_nan());
+       } else if (!strncmp((char*)start + 2, "INF", 3)) {
+               ZVAL_DOUBLE(rval, php_get_inf());
+       } else if (!strncmp((char*)start + 2, "-INF", 4)) {
+               ZVAL_DOUBLE(rval, -php_get_inf());
        } else {
-               ZVAL_NEW_REF(rval_ref, rval_ref);
-               ZVAL_COPY(rval, rval_ref);
+               ZVAL_NULL(rval);
        }
 
        return 1;
 }
-#line 1334 "ext/standard/var_unserializer.c"
+#line 1393 "ext/standard/var_unserializer.c"
 }
-#line 886 "ext/standard/var_unserializer.re"
+#line 921 "ext/standard/var_unserializer.re"
 
 
        return 0;
index 52e2cf36464fc4c7c9a7c87883580f6cd520221d..4ba8f75f3b591717917db5c25909f61e09c602c3 100644 (file)
 #include "ext/standard/php_var.h"
 #include "php_incomplete_class.h"
 
+struct php_unserialize_data {
+       void *first;
+       void *last;
+       void *first_dtor;
+       void *last_dtor;
+};
+
+PHPAPI php_unserialize_data_t php_var_unserialize_init() {
+       php_unserialize_data_t d;
+       /* fprintf(stderr, "UNSERIALIZE_INIT    == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
+       if (BG(serialize_lock) || !BG(unserialize).level) {
+               d = ecalloc(1, sizeof(struct php_unserialize_data));
+               if (!BG(serialize_lock)) {
+                       BG(unserialize).data = d;
+                       BG(unserialize).level = 1;
+               }
+       } else {
+               d = BG(unserialize).data;
+               ++BG(unserialize).level;
+       }
+       return d;
+}
+
+PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d) {
+       /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
+       if (BG(serialize_lock) || BG(unserialize).level == 1) {
+               var_destroy(&d);
+               efree(d);
+       }
+       if (!BG(serialize_lock) && !--BG(unserialize).level) {
+               BG(unserialize).data = NULL;
+       }
+}
+
+
 /* {{{ reference-handling for unserializer: var_* */
 #define VAR_ENTRIES_MAX 1024
 #define VAR_ENTRIES_DBG 0