]> granicus.if.org Git - php/commitdiff
Fixed unzserialize(), to disable creation of unsupported data structures through...
authorDmitry Stogov <dmitry@zend.com>
Fri, 13 Oct 2017 12:53:11 +0000 (15:53 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 13 Oct 2017 12:53:11 +0000 (15:53 +0300)
NEWS
ext/gmp/tests/bug70284.phpt
ext/soap/tests/bug70211.phpt
ext/standard/tests/serialize/bug70172.phpt
ext/standard/tests/serialize/bug70963.phpt
ext/standard/tests/serialize/unserialize_mem_leak.phpt
ext/standard/tests/strings/bug72433.phpt
ext/standard/var_unserializer.c
ext/standard/var_unserializer.re

diff --git a/NEWS b/NEWS
index d5247a9369ef3e5c7c1c3f64bf98932d7718f4dc..3f9cff1e5fbb8b2031fa0c3fa01ab7fbe21aec23 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -90,4 +90,8 @@ PHP                                                                        NEWS
   . Fixed bug #75173 (incorrect behavior of AppendIterator::append in foreach loop).
     (jhdxr)
 
+- Standard:
+  . Fixed unzserialize(), to disable creation of unsupported data structures
+    through manually crafted strings. (Dmitry)
+
 <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
index 58fc50cf2d95b429bc6866000214890ef72ac8a7..49df5d0359816060156741970ba523dd28c3353a 100644 (file)
@@ -34,17 +34,8 @@ $out = '';
 }
 ?>
 --EXPECTF--
-array(2) {
-  [0]=>
-  string(1) "1"
-  [1]=>
-  object(GMP)#%d (2) {
-    [0]=>
-    array(1) {
-      [0]=>
-      string(1) "1"
-    }
-    ["num"]=>
-    string(1) "1"
-  }
-}
+Fatal error: Uncaught Exception: Could not unserialize number in %sbug70284.php:6
+Stack trace:
+#0 %sbug70284.php(6): unserialize('%s')
+#1 {main}
+  thrown in %sbug70284.php on line 6
index 8346b35ab7e3069dbe312d7c7737b4671239e2aa..2d7124376b8a6620e3c5613e1635f882c0ef250f 100644 (file)
@@ -16,7 +16,7 @@ function ptr2str($ptr)
 }
 
 $sf = new SoapFault('1', 'string', 'detail', 'header','line', str_repeat("A",232).ptr2str($addr));
-$ob = unserialize("a:3:{i:0;".serialize($sf).'i:1;r:12;i:2;r:10;}');
+$ob = unserialize("a:3:{i:0;".serialize($sf).'i:1;R:12;i:2;R:10;}');
 
 var_dump($ob[1]);
 ?>
index 471d1a4b4e5c9756a6f66b37b7f28cc542e5fec8..a2359d6434539f07ccf6dadcbec29f9ed55b533a 100644 (file)
@@ -19,7 +19,7 @@ $fakezval .= "\x01";
 $fakezval .= "\x00";
 $fakezval .= "\x00\x00";
 
-$inner = 'r:2;';
+$inner = 'R:2;';
 $exploit = 'a:2:{i:0;i:1;i:1;C:3:"obj":'.strlen($inner).':{'.$inner.'}}';
 
 $data = unserialize($exploit);
index 0bdfb2c4c9aae8b563163eeab17bafaa345a68c8..c4e2267b043d54a74d9d537b995bfa01b33c4b37 100644 (file)
@@ -25,22 +25,6 @@ array(2) {
   [1]=>
   string(4) "test"
 }
-array(2) {
-  [0]=>
-  object(Exception)#%d (6) {
-    ["message":protected]=>
-    string(0) ""
-    ["string":"Exception":private]=>
-    string(0) ""
-    ["code":protected]=>
-    int(0)
-    ["file":protected]=>
-    string(%d) "%s"
-    ["line":protected]=>
-    int(3)
-    ["previous":"Exception":private]=>
-    NULL
-  }
-  [1]=>
-  string(4) "test"
-}
+
+Notice: unserialize(): Error at offset %d of %d bytes in %sbug70963.php on line 3
+bool(false)
index 97c59f9ad1ced05ddc8b91cb10169cf183518a0d..2a295d83b9992ff8f26e9d0ccf2c076c64ee0c5a 100644 (file)
@@ -8,9 +8,12 @@ function foo() {
        gc_collect_cycles();
 }
 
+$str = 'a:1:{i:0;R:1;}';
+foo(unserialize($str));
 $str = 'a:1:{i:0;r:1;}';
 foo(unserialize($str));
 echo "okey";
 ?>
---EXPECT--
+--EXPECTF--
+Notice: unserialize(): Error at offset %d of %d bytes in %sunserialize_mem_leak.php on line 9
 okey
index d5a6612f2b7eb6f94d16777dbf276aebf068b2e2..534b1e6ac6f6b530a5f7bbb7545dca70a7ebd7ca 100644 (file)
@@ -19,41 +19,5 @@ $fill_freed_space_2 = "filler_zval_2";
 var_dump($free_me);
 ?>
 --EXPECTF--
-array(3) {
-  [0]=>
-  array(3) {
-    [0]=>
-    *RECURSION*
-    [1]=>
-    *RECURSION*
-    [2]=>
-    object(ArrayObject)#%d (1) {
-      ["storage":"ArrayObject":private]=>
-      *RECURSION*
-    }
-  }
-  [1]=>
-  array(3) {
-    [0]=>
-    *RECURSION*
-    [1]=>
-    *RECURSION*
-    [2]=>
-    object(ArrayObject)#%d (1) {
-      ["storage":"ArrayObject":private]=>
-      *RECURSION*
-    }
-  }
-  [2]=>
-  object(ArrayObject)#%d (1) {
-    ["storage":"ArrayObject":private]=>
-    array(3) {
-      [0]=>
-      *RECURSION*
-      [1]=>
-      *RECURSION*
-      [2]=>
-      *RECURSION*
-    }
-  }
-}
+Notice: unserialize(): Error at offset %d of %d bytes in %sbug72433.php on line 8
+bool(false)
index 530c88fb7a3d5264a944780261703eafdefabc6c..b32379a06443a6b31a901be1e8f289b26a203258 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.16 */
+/* Generated by re2c 0.14.3 */
 #line 1 "ext/standard/var_unserializer.re"
 /*
   +----------------------------------------------------------------------+
@@ -681,503 +681,152 @@ static int php_var_unserialize_internal(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 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 yy88;
 yy3:
-#line 1035 "ext/standard/var_unserializer.re"
+#line 1036 "ext/standard/var_unserializer.re"
        { return 0; }
-#line 708 "ext/standard/var_unserializer.c"
+#line 710 "ext/standard/var_unserializer.c"
 yy4:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy17;
+       if (yych == ':') goto yy83;
        goto yy3;
 yy5:
        yych = *++YYCURSOR;
-       if (yych == ';') goto yy19;
+       if (yych == ';') goto yy81;
        goto yy3;
 yy6:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy21;
+       if (yych == ':') goto yy77;
        goto yy3;
 yy7:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy22;
+       if (yych == ':') goto yy71;
        goto yy3;
 yy8:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy23;
+       if (yych == ':') goto yy48;
        goto yy3;
 yy9:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy24;
+       if (yych == ':') goto yy42;
        goto yy3;
 yy10:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy25;
+       if (yych == ':') goto yy36;
        goto yy3;
 yy11:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy26;
+       if (yych == ':') goto yy30;
        goto yy3;
 yy12:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == ':') goto yy27;
+       if (yych == ':') goto yy24;
        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 1029 "ext/standard/var_unserializer.re"
+#line 1030 "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 761 "ext/standard/var_unserializer.c"
+#line 759 "ext/standard/var_unserializer.c"
+yy16:
+       yych = *++YYCURSOR;
+       goto yy3;
 yy17:
        yych = *++YYCURSOR;
        if (yybm[0+yych] & 128) {
-               goto yy30;
+               goto yy19;
        }
 yy18:
        YYCURSOR = YYMARKER;
        goto yy3;
 yy19:
        ++YYCURSOR;
-#line 701 "ext/standard/var_unserializer.re"
-       {
-       *p = YYCURSOR;
-       ZVAL_NULL(rval);
-       return 1;
-}
-#line 778 "ext/standard/var_unserializer.c"
-yy21:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy32;
-       goto yy18;
-yy22:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy34;
-       goto yy18;
-yy23:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy36;
-       goto yy18;
-yy24:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '1') goto yy38;
-       goto yy18;
-yy25:
-       yych = *++YYCURSOR;
-       if (yych <= '/') {
-               if (yych <= ',') {
-                       if (yych == '+') goto yy39;
-                       goto yy18;
-               } else {
-                       if (yych <= '-') goto yy40;
-                       if (yych <= '.') goto yy41;
-                       goto yy18;
-               }
-       } else {
-               if (yych <= 'I') {
-                       if (yych <= '9') goto yy42;
-                       if (yych <= 'H') goto yy18;
-                       goto yy44;
-               } else {
-                       if (yych == 'N') goto yy45;
-                       goto yy18;
-               }
-       }
-yy26:
-       yych = *++YYCURSOR;
-       if (yych <= ',') {
-               if (yych == '+') goto yy46;
-               goto yy18;
-       } else {
-               if (yych <= '-') goto yy46;
-               if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy47;
-               goto yy18;
-       }
-yy27:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy49;
-       goto yy18;
-yy28:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy51;
-       goto yy18;
-yy29:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy53;
-       goto yy18;
-yy30:
-       ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yybm[0+yych] & 128) {
-               goto yy30;
-       }
-       if (yych <= '/') goto yy18;
-       if (yych <= ':') goto yy55;
-       goto yy18;
-yy32:
-       ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy32;
-       if (yych == ';') goto yy56;
-       goto yy18;
-yy34:
-       ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy34;
-       if (yych <= ':') goto yy58;
-       goto yy18;
-yy36:
-       ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy36;
-       if (yych <= ':') goto yy59;
-       goto yy18;
-yy38:
-       yych = *++YYCURSOR;
-       if (yych == ';') goto yy60;
-       goto yy18;
-yy39:
-       yych = *++YYCURSOR;
-       if (yych == '.') goto yy41;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy42;
-       goto yy18;
-yy40:
-       yych = *++YYCURSOR;
-       if (yych <= '/') {
-               if (yych != '.') goto yy18;
-       } else {
-               if (yych <= '9') goto yy42;
-               if (yych == 'I') goto yy44;
-               goto yy18;
-       }
-yy41:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy62;
-       goto yy18;
-yy42:
-       ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
-       yych = *YYCURSOR;
-       if (yych <= ':') {
-               if (yych <= '.') {
-                       if (yych <= '-') goto yy18;
-                       goto yy62;
-               } else {
-                       if (yych <= '/') goto yy18;
-                       if (yych <= '9') goto yy42;
-                       goto yy18;
-               }
-       } else {
-               if (yych <= 'E') {
-                       if (yych <= ';') goto yy64;
-                       if (yych <= 'D') goto yy18;
-                       goto yy66;
-               } else {
-                       if (yych == 'e') goto yy66;
-                       goto yy18;
-               }
+               goto yy19;
        }
-yy44:
-       yych = *++YYCURSOR;
-       if (yych == 'N') goto yy67;
-       goto yy18;
-yy45:
-       yych = *++YYCURSOR;
-       if (yych == 'A') goto yy68;
-       goto yy18;
-yy46:
-       yych = *++YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych >= ':') goto yy18;
-yy47:
-       ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy47;
-       if (yych == ';') goto yy69;
-       goto yy18;
-yy49:
-       ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
-       yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy49;
-       if (yych <= ':') goto yy71;
-       goto yy18;
-yy51:
-       ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy51;
-       if (yych == ';') goto yy72;
-       goto yy18;
-yy53:
-       ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
-       yych = *YYCURSOR;
-       if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy53;
-       if (yych <= ':') goto yy74;
-       goto yy18;
-yy55:
+       if (yych >= ';') goto yy18;
        yych = *++YYCURSOR;
-       if (yych == '"') goto yy75;
-       goto yy18;
-yy56:
+       if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 652 "ext/standard/var_unserializer.re"
+#line 878 "ext/standard/var_unserializer.re"
        {
-       zend_long id;
+       size_t len, len2, len3, maxlen;
+       zend_long elements;
+       char *str;
+       zend_string *class_name;
+       zend_class_entry *ce;
+       int incomplete_class = 0;
 
-       *p = YYCURSOR;
-       if (!var_hash) return 0;
+       int custom_object = 0;
 
-       id = parse_uiv(start + 2) - 1;
-       if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
-               return 0;
+       zval user_func;
+       zval retval;
+       zval args[1];
+
+    if (!var_hash) return 0;
+       if (*start == 'C') {
+               custom_object = 1;
        }
 
-       if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+       len2 = len = parse_uiv(start + 2);
+       maxlen = max - YYCURSOR;
+       if (maxlen < len || len == 0) {
+               *p = start + 2;
                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);
-       }
+       str = (char*)YYCURSOR;
 
-       return 1;
-}
-#line 1002 "ext/standard/var_unserializer.c"
-yy58:
-       yych = *++YYCURSOR;
-       if (yych == '"') goto yy77;
-       goto yy18;
-yy59:
-       yych = *++YYCURSOR;
-       if (yych == '{') goto yy79;
-       goto yy18;
-yy60:
-       ++YYCURSOR;
-#line 707 "ext/standard/var_unserializer.re"
-       {
-       *p = YYCURSOR;
-       ZVAL_BOOL(rval, parse_iv(start + 2));
-       return 1;
-}
-#line 1019 "ext/standard/var_unserializer.c"
-yy62:
-       ++YYCURSOR;
-       if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
-       yych = *YYCURSOR;
-       if (yych <= ';') {
-               if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy62;
-               if (yych <= ':') goto yy18;
-       } else {
-               if (yych <= 'E') {
-                       if (yych <= 'D') goto yy18;
-                       goto yy66;
-               } else {
-                       if (yych == 'e') goto yy66;
-                       goto yy18;
-               }
+       YYCURSOR += len;
+
+       if (*(YYCURSOR) != '"') {
+               *p = YYCURSOR;
+               return 0;
        }
-yy64:
-       ++YYCURSOR;
-#line 755 "ext/standard/var_unserializer.re"
-       {
-#if SIZEOF_ZEND_LONG == 4
-use_double:
-#endif
-       *p = YYCURSOR;
-       ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
-       return 1;
-}
-#line 1048 "ext/standard/var_unserializer.c"
-yy66:
-       yych = *++YYCURSOR;
-       if (yych <= ',') {
-               if (yych == '+') goto yy81;
-               goto yy18;
-       } else {
-               if (yych <= '-') goto yy81;
-               if (yych <= '/') goto yy18;
-               if (yych <= '9') goto yy82;
-               goto yy18;
+       if (*(YYCURSOR+1) != ':') {
+               *p = YYCURSOR+1;
+               return 0;
        }
-yy67:
-       yych = *++YYCURSOR;
-       if (yych == 'F') goto yy84;
-       goto yy18;
-yy68:
-       yych = *++YYCURSOR;
-       if (yych == 'N') goto yy84;
-       goto yy18;
-yy69:
-       ++YYCURSOR;
-#line 713 "ext/standard/var_unserializer.re"
-       {
-#if SIZEOF_ZEND_LONG == 4
-       int digits = YYCURSOR - start - 3;
 
-       if (start[2] == '-' || start[2] == '+') {
-               digits--;
+       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;
        }
 
-       /* 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 {
-                       goto use_double;
-               }
-       }
-#endif
-       *p = YYCURSOR;
-       ZVAL_LONG(rval, parse_iv(start + 2));
-       return 1;
-}
-#line 1096 "ext/standard/var_unserializer.c"
-yy71:
-       yych = *++YYCURSOR;
-       if (yych == '"') goto yy85;
-       goto yy18;
-yy72:
-       ++YYCURSOR;
-#line 677 "ext/standard/var_unserializer.re"
-       {
-       zend_long id;
-
-       *p = YYCURSOR;
-       if (!var_hash) return 0;
-
-       id = parse_uiv(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)))) {
-               return 0;
-       }
-
-       ZVAL_COPY(rval, rval_ref);
-
-       return 1;
-}
-#line 1127 "ext/standard/var_unserializer.c"
-yy74:
-       yych = *++YYCURSOR;
-       if (yych == '"') goto yy87;
-       goto yy18;
-yy75:
-       ++YYCURSOR;
-#line 877 "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);
+       class_name = zend_string_init(str, len, 0);
 
        do {
                if(!unserialize_allowed_class(class_name, var_hash)) {
@@ -1282,47 +931,48 @@ yy75:
 
        return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 1286 "ext/standard/var_unserializer.c"
-yy77:
+#line 935 "ext/standard/var_unserializer.c"
+yy24:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy25:
+       ++YYCURSOR;
+       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy25;
+       if (yych >= ';') goto yy18;
+       yych = *++YYCURSOR;
+       if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 802 "ext/standard/var_unserializer.re"
+#line 867 "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;
-       }
+       zend_long elements;
+    if (!var_hash) return 0;
 
-       if (*(YYCURSOR + 1) != ';') {
-               efree(str);
-               *p = YYCURSOR + 1;
+       elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
+       if (elements < 0 || elements >= HT_MAX_SIZE) {
                return 0;
        }
-
-       YYCURSOR += 2;
-       *p = YYCURSOR;
-
-       ZVAL_STR(rval, str);
-       return 1;
+       return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 1323 "ext/standard/var_unserializer.c"
-yy79:
+#line 961 "ext/standard/var_unserializer.c"
+yy30:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy31:
        ++YYCURSOR;
-#line 836 "ext/standard/var_unserializer.re"
+       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy31;
+       if (yych >= ';') goto yy18;
+       yych = *++YYCURSOR;
+       if (yych != '{') goto yy18;
+       ++YYCURSOR;
+#line 837 "ext/standard/var_unserializer.re"
        {
        zend_long elements = parse_iv(start + 2);
        /* use iv() not uiv() in order to check data range */
@@ -1352,40 +1002,71 @@ yy79:
 
        return finish_nested_data(UNSERIALIZE_PASSTHRU);
 }
-#line 1356 "ext/standard/var_unserializer.c"
-yy81:
+#line 1006 "ext/standard/var_unserializer.c"
+yy36:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
        if (yych >= ':') goto yy18;
-yy82:
+yy37:
        ++YYCURSOR;
-       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy18;
-       if (yych <= '9') goto yy82;
-       if (yych == ';') goto yy64;
-       goto yy18;
-yy84:
+       if (yych <= '9') goto yy37;
+       if (yych >= ';') goto yy18;
        yych = *++YYCURSOR;
-       if (yych == ';') goto yy89;
-       goto yy18;
-yy85:
+       if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 866 "ext/standard/var_unserializer.re"
+#line 803 "ext/standard/var_unserializer.re"
        {
-       zend_long elements;
-    if (!var_hash) return 0;
+       size_t len, maxlen;
+       zend_string *str;
 
-       elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
-       if (elements < 0 || elements >= HT_MAX_SIZE) {
+       len = parse_uiv(start + 2);
+       maxlen = max - YYCURSOR;
+       if (maxlen < len) {
+               *p = start + 2;
                return 0;
        }
-       return object_common2(UNSERIALIZE_PASSTHRU, elements);
+
+       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 1386 "ext/standard/var_unserializer.c"
-yy87:
+#line 1055 "ext/standard/var_unserializer.c"
+yy42:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy43:
        ++YYCURSOR;
-#line 764 "ext/standard/var_unserializer.re"
+       if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy43;
+       if (yych >= ';') goto yy18;
+       yych = *++YYCURSOR;
+       if (yych != '"') goto yy18;
+       ++YYCURSOR;
+#line 765 "ext/standard/var_unserializer.re"
        {
        size_t len, maxlen;
        char *str;
@@ -1423,10 +1104,152 @@ yy87:
        }
        return 1;
 }
-#line 1427 "ext/standard/var_unserializer.c"
-yy89:
+#line 1108 "ext/standard/var_unserializer.c"
+yy48:
+       yych = *++YYCURSOR;
+       if (yych <= '/') {
+               if (yych <= ',') {
+                       if (yych == '+') goto yy52;
+                       goto yy18;
+               } else {
+                       if (yych <= '-') goto yy50;
+                       if (yych <= '.') goto yy55;
+                       goto yy18;
+               }
+       } else {
+               if (yych <= 'I') {
+                       if (yych <= '9') goto yy53;
+                       if (yych <= 'H') goto yy18;
+                       goto yy51;
+               } else {
+                       if (yych != 'N') goto yy18;
+               }
+       }
+       yych = *++YYCURSOR;
+       if (yych == 'A') goto yy70;
+       goto yy18;
+yy50:
+       yych = *++YYCURSOR;
+       if (yych <= '/') {
+               if (yych == '.') goto yy55;
+               goto yy18;
+       } else {
+               if (yych <= '9') goto yy53;
+               if (yych != 'I') goto yy18;
+       }
+yy51:
+       yych = *++YYCURSOR;
+       if (yych == 'N') goto yy66;
+       goto yy18;
+yy52:
+       yych = *++YYCURSOR;
+       if (yych == '.') goto yy55;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy53:
+       ++YYCURSOR;
+       if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+       yych = *YYCURSOR;
+       if (yych <= ':') {
+               if (yych <= '.') {
+                       if (yych <= '-') goto yy18;
+                       goto yy64;
+               } else {
+                       if (yych <= '/') goto yy18;
+                       if (yych <= '9') goto yy53;
+                       goto yy18;
+               }
+       } else {
+               if (yych <= 'E') {
+                       if (yych <= ';') goto yy58;
+                       if (yych <= 'D') goto yy18;
+                       goto yy60;
+               } else {
+                       if (yych == 'e') goto yy60;
+                       goto yy18;
+               }
+       }
+yy55:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy56:
+       ++YYCURSOR;
+       if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+       yych = *YYCURSOR;
+       if (yych <= ';') {
+               if (yych <= '/') goto yy18;
+               if (yych <= '9') goto yy56;
+               if (yych <= ':') goto yy18;
+       } else {
+               if (yych <= 'E') {
+                       if (yych <= 'D') goto yy18;
+                       goto yy60;
+               } else {
+                       if (yych == 'e') goto yy60;
+                       goto yy18;
+               }
+       }
+yy58:
+       ++YYCURSOR;
+#line 756 "ext/standard/var_unserializer.re"
+       {
+#if SIZEOF_ZEND_LONG == 4
+use_double:
+#endif
+       *p = YYCURSOR;
+       ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
+       return 1;
+}
+#line 1205 "ext/standard/var_unserializer.c"
+yy60:
+       yych = *++YYCURSOR;
+       if (yych <= ',') {
+               if (yych != '+') goto yy18;
+       } else {
+               if (yych <= '-') goto yy61;
+               if (yych <= '/') goto yy18;
+               if (yych <= '9') goto yy62;
+               goto yy18;
+       }
+yy61:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy62:
        ++YYCURSOR;
-#line 739 "ext/standard/var_unserializer.re"
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy62;
+       if (yych == ';') goto yy58;
+       goto yy18;
+yy64:
+       ++YYCURSOR;
+       if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+       yych = *YYCURSOR;
+       if (yych <= ';') {
+               if (yych <= '/') goto yy18;
+               if (yych <= '9') goto yy64;
+               if (yych <= ':') goto yy18;
+               goto yy58;
+       } else {
+               if (yych <= 'E') {
+                       if (yych <= 'D') goto yy18;
+                       goto yy60;
+               } else {
+                       if (yych == 'e') goto yy60;
+                       goto yy18;
+               }
+       }
+yy66:
+       yych = *++YYCURSOR;
+       if (yych != 'F') goto yy18;
+yy67:
+       yych = *++YYCURSOR;
+       if (yych != ';') goto yy18;
+       ++YYCURSOR;
+#line 740 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
 
@@ -1442,9 +1265,161 @@ yy89:
 
        return 1;
 }
-#line 1446 "ext/standard/var_unserializer.c"
+#line 1269 "ext/standard/var_unserializer.c"
+yy70:
+       yych = *++YYCURSOR;
+       if (yych == 'N') goto yy67;
+       goto yy18;
+yy71:
+       yych = *++YYCURSOR;
+       if (yych <= ',') {
+               if (yych != '+') goto yy18;
+       } else {
+               if (yych <= '-') goto yy72;
+               if (yych <= '/') goto yy18;
+               if (yych <= '9') goto yy73;
+               goto yy18;
+       }
+yy72:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy73:
+       ++YYCURSOR;
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy73;
+       if (yych != ';') goto yy18;
+       ++YYCURSOR;
+#line 714 "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 {
+                       goto use_double;
+               }
+       }
+#endif
+       *p = YYCURSOR;
+       ZVAL_LONG(rval, parse_iv(start + 2));
+       return 1;
+}
+#line 1322 "ext/standard/var_unserializer.c"
+yy77:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= '2') goto yy18;
+       yych = *++YYCURSOR;
+       if (yych != ';') goto yy18;
+       ++YYCURSOR;
+#line 708 "ext/standard/var_unserializer.re"
+       {
+       *p = YYCURSOR;
+       ZVAL_BOOL(rval, parse_iv(start + 2));
+       return 1;
+}
+#line 1336 "ext/standard/var_unserializer.c"
+yy81:
+       ++YYCURSOR;
+#line 702 "ext/standard/var_unserializer.re"
+       {
+       *p = YYCURSOR;
+       ZVAL_NULL(rval);
+       return 1;
+}
+#line 1345 "ext/standard/var_unserializer.c"
+yy83:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy84:
+       ++YYCURSOR;
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy84;
+       if (yych != ';') goto yy18;
+       ++YYCURSOR;
+#line 677 "ext/standard/var_unserializer.re"
+       {
+       zend_long id;
+
+       *p = YYCURSOR;
+       if (!var_hash) return 0;
+
+       id = parse_uiv(start + 2) - 1;
+       if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+               return 0;
+       }
+
+       if (rval_ref == rval) {
+               return 0;
+       }
+
+       ZVAL_DEREF(rval_ref);
+       if (Z_TYPE_P(rval_ref) != IS_OBJECT) {
+               return 0;
+       }
+
+       ZVAL_COPY(rval, rval_ref);
+
+       return 1;
+}
+#line 1383 "ext/standard/var_unserializer.c"
+yy88:
+       yych = *++YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych >= ':') goto yy18;
+yy89:
+       ++YYCURSOR;
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
+       yych = *YYCURSOR;
+       if (yych <= '/') goto yy18;
+       if (yych <= '9') goto yy89;
+       if (yych != ';') goto yy18;
+       ++YYCURSOR;
+#line 652 "ext/standard/var_unserializer.re"
+       {
+       zend_long id;
+
+       *p = YYCURSOR;
+       if (!var_hash) return 0;
+
+       id = parse_uiv(start + 2) - 1;
+       if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+               return 0;
+       }
+
+       if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+               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);
+       }
+
+       return 1;
+}
+#line 1421 "ext/standard/var_unserializer.c"
 }
-#line 1037 "ext/standard/var_unserializer.re"
+#line 1038 "ext/standard/var_unserializer.re"
 
 
        return 0;
index e588a024d8688d375ebda9daf747ff69c135b34a..912d7be4c80c91df4c53351111cb4e5e59acbc87 100644 (file)
@@ -689,7 +689,8 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
                return 0;
        }
 
-       if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+       ZVAL_DEREF(rval_ref);
+       if (Z_TYPE_P(rval_ref) != IS_OBJECT) {
                return 0;
        }