]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-5.6' into PHP-7.0
authorStanislav Malyshev <stas@php.net>
Tue, 3 Jan 2017 05:01:35 +0000 (21:01 -0800)
committerStanislav Malyshev <stas@php.net>
Tue, 3 Jan 2017 05:01:35 +0000 (21:01 -0800)
* PHP-5.6:
  Fix bug #73737 FPE when parsing a tag format
  Fix bug #73773 - Seg fault when loading hostile phar
  Fix bug #73825 - Heap out of bounds read on unserialize in finish_nested_data()
  Fix bug #73768 - Memory corruption when loading hostile phar
  Fix int overflows in phar (bug #73764)

1  2 
ext/exif/exif.c
ext/phar/phar.c
ext/standard/var_unserializer.c
ext/standard/var_unserializer.re

diff --cc ext/exif/exif.c
Simple merge
diff --cc ext/phar/phar.c
Simple merge
index d1eb7b4bb0c3ab3a8db06dfe5fb1616fb33b9cdb,79d98e5a247333e8b342b3137ea47382e25703f6..cb5d8662d6b583304847766f28618b012566c046
@@@ -429,10 -401,15 +429,15 @@@ static inline int object_custom(UNSERIA
        return finish_nested_data(UNSERIALIZE_PASSTHRU);
  }
  
 -static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
 +static inline zend_long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
  {
 -      long elements;
 +      zend_long elements;
  
+       if( *p >= max - 2) {
+               zend_error(E_WARNING, "Bad unserialize data");
+               return -1;
+       }
        elements = parse_iv2((*p) + 2, p);
  
        (*p) += 2;
@@@ -550,7 -495,9 +555,7 @@@ static int php_var_unserialize_internal
        start = cursor;
  
  
- #line 554 "ext/standard/var_unserializer.c"
 -
 -
 -#line 501 "ext/standard/var_unserializer.c"
++#line 559 "ext/standard/var_unserializer.c"
  {
        YYCTYPE yych;
        static const unsigned char yybm[] = {
        yych = *YYCURSOR;
        switch (yych) {
        case 'C':
-       case 'O':       goto yy4;
+       case 'O':       goto yy13;
        case 'N':       goto yy5;
-       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 'R':       goto yy2;
+       case 'S':       goto yy10;
+       case 'a':       goto yy11;
+       case 'b':       goto yy6;
+       case 'd':       goto yy8;
+       case 'i':       goto yy7;
        case 'o':       goto yy12;
-       case 'r':       goto yy13;
-       case 's':       goto yy14;
-       case '}':       goto yy15;
-       default:        goto yy2;
+       case 'r':       goto yy4;
+       case 's':       goto yy9;
+       case '}':       goto yy14;
+       default:        goto yy16;
        }
  yy2:
-       ++YYCURSOR;
+       yych = *(YYMARKER = ++YYCURSOR);
+       if (yych == ':') goto yy95;
  yy3:
- #line 922 "ext/standard/var_unserializer.re"
 -#line 877 "ext/standard/var_unserializer.re"
++#line 936 "ext/standard/var_unserializer.re"
        { return 0; }
- #line 614 "ext/standard/var_unserializer.c"
 -#line 563 "ext/standard/var_unserializer.c"
++#line 621 "ext/standard/var_unserializer.c"
  yy4:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy17;
+       if (yych == ':') goto yy89;
        goto yy3;
  yy5:
        yych = *++YYCURSOR;
@@@ -649,21 -598,20 +656,20 @@@ yy12
        goto yy3;
  yy13:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy28;
+       if (yych == ':') goto yy17;
        goto yy3;
  yy14:
-       yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy29;
-       goto yy3;
- yy15:
        ++YYCURSOR;
- #line 916 "ext/standard/var_unserializer.re"
 -#line 871 "ext/standard/var_unserializer.re"
++#line 930 "ext/standard/var_unserializer.re"
        {
        /* this is the case where we have less data than planned */
 -      php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
 +      php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
        return 0; /* not sure if it should be 0 or 1 here? */
  }
- #line 667 "ext/standard/var_unserializer.c"
 -#line 612 "ext/standard/var_unserializer.c"
++#line 670 "ext/standard/var_unserializer.c"
+ yy16:
+       yych = *++YYCURSOR;
+       goto yy3;
  yy17:
        yych = *++YYCURSOR;
        if (yybm[0+yych] & 128) {
@@@ -674,131 -622,223 +680,219 @@@ yy18
        YYCURSOR = YYMARKER;
        goto yy3;
  yy19:
-       ++YYCURSOR;
- #line 609 "ext/standard/var_unserializer.re"
-       {
-       *p = YYCURSOR;
-       ZVAL_NULL(rval);
-       return 1;
- }
- #line 685 "ext/standard/var_unserializer.c"
- yy21:
        yych = *++YYCURSOR;
-       if (yych <= ',') {
-               if (yych == '+') goto yy33;
-               goto yy18;
-       } else {
-               if (yych <= '-') goto yy33;
-               if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy34;
-               goto yy18;
+       if (yybm[0+yych] & 128) {
+               goto yy20;
        }
- yy22:
-       yych = *++YYCURSOR;
-       if (yych == '+') goto yy36;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy37;
        goto yy18;
- yy23:
-       yych = *++YYCURSOR;
-       if (yych == '+') goto yy39;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy40;
-       goto yy18;
- yy24:
-       yych = *++YYCURSOR;
+ yy20:
+       ++YYCURSOR;
+       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+       yych = *YYCURSOR;
+       if (yybm[0+yych] & 128) {
+               goto yy20;
+       }
        if (yych <= '/') goto yy18;
-       if (yych <= '1') goto yy42;
-       goto yy18;
- yy25:
+       if (yych >= ';') goto yy18;
        yych = *++YYCURSOR;
-       if (yych <= '/') {
-               if (yych <= ',') {
-                       if (yych == '+') goto yy43;
-                       goto yy18;
-               } else {
-                       if (yych <= '-') goto yy44;
-                       if (yych <= '.') goto yy45;
-                       goto yy18;
+       if (yych != '"') goto yy18;
+       ++YYCURSOR;
 -#line 717 "ext/standard/var_unserializer.re"
++#line 778 "ext/standard/var_unserializer.re"
+       {
+       size_t len, len2, len3, maxlen;
 -      long elements;
 -      char *class_name;
++      zend_long elements;
++      char *str;
++      zend_string *class_name;
+       zend_class_entry *ce;
 -      zend_class_entry **pce;
+       int incomplete_class = 0;
+       int custom_object = 0;
 -      zval *user_func;
 -      zval *retval_ptr;
 -      zval **args[1];
 -      zval *arg_func_name;
++      zval user_func;
++      zval retval;
++      zval args[1];
+     if (!var_hash) return 0;
+       if (*start == 'C') {
+               custom_object = 1;
+       }
 -      INIT_PZVAL(*rval);
+       len2 = len = parse_uiv(start + 2);
+       maxlen = max - YYCURSOR;
+       if (maxlen < len || len == 0) {
+               *p = start + 2;
+               return 0;
+       }
 -      class_name = (char*)YYCURSOR;
++      str = (char*)YYCURSOR;
+       YYCURSOR += len;
+       if (*(YYCURSOR) != '"') {
+               *p = YYCURSOR;
+               return 0;
+       }
+       if (*(YYCURSOR+1) != ':') {
+               *p = YYCURSOR+1;
+               return 0;
+       }
 -      len3 = strspn(class_name, "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\\");
++      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 = estrndup(class_name, len);
++      class_name = zend_string_init(str, len, 0);
+       do {
++              if(!unserialize_allowed_class(class_name, classes)) {
++                      incomplete_class = 1;
++                      ce = PHP_IC_ENTRY;
++                      break;
 +              }
-       } else {
-               if (yych <= 'I') {
-                       if (yych <= '9') goto yy46;
-                       if (yych <= 'H') goto yy18;
-                       goto yy48;
-               } else {
-                       if (yych == 'N') goto yy49;
-                       goto yy18;
++
+               /* Try to find class directly */
+               BG(serialize_lock)++;
 -              if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
++              ce = zend_lookup_class(class_name);
++              if (ce) {
+                       BG(serialize_lock)--;
+                       if (EG(exception)) {
 -                              efree(class_name);
++                              zend_string_release(class_name);
+                               return 0;
+                       }
 -                      ce = *pce;
+                       break;
+               }
+               BG(serialize_lock)--;
+               if (EG(exception)) {
 -                      efree(class_name);
++                      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 */
 -              MAKE_STD_ZVAL(user_func);
 -              ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
 -              args[0] = &arg_func_name;
 -              MAKE_STD_ZVAL(arg_func_name);
 -              ZVAL_STRING(arg_func_name, class_name, 1);
++              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_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
++              if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
+                       BG(serialize_lock)--;
+                       if (EG(exception)) {
 -                              efree(class_name);
++                              zend_string_release(class_name);
+                               zval_ptr_dtor(&user_func);
 -                              zval_ptr_dtor(&arg_func_name);
++                              zval_ptr_dtor(&args[0]);
+                               return 0;
+                       }
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val);
++                      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(&arg_func_name);
++                      zval_ptr_dtor(&args[0]);
+                       break;
+               }
+               BG(serialize_lock)--;
 -              if (retval_ptr) {
 -                      zval_ptr_dtor(&retval_ptr);
 -              }
++              zval_ptr_dtor(&retval);
+               if (EG(exception)) {
 -                      efree(class_name);
++                      zend_string_release(class_name);
+                       zval_ptr_dtor(&user_func);
 -                      zval_ptr_dtor(&arg_func_name);
++                      zval_ptr_dtor(&args[0]);
+                       return 0;
+               }
+               /* The callback function may have defined the class */
+               BG(serialize_lock)++;
 -              if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
 -                      ce = *pce;
 -              } else {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function %s() hasn't defined the class it was called for", user_func->value.str.val);
++              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;
+               }
+               BG(serialize_lock)--;
+               zval_ptr_dtor(&user_func);
 -              zval_ptr_dtor(&arg_func_name);
++              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, class_name, len2);
++                      php_store_class_name(rval, ZSTR_VAL(class_name), len2);
                }
 -              efree(class_name);
++              zend_string_release(class_name);
+               return ret;
        }
- 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;
+       elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
+       if (elements < 0) {
+          efree(class_name);
+          return 0;
        }
- 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;
+       if (incomplete_class) {
 -              php_store_class_name(*rval, class_name, len2);
++              php_store_class_name(rval, ZSTR_VAL(class_name), len2);
        }
- yy28:
 -      efree(class_name);
++      zend_string_release(class_name);
+       return object_common2(UNSERIALIZE_PASSTHRU, elements);
+ }
 -#line 797 "ext/standard/var_unserializer.c"
++#line 853 "ext/standard/var_unserializer.c"
+ yy25:
        yych = *++YYCURSOR;
        if (yych <= ',') {
-               if (yych == '+') goto yy56;
-               goto yy18;
+               if (yych != '+') goto yy18;
        } else {
-               if (yych <= '-') goto yy56;
+               if (yych <= '-') goto yy26;
                if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy57;
+               if (yych <= '9') goto yy27;
                goto yy18;
        }
- yy29:
+ yy26:
        yych = *++YYCURSOR;
-       if (yych == '+') goto yy59;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy60;
-       goto yy18;
- yy30:
-       yych = *++YYCURSOR;
-       if (yybm[0+yych] & 128) {
-               goto yy31;
-       }
-       goto yy18;
- yy31:
+       if (yych >= ':') goto yy18;
+ yy27:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
-       if (yybm[0+yych] & 128) {
-               goto yy31;
-       }
        if (yych <= '/') goto yy18;
-       if (yych <= ':') goto yy62;
-       goto yy18;
- yy33:
+       if (yych <= '9') goto yy27;
+       if (yych >= ';') goto yy18;
        yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
- yy34:
+       if (yych != '"') goto yy18;
        ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
 -#line 704 "ext/standard/var_unserializer.re"
++#line 767 "ext/standard/var_unserializer.re"
+       {
+       long elements;
+     if (!var_hash) return 0;
 -      INIT_PZVAL(*rval);
 -
+       elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
+       if (elements < 0) {
+               return 0;
+       }
+       return object_common2(UNSERIALIZE_PASSTHRU, elements);
+ }
 -#line 835 "ext/standard/var_unserializer.c"
++#line 889 "ext/standard/var_unserializer.c"
+ yy32:
+       yych = *++YYCURSOR;
+       if (yych == '+') goto yy33;
        if (yych <= '/') goto yy18;
        if (yych <= '9') goto yy34;
-       if (yych == ';') goto yy63;
        goto yy18;
- yy36:
+ yy33:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
        if (yych >= ':') goto yy18;
@@@ -807,89 -847,40 +901,43 @@@ yy34
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy37;
-       if (yych <= ':') goto yy65;
-       goto yy18;
- yy39:
+       if (yych <= '9') goto yy34;
+       if (yych >= ';') goto yy18;
        yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
- yy40:
+       if (yych != '{') goto yy18;
        ++YYCURSOR;
-       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;
 -#line 683 "ext/standard/var_unserializer.re"
++#line 743 "ext/standard/var_unserializer.re"
+       {
 -      long elements = parse_iv(start + 2);
++      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;
        }
- 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;
-               }
 -      INIT_PZVAL(*rval);
 -
 -      array_init_size(*rval, elements);
++      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);
 +      }
- yy48:
-       yych = *++YYCURSOR;
-       if (yych == 'N') goto yy74;
-       goto yy18;
- yy49:
-       yych = *++YYCURSOR;
-       if (yych == 'A') goto yy75;
-       goto yy18;
- yy50:
 -      if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_PP(rval), elements, 0)) {
++      if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
+               return 0;
+       }
+       return finish_nested_data(UNSERIALIZE_PASSTHRU);
+ }
 -#line 877 "ext/standard/var_unserializer.c"
++#line 934 "ext/standard/var_unserializer.c"
+ yy39:
        yych = *++YYCURSOR;
+       if (yych == '+') goto yy40;
        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 yy51;
-       if (yych == ';') goto yy76;
+       if (yych <= '9') goto yy41;
        goto yy18;
- yy53:
+ yy40:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
        if (yych >= ':') goto yy18;
@@@ -898,22 -889,54 +946,53 @@@ yy41
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy54;
-       if (yych <= ':') goto yy78;
-       goto yy18;
- yy56:
+       if (yych <= '9') goto yy41;
+       if (yych >= ';') goto yy18;
        yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
- yy57:
+       if (yych != '"') goto yy18;
        ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
 -#line 648 "ext/standard/var_unserializer.re"
++#line 709 "ext/standard/var_unserializer.re"
+       {
+       size_t len, maxlen;
 -      char *str;
++      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) {
++      if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
+               return 0;
+       }
+       if (*(YYCURSOR) != '"') {
 -              efree(str);
++              zend_string_free(str);
+               *p = YYCURSOR;
+               return 0;
+       }
+       if (*(YYCURSOR + 1) != ';') {
+               efree(str);
+               *p = YYCURSOR + 1;
+               return 0;
+       }
+       YYCURSOR += 2;
+       *p = YYCURSOR;
 -      INIT_PZVAL(*rval);
 -      ZVAL_STRINGL(*rval, str, len, 0);
++      ZVAL_STR(rval, str);
+       return 1;
+ }
 -#line 933 "ext/standard/var_unserializer.c"
++#line 989 "ext/standard/var_unserializer.c"
+ yy46:
+       yych = *++YYCURSOR;
+       if (yych == '+') goto yy47;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy57;
-       if (yych == ';') goto yy79;
+       if (yych <= '9') goto yy48;
        goto yy18;
- yy59:
+ yy47:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
        if (yych >= ':') goto yy18;
@@@ -922,60 -945,114 +1001,113 @@@ yy48
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy60;
-       if (yych <= ':') goto yy81;
-       goto yy18;
- yy62:
+       if (yych <= '9') goto yy48;
+       if (yych >= ';') goto yy18;
        yych = *++YYCURSOR;
-       if (yych == '"') goto yy82;
-       goto yy18;
- yy63:
+       if (yych != '"') goto yy18;
        ++YYCURSOR;
- #line 558 "ext/standard/var_unserializer.re"
 -#line 615 "ext/standard/var_unserializer.re"
++#line 677 "ext/standard/var_unserializer.re"
        {
-       zend_long id;
-       *p = YYCURSOR;
-       if (!var_hash) return 0;
+       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;
        }
  
-       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;
+       str = (char*)YYCURSOR;
+       YYCURSOR += len;
+       if (*(YYCURSOR) != '"') {
+               *p = YYCURSOR;
+               return 0;
        }
-       if (Z_ISREF_P(rval_ref)) {
-               ZVAL_COPY(rval, rval_ref);
-       } else {
-               ZVAL_NEW_REF(rval_ref, rval_ref);
-               ZVAL_COPY(rval, rval_ref);
+       if (*(YYCURSOR + 1) != ';') {
+               *p = YYCURSOR + 1;
+               return 0;
        }
  
 -      INIT_PZVAL(*rval);
 -      ZVAL_STRINGL(*rval, str, len, 1);
+       YYCURSOR += 2;
+       *p = YYCURSOR;
++      ZVAL_STRINGL(rval, str, len);
        return 1;
  }
- #line 961 "ext/standard/var_unserializer.c"
- yy65:
 -#line 987 "ext/standard/var_unserializer.c"
++#line 1042 "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;
+               }
+       }
        yych = *++YYCURSOR;
-       if (yych == '"') goto yy84;
+       if (yych == 'A') goto yy76;
        goto yy18;
- yy66:
+ yy55:
+       yych = *++YYCURSOR;
+       if (yych <= '/') {
+               if (yych == '.') goto yy60;
+               goto yy18;
+       } else {
+               if (yych <= '9') goto yy58;
+               if (yych != 'I') goto yy18;
+       }
+ yy56:
        yych = *++YYCURSOR;
-       if (yych == '{') goto yy86;
+       if (yych == 'N') goto yy72;
        goto yy18;
- yy67:
+ yy57:
+       yych = *++YYCURSOR;
+       if (yych == '.') goto yy60;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+ yy58:
        ++YYCURSOR;
- #line 615 "ext/standard/var_unserializer.re"
-       {
-       *p = YYCURSOR;
-       ZVAL_BOOL(rval, parse_iv(start + 2));
-       return 1;
- }
- #line 978 "ext/standard/var_unserializer.c"
- yy69:
+       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:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
        yych = *YYCURSOR;
                        goto yy18;
                }
        }
- yy71:
+ yy63:
        ++YYCURSOR;
- #line 663 "ext/standard/var_unserializer.re"
 -#line 605 "ext/standard/var_unserializer.re"
++#line 668 "ext/standard/var_unserializer.re"
        {
 -#if SIZEOF_LONG == 4
 +#if SIZEOF_ZEND_LONG == 4
  use_double:
  #endif
        *p = YYCURSOR;
 -      INIT_PZVAL(*rval);
 -      ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
 +      ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
        return 1;
  }
- #line 1007 "ext/standard/var_unserializer.c"
- yy73:
 -#line 1085 "ext/standard/var_unserializer.c"
++#line 1139 "ext/standard/var_unserializer.c"
+ yy65:
        yych = *++YYCURSOR;
        if (yych <= ',') {
-               if (yych == '+') goto yy88;
-               goto yy18;
+               if (yych != '+') goto yy18;
        } else {
-               if (yych <= '-') goto yy88;
+               if (yych <= '-') goto yy66;
                if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy89;
+               if (yych <= '9') goto yy67;
                goto yy18;
        }
- yy74:
+ yy66:
        yych = *++YYCURSOR;
-       if (yych == 'F') goto yy91;
+       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;
        goto yy18;
- yy75:
+ yy69:
        yych = *++YYCURSOR;
-       if (yych == 'N') goto yy91;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy67;
        goto yy18;
- yy76:
+ yy70:
        ++YYCURSOR;
- #line 621 "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;
-                       }
+       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;
                } else {
-                       goto use_double;
+                       if (yych == 'e') goto yy65;
+                       goto yy18;
                }
        }
- #endif
-       *p = YYCURSOR;
-       ZVAL_LONG(rval, parse_iv(start + 2));
-       return 1;
- }
- #line 1055 "ext/standard/var_unserializer.c"
- yy78:
+ yy72:
        yych = *++YYCURSOR;
-       if (yych == '"') goto yy92;
-       goto yy18;
- yy79:
+       if (yych != 'F') goto yy18;
+ yy73:
+       yych = *++YYCURSOR;
+       if (yych != ';') goto yy18;
        ++YYCURSOR;
- #line 584 "ext/standard/var_unserializer.re"
 -#line 590 "ext/standard/var_unserializer.re"
++#line 652 "ext/standard/var_unserializer.re"
        {
-       zend_long id;
-       *p = YYCURSOR;
-       if (!var_hash) return 0;
+       *p = YYCURSOR;
 -      INIT_PZVAL(*rval);
  
-       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;
 -      if (!strncmp(start + 2, "NAN", 3)) {
 -              ZVAL_DOUBLE(*rval, php_get_nan());
 -      } else if (!strncmp(start + 2, "INF", 3)) {
 -              ZVAL_DOUBLE(*rval, php_get_inf());
 -      } else if (!strncmp(start + 2, "-INF", 4)) {
 -              ZVAL_DOUBLE(*rval, -php_get_inf());
++      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);
        }
  
-       ZVAL_COPY(rval, rval_ref);
        return 1;
  }
- #line 1087 "ext/standard/var_unserializer.c"
- yy81:
 -#line 1159 "ext/standard/var_unserializer.c"
++#line 1214 "ext/standard/var_unserializer.c"
+ yy76:
        yych = *++YYCURSOR;
-       if (yych == '"') goto yy94;
+       if (yych == 'N') goto yy73;
        goto yy18;
- yy82:
+ 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;
- #line 769 "ext/standard/var_unserializer.re"
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy79;
+       if (yych != ';') goto yy18;
+       ++YYCURSOR;
 -#line 563 "ext/standard/var_unserializer.re"
++#line 626 "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;
-       }
 -#if SIZEOF_LONG == 4
++#if SIZEOF_ZEND_LONG == 4
+       int digits = YYCURSOR - start - 3;
  
-       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;
+       if (start[2] == '-' || start[2] == '+') {
+               digits--;
        }
  
-       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));
 -      /* Use double for large long values that were serialized on a 64-bit system */
++      /* 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(YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
++                      int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
  
-               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;
+                       if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
+                               goto use_double;
                        }
-                       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 */
-               BG(serialize_lock)++;
-               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;
-               }
-               BG(serialize_lock)--;
-               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 {
+                       goto use_double;
                }
-               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);
+ #endif
+       *p = YYCURSOR;
 -      INIT_PZVAL(*rval);
 -      ZVAL_LONG(*rval, parse_iv(start + 2));
++      ZVAL_LONG(rval, parse_iv(start + 2));
+       return 1;
  }
- #line 1241 "ext/standard/var_unserializer.c"
- yy84:
 -#line 1213 "ext/standard/var_unserializer.c"
++#line 1267 "ext/standard/var_unserializer.c"
+ yy83:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= '2') goto yy18;
+       yych = *++YYCURSOR;
+       if (yych != ';') goto yy18;
        ++YYCURSOR;
- #line 704 "ext/standard/var_unserializer.re"
 -#line 556 "ext/standard/var_unserializer.re"
++#line 620 "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);
 -      INIT_PZVAL(*rval);
 -      ZVAL_BOOL(*rval, parse_iv(start + 2));
++      ZVAL_BOOL(rval, parse_iv(start + 2));
        return 1;
  }
- #line 1278 "ext/standard/var_unserializer.c"
- yy86:
 -#line 1228 "ext/standard/var_unserializer.c"
++#line 1281 "ext/standard/var_unserializer.c"
+ yy87:
        ++YYCURSOR;
- #line 738 "ext/standard/var_unserializer.re"
 -#line 549 "ext/standard/var_unserializer.re"
++#line 614 "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 (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
-               return 0;
-       }
-       return finish_nested_data(UNSERIALIZE_PASSTHRU);
 -      INIT_PZVAL(*rval);
 -      ZVAL_NULL(*rval);
++      ZVAL_NULL(rval);
+       return 1;
  }
- #line 1305 "ext/standard/var_unserializer.c"
- yy88:
 -#line 1238 "ext/standard/var_unserializer.c"
++#line 1290 "ext/standard/var_unserializer.c"
+ yy89:
        yych = *++YYCURSOR;
        if (yych <= ',') {
-               if (yych == '+') goto yy96;
-               goto yy18;
+               if (yych != '+') goto yy18;
        } else {
-               if (yych <= '-') goto yy96;
+               if (yych <= '-') goto yy90;
                if (yych <= '/') goto yy18;
-               if (yych >= ':') goto yy18;
+               if (yych <= '9') goto yy91;
+               goto yy18;
        }
- yy89:
+ yy90:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+ yy91:
        ++YYCURSOR;
        if (YYLIMIT <= YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        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:
+       if (yych <= '9') goto yy91;
+       if (yych != ';') goto yy18;
        ++YYCURSOR;
- #line 762 "ext/standard/var_unserializer.re"
 -#line 526 "ext/standard/var_unserializer.re"
++#line 589 "ext/standard/var_unserializer.re"
        {
-     if (!var_hash) return 0;
 -      long id;
++      zend_long id;
  
-       return object_common2(UNSERIALIZE_PASSTHRU,
-                       object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
- }
- #line 1337 "ext/standard/var_unserializer.c"
- yy94:
-       ++YYCURSOR;
- #line 672 "ext/standard/var_unserializer.re"
-       {
-       size_t len, maxlen;
-       char *str;
+       *p = YYCURSOR;
+       if (!var_hash) return 0;
  
-       len = parse_uiv(start + 2);
-       maxlen = max - YYCURSOR;
-       if (maxlen < len) {
-               *p = start + 2;
+       id = parse_iv(start + 2) - 1;
 -      if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
++      if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
                return 0;
        }
  
-       str = (char*)YYCURSOR;
-       YYCURSOR += len;
-       if (*(YYCURSOR) != '"') {
-               *p = YYCURSOR;
 -      if (*rval == *rval_ref) return 0;
++      if (rval_ref == rval) {
 +              return 0;
 +      }
  
-       if (*(YYCURSOR + 1) != ';') {
-               *p = YYCURSOR + 1;
-               return 0;
 -      if (*rval != NULL) {
 -              var_push_dtor_no_addref(var_hash, 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;
        }
 -      *rval = *rval_ref;
 -      Z_ADDREF_PP(rval);
 -      Z_UNSET_ISREF_PP(rval);
 +
-       YYCURSOR += 2;
-       *p = YYCURSOR;
++      ZVAL_COPY(rval, rval_ref);
  
-       ZVAL_STRINGL(rval, str, len);
        return 1;
  }
- #line 1372 "ext/standard/var_unserializer.c"
 -#line 1284 "ext/standard/var_unserializer.c"
++#line 1338 "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;
+       }
  yy96:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy89;
-       goto yy18;
+       if (yych >= ':') goto yy18;
  yy97:
        ++YYCURSOR;
- #line 647 "ext/standard/var_unserializer.re"
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy97;
+       if (yych != ';') goto yy18;
+       ++YYCURSOR;
 -#line 505 "ext/standard/var_unserializer.re"
++#line 563 "ext/standard/var_unserializer.re"
        {
-       *p = YYCURSOR;
 -      long id;
++      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());
+       *p = YYCURSOR;
+       if (!var_hash) return 0;
+       id = parse_iv(start + 2) - 1;
 -      if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
++      if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+               return 0;
+       }
 -      if (*rval != NULL) {
 -              var_push_dtor_no_addref(var_hash, rval);
++      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_NULL(rval);
++              ZVAL_NEW_REF(rval_ref, rval_ref);
++              ZVAL_COPY(rval, rval_ref);
        }
 -      *rval = *rval_ref;
 -      Z_ADDREF_PP(rval);
 -      Z_SET_ISREF_PP(rval);
  
        return 1;
  }
- #line 1396 "ext/standard/var_unserializer.c"
 -#line 1328 "ext/standard/var_unserializer.c"
++#line 1387 "ext/standard/var_unserializer.c"
  }
- #line 924 "ext/standard/var_unserializer.re"
 -#line 879 "ext/standard/var_unserializer.re"
++#line 938 "ext/standard/var_unserializer.re"
  
  
        return 0;
index 978f401ac25b3d3b59011193048445581f1bad84,7fbab9f2f0b8dc0eb18c5ebd2bbed803444b1f8e..c5fe25d7274fdbfdcd9fa77bd04b8a70b1f7254f
@@@ -433,10 -405,15 +433,15 @@@ static inline int object_custom(UNSERIA
        return finish_nested_data(UNSERIALIZE_PASSTHRU);
  }
  
 -static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
 +static inline zend_long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
  {
 -      long elements;
 +      zend_long elements;
  
+       if( *p >= max - 2) {
+               zend_error(E_WARNING, "Bad unserialize data");
+               return -1;
+       }
        elements = parse_iv2((*p) + 2, p);
  
        (*p) += 2;
@@@ -760,10 -702,16 +765,14 @@@ use_double
  }
  
  "o:" iv ":" ["] {
+       long elements;
      if (!var_hash) return 0;
  
-       return object_common2(UNSERIALIZE_PASSTHRU,
-                       object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
 -      INIT_PZVAL(*rval);
 -
+       elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
+       if (elements < 0) {
+               return 0;
+       }
+       return object_common2(UNSERIALIZE_PASSTHRU, elements);
  }
  
  object ":" uiv ":" ["]        {
  
        elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
  
+       if (elements < 0) {
+          efree(class_name);
+          return 0;
+       }
        if (incomplete_class) {
 -              php_store_class_name(*rval, class_name, len2);
 +              php_store_class_name(rval, ZSTR_VAL(class_name), len2);
        }
 -      efree(class_name);
 +      zend_string_release(class_name);
  
        return object_common2(UNSERIALIZE_PASSTHRU, elements);
  }