]> granicus.if.org Git - php/commitdiff
- MFH Several serialize/unserialize fixes
authorMarcus Boerger <helly@php.net>
Fri, 24 Sep 2004 21:57:19 +0000 (21:57 +0000)
committerMarcus Boerger <helly@php.net>
Fri, 24 Sep 2004 21:57:19 +0000 (21:57 +0000)
12 files changed:
ext/standard/incomplete_class.c
ext/standard/php_incomplete_class.h
ext/standard/php_var.h
ext/standard/tests/file/bug22414.phpt
ext/standard/tests/serialize/001.phpt
ext/standard/tests/serialize/002.phpt
ext/standard/tests/serialize/bug14293.phpt
ext/standard/tests/serialize/bug25378.phpt
ext/standard/tests/serialize/bug27469.phpt
ext/standard/tests/serialize/bug28325.phpt
ext/standard/var.c
ext/standard/var_unserializer.c

index a5f74b1a844e25afdfbb1600df8c93c73712fed7..f9a1f0c7eebe6ca878f8ff66fd5c89bbfae02720 100644 (file)
@@ -115,9 +115,6 @@ char *php_lookup_class_name(zval *object, size_t *nlen, zend_bool del TSRMLS_DC)
 
                if (nlen)
                        *nlen = Z_STRLEN_PP(val);
-
-               if (del)
-                       zend_hash_del(object_properties, MAGIC_MEMBER, sizeof(MAGIC_MEMBER));
        }
 
        return (retval);
index 6cf7f5eb998c72b3c0fae8ab96ae6a448fc302dd..649f8b7ca57cfeb14a0d329e312592df15b577c1 100644 (file)
@@ -31,6 +31,7 @@
        if (Z_OBJCE_P(struc) == BG(incomplete_class)) {                                         \
                class_name = php_lookup_class_name(struc, &name_len, 1 TSRMLS_CC);              \
                free_class_name = 1;                                                                                    \
+               incomplete_class = 1; \
        } else {                                                                                                                        \
                class_name = Z_OBJCE_P(struc)->name;                                                    \
                name_len   = Z_OBJCE_P(struc)->name_length;                                             \
@@ -42,7 +43,8 @@
 #define PHP_CLASS_ATTRIBUTES                                                                                   \
        char *class_name;                                                                                                       \
        size_t name_len;                                                                                                        \
-       zend_bool free_class_name = 0                                                                           \
+       zend_bool free_class_name = 0;                                                                          \
+       zend_bool incomplete_class = 0
 
 #define INCOMPLETE_CLASS "__PHP_Incomplete_Class"
 #define MAGIC_MEMBER "__PHP_Incomplete_Class_Name"
index 18cf3d78678ed710af2b00f5298d31e2cb8c4165..d6f569c2aad690596c499248da3f7b7b7b9ef0c3 100644 (file)
@@ -46,7 +46,7 @@ struct php_unserialize_data {
 typedef struct php_unserialize_data php_unserialize_data_t;
 
 PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash TSRMLS_DC);
-PHPAPI int php_var_unserialize(zval **rval, const char **p, const char *max, php_unserialize_data_t *var_hash TSRMLS_DC);
+PHPAPI int php_var_unserialize(zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC);
 
 #define PHP_VAR_SERIALIZE_INIT(var_hash) \
    zend_hash_init(&(var_hash), 10, NULL, NULL, 0)
index f6effd272c298fc486d97a97cefc01b43b73a7c0..db85edd0f093d23cf87278f9122beef8b8187282 100644 (file)
@@ -1,5 +1,7 @@
 --TEST--
 Bug #22414: passthru() does not read data correctly
+--SKIPIF--
+<?php if (strtolower(@getenv('TEST_PHP_EXECUTABLE'))=='auto') die('skip: TEST_PHP_EXECUTABLE = auto'); ?>
 --INI--
 safe_mode=
 output_handler=
index 811355beb79426436e548e8c52d26c201b3547c5..958171ace992ec50c145912d0d56566429edea07 100644 (file)
@@ -1,7 +1,5 @@
 --TEST--
 serialize()/unserialize()/var_dump()
---POST--
---GET--
 --FILE--
 <?php 
 class t
@@ -14,11 +12,16 @@ class t
 
 class s
 {
+       var $a;
+       var $b;
+       var $c;
+
        function s()
        {
                $this->a = "hallo";
                $this->b = "php";
                $this->c = "world";
+               $this->d = "!";
        }
 
        function __sleep()
@@ -94,9 +97,11 @@ object(t)(1) {
 __sleep called
 O:1:"s":2:{s:1:"a";s:5:"hallo";s:1:"c";s:5:"world";}
 __wakeup called
-object(s)(2) {
+object(s)(3) {
   ["a"]=>
   string(5) "hallo"
+  ["b"]=>
+  NULL
   ["c"]=>
   string(5) "world"
 }
index 7b83c28a63463c1f7cac4c019d90b2d11f2b1958..841e104a6b5587f2c0f838b47fbb31ad7c882e9e 100644 (file)
@@ -1,36 +1,44 @@
 --TEST--
-serialize() (Bug #14293)
---POST--
---GET--
+Bug #25378 (unserialize() crashes with invalid data)
 --FILE--
 <?php 
-class t
-{
-       function t()
-       {
-               $this->a = 'hello';
-       }
-
-       function __sleep()
-       {
-               echo "__sleep called\n";
-               return array('a','b');
-       }       
-}
-
-$t = new t();
-$data = serialize($t);
-echo "$data\n";
-$t = unserialize($data);
-var_dump($t);
-
+var_dump(unserialize('b:0;'));
+var_dump(unserialize('b:1;'));
+var_dump(unserialize('i:823;'));
+var_dump(unserialize('s:0:"";'));
+var_dump(unserialize('s:3:"foo";'));
+var_dump(unserialize('a:1:{i:0;s:2:"12";}'));
+var_dump(unserialize('a:2:{i:0;a:0:{}i:1;a:0:{}}'));
+var_dump(unserialize('a:3:{i:0;s:3:"foo";i:1;s:3:"bar";i:2;s:3:"baz";}'));
+var_dump(unserialize('O:8:"stdClass":0:{}'));
 ?>
+===DONE===
 --EXPECT--
-__sleep called
-O:1:"t":2:{s:1:"a";s:5:"hello";s:1:"b";N;}
-object(t)(2) {
-  ["a"]=>
-  string(5) "hello"
-  ["b"]=>
-  NULL
+bool(false)
+bool(true)
+int(823)
+string(0) ""
+string(3) "foo"
+array(1) {
+  [0]=>
+  string(2) "12"
+}
+array(2) {
+  [0]=>
+  array(0) {
+  }
+  [1]=>
+  array(0) {
+  }
+}
+array(3) {
+  [0]=>
+  string(3) "foo"
+  [1]=>
+  string(3) "bar"
+  [2]=>
+  string(3) "baz"
+}
+object(stdClass)(0) {
 }
+===DONE===
index 3fca7e406edcf4ec7574a3888b2d6881d5670201..ca28bc1853c2bd9c3e930f9c58c64ec51e6a78c8 100644 (file)
@@ -25,10 +25,8 @@ var_dump($t);
 ?>
 --EXPECTF--
 __sleep called
-
-Notice: serialize(): "b" returned as member variable from __sleep() but does not exist in %sbug14293.php on line %d
 O:1:"t":2:{s:1:"a";s:5:"hello";s:1:"b";N;}
-object(t)#%d (2) {
+object(t)(2) {
   ["a"]=>
   string(5) "hello"
   ["b"]=>
index e59044002f1b2d4ebba4e5a644e5e600292764c7..e865b96e9935f281967a8feb3b1cca373b6364b8 100644 (file)
@@ -3,7 +3,57 @@ Bug #25378 (unserialize() crashes with invalid data)
 --FILE--
 <?php 
 var_dump(unserialize("s:-1:\"\";"));
+var_dump(unserialize("i:823"));
+var_dump(unserialize("O:8:\"stdClass :0:{}"));
+var_dump(unserialize("O:8:\"stdClass\"+0:{}"));
+var_dump(unserialize("O:1000:\"stdClass\":0:{}"));
+var_dump(unserialize("a:2:{i:0;s:2:\"12\":"));
+var_dump(unserialize("a:2:{i:0;s:2:\"12\";i:1;s:3000:\"123"));
+var_dump(unserialize("a:2:{i:0;s:2:\"12\"+i:1;s:3:\"123\";}"));
+var_dump(unserialize("a:2:{i:0;s:2:\"12\";i:1;s:3:\"123\";"));
+var_dump(unserialize("s:3000:\"123\";"));
+var_dump(unserialize("s:3000:\"123"));
+var_dump(unserialize("s:3:\"123;"));
+var_dump(unserialize("s:0:\"123\";"));
 ?>
+===DONE===
 --EXPECTF--
-Notice: unserialize(): Error at offset 0 of 8 bytes in %s on line %d
+Notice: unserialize(): Error at offset 0 of 8 bytes in %sbug25378.php on line %d
 bool(false)
+
+Notice: unserialize(): Error at offset 0 of 5 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 13 of 19 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 14 of 19 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 2 of 22 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 17 of 18 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 24 of 33 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 17 of 33 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 33 of 32 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 2 of 13 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 2 of 11 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 8 of 9 bytes in %sbug25378.php on line %d
+bool(false)
+
+Notice: unserialize(): Error at offset 5 of 10 bytes in %sbug25378.php on line %d
+bool(false)
+===DONE===
index e8d14106a8ba92f25da63fcfceee4b7fe6a3cf00..a932f6c0fe8006d8b1848ac977243fc296313a68 100644 (file)
@@ -11,17 +11,17 @@ echo serialize($obj)."\n";
 var_dump($obj);
 ?>
 --EXPECT--
-object(__PHP_Incomplete_Class)#1 (1) {
+object(__PHP_Incomplete_Class)(1) {
   ["__PHP_Incomplete_Class_Name"]=>
-  string(9) "TestClass"
+  string(9) "testclass"
 }
-O:9:"TestClass":0:{}
-object(__PHP_Incomplete_Class)#1 (1) {
+O:9:"testclass":0:{}
+object(__PHP_Incomplete_Class)(1) {
   ["__PHP_Incomplete_Class_Name"]=>
-  string(9) "TestClass"
+  string(9) "testclass"
 }
-O:9:"TestClass":0:{}
-object(__PHP_Incomplete_Class)#1 (1) {
+O:9:"testclass":0:{}
+object(__PHP_Incomplete_Class)(1) {
   ["__PHP_Incomplete_Class_Name"]=>
-  string(9) "TestClass"
+  string(9) "testclass"
 }
index 7f2bd66371128c96d36fba073dc7f115ec9aa170..0a318736c8a635b4154d5b35ab4cdc6da245aa0b 100644 (file)
@@ -3,13 +3,13 @@ Bug #28325 (Problem in serialisation of circular references)
 --FILE--
 <?php
 class a {
-       public $b;
+       var $b;
 }
 class b {
-       public $c;
+       var $c;
 }
 class c {
-       public $d;
+       var $d;
 }
 $a = new a();
 $a->b = new b();
@@ -17,20 +17,20 @@ $a->b->c = new c();
 $a->b->c->d = $a;
 var_dump(unserialize(serialize($a)));
 ?>
---EXPECTF--
-object(a)#%d (1) {
+--EXPECT--
+object(a)(1) {
   ["b"]=>
-  object(b)#%d (1) {
+  object(b)(1) {
     ["c"]=>
-    object(c)#%d (1) {
+    object(c)(1) {
       ["d"]=>
-      object(a)#%d (1) {
+      object(a)(1) {
         ["b"]=>
-        object(b)#%d (1) {
+        object(b)(1) {
           ["c"]=>
-          object(c)#%d (1) {
+          object(c)(1) {
             ["d"]=>
-            *RECURSION*
+            NULL
           }
         }
       }
index c992d9cefb79fd036696d51d97e05f946d664331..ce976c9e342d8da836d6fe6d3d992bb0c85bf7b3 100644 (file)
@@ -18,8 +18,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: var.c
- 1.111 2001/08/06 13:36:08 thies Exp $ */
+/* $Id$ */
 
 
 /* {{{ includes 
@@ -63,6 +62,9 @@ PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC)
 {
        HashTable *myht = NULL;
        zend_object *object = NULL;
+       int (*php_element_dump_func)(zval**, int, va_list, zend_hash_key*);
+
+       php_element_dump_func = php_array_element_dump;
 
        if (level > 1) {
                php_printf("%*c", level - 1, ' ');
@@ -93,17 +95,20 @@ PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC)
                        return;
                }
                php_printf("%sarray(%d) {\n", COMMON, zend_hash_num_elements(myht));
+               php_element_dump_func = php_array_element_dump;
                goto head_done;
        case IS_OBJECT:
                object = Z_OBJ_PP(struc);
                myht = Z_OBJPROP_PP(struc);
-               if (myht->nApplyCount > 1) {
+               if (myht && myht->nApplyCount > 1) {
                        PUTS("*RECURSION*\n");
                        return;
                }
                php_printf("%sobject(%s)(%d) {\n", COMMON, Z_OBJCE_PP(struc)->name, zend_hash_num_elements(myht));
 head_done:
-               zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_array_element_dump, 1, level);
+               if (myht) {
+                       zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_element_dump_func, 1, level);
+               }
                if (level > 1) {
                        php_printf("%*c", level-1, ' ');
                }
@@ -203,7 +208,9 @@ PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC)
                myht = Z_OBJPROP_PP(struc);
                php_printf("%sobject(%s)(%d) refcount(%u){\n", COMMON, Z_OBJCE_PP(struc)->name, zend_hash_num_elements(myht), Z_REFCOUNT_PP(struc));
 head_done:
-               zend_hash_apply_with_arguments(myht, (apply_func_args_t) zval_array_element_dump, 1, level);
+               if (myht) {
+                       zend_hash_apply_with_arguments(myht, (apply_func_args_t) zval_array_element_dump, 1, level);
+               }
                if (level > 1) {
                        php_printf("%*c", level-1, ' ');
                }
@@ -260,13 +267,17 @@ static int php_array_element_export(zval **zv, int num_args, va_list args, zend_
        if (hash_key->nKeyLength==0) { /* numeric key */
                php_printf("%*c%ld => ", level + 1, ' ', hash_key->h);
        } else { /* string key */
-               char *key;
-               int key_len;
-               key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC);
-               php_printf("%*c'", level + 1, ' ');
-               PHPWRITE(key, key_len);
-               php_printf("' => ");
-               efree(key);
+               if (va_arg(args, int) && hash_key->arKey[0] == '\0') {
+                       return 0;
+               } else {
+                       char *key;
+                       int key_len;
+                       key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC);
+                       php_printf("%*c'", level + 1, ' ');
+                       PHPWRITE(key, key_len);
+                       php_printf("' => ");
+                       efree(key);
+               }
        }
        php_var_export(zv, level + 2 TSRMLS_CC);
        PUTS (",\n");
@@ -332,7 +343,9 @@ PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC)
                        php_printf("\n%*c", level - 1, ' ');
                }
                php_printf ("class %s {\n", Z_OBJCE_PP(struc)->name);
-               zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_object_element_export, 1, level);
+               if (myht) {
+                       zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_object_element_export, 1, level);
+               }
                if (level > 1) {
                        php_printf("%*c", level - 1, ' ');
                }
@@ -419,7 +432,7 @@ static inline void php_var_serialize_string(smart_str *buf, char *str, int len)
        smart_str_appendl(buf, "\";", 2);
 }
 
-static inline void php_var_serialize_class_name(smart_str *buf, zval **struc TSRMLS_DC)
+static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval **struc TSRMLS_DC)
 {
        PHP_CLASS_ATTRIBUTES;
 
@@ -430,16 +443,21 @@ static inline void php_var_serialize_class_name(smart_str *buf, zval **struc TSR
        smart_str_appendl(buf, class_name, name_len);
        smart_str_appendl(buf, "\":", 2);
        PHP_CLEANUP_CLASS_ATTRIBUTES();
+       return incomplete_class;
 }
 
 static void php_var_serialize_class(smart_str *buf, zval **struc, zval *retval_ptr, HashTable *var_hash TSRMLS_DC)
 {
        int count;
+       zend_bool  incomplete_class;
 
-       php_var_serialize_class_name(buf, struc TSRMLS_CC);
+       incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC);
        /* count after serializing name, since php_var_serialize_class_name
           changes the count if the variable is incomplete class */
        count = zend_hash_num_elements(HASH_OF(retval_ptr));
+       if (incomplete_class) {
+               --count;
+       }
        smart_str_append_long(buf, count);
        smart_str_appendl(buf, ":{", 2);
 
@@ -463,6 +481,9 @@ static void php_var_serialize_class(smart_str *buf, zval **struc, zval *retval_p
                        if (i == HASH_KEY_NON_EXISTANT)
                                break;
 
+                       if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
+                               continue;
+                       }
                        zend_hash_get_current_data_ex(HASH_OF(retval_ptr), 
                                        (void **) &name, &pos);
 
@@ -475,13 +496,12 @@ static void php_var_serialize_class(smart_str *buf, zval **struc, zval *retval_p
                                smart_str_appendl(buf,"N;", 2);
                                continue;
                        }
-
-                       php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
-
                        if (zend_hash_find(Z_OBJPROP_PP(struc), Z_STRVAL_PP(name), 
                                                Z_STRLEN_PP(name) + 1, (void *) &d) == SUCCESS) {
+                               php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));    
                                php_var_serialize_intern(buf, d, var_hash TSRMLS_CC);   
                        } else {
+                               php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name));    
                                php_var_serialize_intern(buf, &nvalp, var_hash TSRMLS_CC);      
                        }
                }
@@ -496,13 +516,19 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va
        ulong *var_already;
        HashTable *myht;
 
-       if(var_hash 
-                       && php_add_var_hash(var_hash, *struc, (void *) &var_already) == FAILURE 
-                       && (*struc)->is_ref) {
+       if (var_hash 
+           && php_add_var_hash(var_hash, *struc, (void *) &var_already) == FAILURE) {
+               if((*struc)->is_ref) {
                smart_str_appendl(buf, "R:", 2);
                smart_str_append_long(buf, *var_already);
                smart_str_appendc(buf, ';');
                return;
+               } else if(Z_TYPE_PP(struc) == IS_OBJECT) {
+                       smart_str_appendl(buf, "r:", 2);
+                       smart_str_append_long(buf, *var_already);
+                       smart_str_appendc(buf, ';');
+                       return;
+               }
        }
 
        switch (Z_TYPE_PP(struc)) {
@@ -539,6 +565,7 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va
                                zval fname;
                                int res;
 
+                               if(Z_OBJCE_PP(struc) != PHP_IC_ENTRY) {
                                INIT_PZVAL(&fname);
                                ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0);
                                res = call_user_function_ex(CG(function_table), struc, &fname, 
@@ -562,20 +589,27 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va
                                        }
                                        return; 
                                }
+                               }
+                               
                                if (retval_ptr)
                                        zval_ptr_dtor(&retval_ptr);
                                /* fall-through */
                        }
-               case IS_ARRAY:
-                       myht = HASH_OF(*struc);
+               case IS_ARRAY: {
+                       zend_bool incomplete_class = 0;
                        if (Z_TYPE_PP(struc) == IS_ARRAY) {
                                smart_str_appendl(buf, "a:", 2);
+                               myht = HASH_OF(*struc);
                        } else {
-                               php_var_serialize_class_name(buf, struc TSRMLS_CC);
+                               incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC);
+                               myht = Z_OBJPROP_PP(struc);
                        }
                        /* count after serializing name, since php_var_serialize_class_name
                           changes the count if the variable is incomplete class */
-                       i = zend_hash_num_elements(myht);
+                       i = myht ? zend_hash_num_elements(myht) : 0;
+                       if (i > 0 && incomplete_class) {
+                               --i;
+                       }
                        smart_str_append_long(buf, i);
                        smart_str_appendl(buf, ":{", 2);
                        if (i > 0) {
@@ -592,6 +626,10 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va
                                        if (i == HASH_KEY_NON_EXISTANT)
                                                break;
                                        
+                                       if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
+                                               continue;
+                                       }               
+                                       
                                        switch (i) {
                                          case HASH_KEY_IS_LONG:
                                                        php_var_serialize_long(buf, index);
@@ -615,6 +653,7 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va
                        }
                        smart_str_appendc(buf, '}');
                        return;
+               }
                default:
                        smart_str_appendl(buf, "i:0;", 4);
                        return;
@@ -671,7 +710,7 @@ PHP_FUNCTION(unserialize)
        }
 
        if (Z_TYPE_PP(buf) == IS_STRING) {
-               const char *p = Z_STRVAL_PP(buf);
+               const unsigned char *p = (unsigned char*)Z_STRVAL_PP(buf);
 
                if (Z_STRLEN_PP(buf) == 0) {
                        RETURN_FALSE;
@@ -681,7 +720,7 @@ PHP_FUNCTION(unserialize)
                if (!php_var_unserialize(&return_value, &p, p + Z_STRLEN_PP(buf),  &var_hash TSRMLS_CC)) {
                        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
                        zval_dtor(return_value);
-                       php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %d of %d bytes", p - Z_STRVAL_PP(buf), Z_STRLEN_PP(buf));
+                       php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - Z_STRVAL_PP(buf)), Z_STRLEN_PP(buf));
                        RETURN_FALSE;
                }
                PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
index d1a006f2bb554a6fd3df3eed6d3c1da56b01e834..65165b9bd28c29fe02625ecc89818513aa6a66f5 100644 (file)
@@ -1,5 +1,24 @@
-/* Generated by re2c 0.9.2 on Sat Mar 27 01:58:46 2004 */
+/* Generated by re2c 0.9.4 on Fri Sep 24 23:45:23 2004 */
 #line 1 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 4                                                        |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2003 The PHP Group                                |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 2.02 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available at through the world-wide-web at                           |
+   | http://www.php.net/license/2_02.txt.                                 |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Sascha Schumann <sascha@schumann.cx>                        |
+   +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
 
 #include "php.h"
 #include "ext/standard/php_var.h"
@@ -92,12 +111,12 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
 #define YYMARKER marker
 
 
-#line 99 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 118 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 
 
 
 
-static inline int parse_iv2(const char *p, const char **q)
+static inline int parse_iv2(const unsigned char *p, const unsigned char **q)
 {
        char cursor;
        int result = 0;
@@ -112,7 +131,7 @@ static inline int parse_iv2(const char *p, const char **q)
        }
        
        while (1) {
-               cursor = *p;
+               cursor = (char)*p;
                if (cursor >= '0' && cursor <= '9') {
                        result = result * 10 + cursor - '0';
                } else {
@@ -125,12 +144,34 @@ static inline int parse_iv2(const char *p, const char **q)
        return result;
 }
 
-static inline int parse_iv(const char *p)
+static inline int parse_iv(const unsigned char *p)
 {
        return parse_iv2(p, NULL);
 }
 
-#define UNSERIALIZE_PARAMETER zval **rval, const char **p, const char *max, php_unserialize_data_t *var_hash TSRMLS_DC
+/* no need to check for length - re2c already did */
+static inline size_t parse_uiv(const unsigned char *p)
+{
+       unsigned char cursor;
+       size_t result = 0;
+
+       if (*p == '+') {
+               p++;
+       }
+       
+       while (1) {
+               cursor = *p;
+               if (cursor >= '0' && cursor <= '9') {
+                       result = result * 10 + (size_t)(cursor - (unsigned char)'0');
+               } else {
+                       break;
+               }
+               p++;
+       }
+       return result;
+}
+
+#define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC
 #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC
 
 static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int elements)
@@ -146,6 +187,12 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int
                        return 0;
                }
 
+               if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
+                       zval_dtor(key);
+                       FREE_ZVAL(key);
+                       return 0;
+               }
+
                ALLOC_INIT_ZVAL(data);
 
                if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
@@ -163,11 +210,15 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int
                        case IS_STRING:
                                zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL);
                                break;
-
                }
                
                zval_dtor(key);
                FREE_ZVAL(key);
+
+               if (elements && *(*p-1) != ';' &&  *(*p-1) != '}') {
+                       (*p)--;
+                       return 0;
+               }
        }
 
        return 1;
@@ -216,6 +267,20 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, int elements)
 
 }
 
+static char *str_tolower_copy(char *dest, const char *source, unsigned int length)
+{
+       register unsigned char *str = (unsigned char*)source;
+       register unsigned char *result = (unsigned char*)dest;
+       register unsigned char *end = str + length;
+
+       while (str < end) {
+               *result++ = tolower((int)*str++);
+       }
+       *result = *end;
+
+       return dest;
+}
+
 PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
 {
        const unsigned char *cursor, *limit, *marker, *start;
@@ -232,7 +297,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
        
        
 
-#line 7 "re2c-output.c"
+#line 7 "<stdout>"
 {
        YYCTYPE yych;
        unsigned int yyaccept;
@@ -310,7 +375,7 @@ yy0:
                                goto yy15;
                        } else {
                                if(yych <= '}') goto yy13;
-                               if(yych <= '\277')      goto yy15;
+                               if(yych <= 0xBF)        goto yy15;
                                goto yy2;
                        }
                }
@@ -321,14 +386,14 @@ yy2:      YYCURSOR = YYMARKER;
        }
 yy3:   yyaccept = 0;
        yych = *(YYMARKER = ++YYCURSOR);
-       if(yych == ':') goto yy82;
+       if(yych == ':') goto yy80;
        goto yy4;
 yy4:
-#line 429 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 511 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 { return 0; }
-#line 101 "re2c-output.c"
+#line 101 "<stdout>"
 yy5:   yych = *++YYCURSOR;
-       if(yych == ';') goto yy80;
+       if(yych == ';') goto yy78;
        goto yy4;
 yy6:   yyaccept = 0;
        yych = *(YYMARKER = ++YYCURSOR);
@@ -358,16 +423,16 @@ yy12:     yyaccept = 0;
        yych = *(YYMARKER = ++YYCURSOR);
        if(yych == ':') goto yy16;
        goto yy4;
-yy13:  yych = *++YYCURSOR;
+yy13:  ++YYCURSOR;
        goto yy14;
 yy14:
-#line 423 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 505 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
        /* this is the case where we have less data than planned */
-       zend_error(E_NOTICE, "Unexpected end of serialized data");
+       php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
        return 0; /* not sure if it should be 0 or 1 here? */
 }
-#line 142 "re2c-output.c"
+#line 142 "<stdout>"
 yy15:  yych = *++YYCURSOR;
        goto yy4;
 yy16:  yych = *++YYCURSOR;
@@ -387,14 +452,13 @@ yy19:     if(yybm[0+yych] & 128)  goto yy18;
 yy20:  yych = *++YYCURSOR;
        if(yych != '"') goto yy2;
        goto yy21;
-yy21:  yych = *++YYCURSOR;
+yy21:  ++YYCURSOR;
        goto yy22;
 yy22:
-#line 349 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 424 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
-       int len;
+       size_t len, len2, maxlen;
        int elements;
-       int len2;
        char *class_name;
        zend_class_entry *ce;
        int incomplete_class = 0;
@@ -405,20 +469,30 @@ yy22:
        zval *arg_func_name;
        
        INIT_PZVAL(*rval);
-       len2 = len = parse_iv(start + 2);
-       if (len == 0)
+       len2 = len = parse_uiv(start + 2);
+       maxlen = max - YYCURSOR;
+       if (maxlen < len || len == 0) {
+               *p = start + 2;
                return 0;
+       }
+
+       class_name = (char*)YYCURSOR;
 
-       class_name = estrndup(YYCURSOR, len);
        YYCURSOR += len;
 
-       while (len-- > 0) {
-               if (class_name[len] >= 'A' && class_name[len] <= 'Z') {
-                       class_name[len] = class_name[len] - 'A' + 'a';
-               }
+       if (*(YYCURSOR) != '"') {
+               *p = YYCURSOR;
+               return 0;
        }
-
-       if (zend_hash_find(CG(class_table), class_name, len2 + 1, (void **) &ce) != SUCCESS) {
+       if (*(YYCURSOR+1) != ':') {
+               *p = YYCURSOR+1;
+               return 0;
+       }
+       
+       class_name = str_tolower_copy((char *)emalloc(len+1), class_name, len);
+       class_name[len] = '\0';
+       
+       if (zend_hash_find(CG(class_table), class_name, len + 1, (void **) &ce) != SUCCESS) {
                if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
                        incomplete_class = 1;
                        ce = PHP_IC_ENTRY;
@@ -435,7 +509,7 @@ yy22:
                                incomplete_class = 1;
                                ce = PHP_IC_ENTRY;
                        } else {
-                               if (zend_hash_find(CG(class_table), class_name, len2 + 1, (void **) &ce) != SUCCESS) {
+                               if (zend_hash_find(CG(class_table), class_name, len + 1, (void **) &ce) != SUCCESS) {
                                        zend_error(E_WARNING, "'unserialize_callback_func' (%s) hasn't defined the class it was called for", user_func->value.str.val);
                                        incomplete_class = 1;
                                        ce = PHP_IC_ENTRY;
@@ -443,7 +517,6 @@ yy22:
 #ifdef ZEND_ENGINE_2
                                        ce = *(zend_class_entry **)ce; /* Bad hack, TBF! */
 #endif 
-                                       efree(class_name);
                                }
                        }
                }
@@ -451,7 +524,6 @@ yy22:
 #ifdef ZEND_ENGINE_2
                ce = *(zend_class_entry **)ce; /* Bad hack, TBF! */
 #endif 
-               efree(class_name);
        }
 
        *p = YYCURSOR;
@@ -459,12 +531,12 @@ yy22:
 
        if (incomplete_class) {
                php_store_class_name(*rval, class_name, len2 TSRMLS_CC);
-               efree(class_name);
        }
+       efree(class_name);
 
        return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 239 "re2c-output.c"
+#line 247 "<stdout>"
 yy23:  yych = *++YYCURSOR;
        if(yych <= ','){
                if(yych != '+') goto yy2;
@@ -490,10 +562,10 @@ yy26:     if(yych <= '/') goto yy2;
 yy27:  yych = *++YYCURSOR;
        if(yych != '"') goto yy2;
        goto yy28;
-yy28:  yych = *++YYCURSOR;
+yy28:  ++YYCURSOR;
        goto yy29;
 yy29:
-#line 341 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 416 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
 
        INIT_PZVAL(*rval);
@@ -501,7 +573,7 @@ yy29:
        return object_common2(UNSERIALIZE_PASSTHRU,
                        object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
 }
-#line 276 "re2c-output.c"
+#line 285 "<stdout>"
 yy30:  yych = *++YYCURSOR;
        if(yych == '+') goto yy31;
        if(yych <= '/') goto yy2;
@@ -522,10 +594,10 @@ yy33:     if(yych <= '/') goto yy2;
 yy34:  yych = *++YYCURSOR;
        if(yych != '{') goto yy2;
        goto yy35;
-yy35:  yych = *++YYCURSOR;
+yy35:  ++YYCURSOR;
        goto yy36;
 yy36:
-#line 323 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 398 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
        int elements = parse_iv(start + 2);
 
@@ -543,7 +615,7 @@ yy36:
 
        return finish_nested_data(UNSERIALIZE_PASSTHRU);
 }
-#line 318 "re2c-output.c"
+#line 328 "<stdout>"
 yy37:  yych = *++YYCURSOR;
        if(yych == '+') goto yy38;
        if(yych <= '/') goto yy2;
@@ -564,30 +636,38 @@ yy40:     if(yych <= '/') goto yy2;
 yy41:  yych = *++YYCURSOR;
        if(yych != '"') goto yy2;
        goto yy42;
-yy42:  yych = *++YYCURSOR;
+yy42:  ++YYCURSOR;
        goto yy43;
 yy43:
-#line 303 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 370 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
-       int len;
+       size_t len, maxlen;
        char *str;
 
-       len = parse_iv(start + 2);
+       len = parse_uiv(start + 2);
+       maxlen = max - YYCURSOR;
+       if (maxlen < len) {
+               *p = start + 2;
+               return 0;
+       }
+
+       str = (char*)YYCURSOR;
 
-       if (len == 0) {
-               str = empty_string;
-       } else {
-               str = estrndup(YYCURSOR, len);
+       YYCURSOR += len;
+
+       if (*(YYCURSOR) != '"') {
+               *p = YYCURSOR;
+               return 0;
        }
 
-       YYCURSOR += len + 2;
+       YYCURSOR += 2;
        *p = YYCURSOR;
 
        INIT_PZVAL(*rval);
-       ZVAL_STRINGL(*rval, str, len, 0);
+       ZVAL_STRINGL(*rval, str, len, 1);
        return 1;
 }
-#line 362 "re2c-output.c"
+#line 381 "<stdout>"
 yy44:  yych = *++YYCURSOR;
        if(yych <= '/'){
                if(yych <= ','){
@@ -673,17 +753,17 @@ yy53:     if(yych <= ';'){
                        goto yy2;
                }
        }
-yy54:  yych = *++YYCURSOR;
+yy54:  ++YYCURSOR;
        goto yy55;
 yy55:
-#line 296 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 363 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
        ZVAL_DOUBLE(*rval, atof(start + 2));
        return 1;
 }
-#line 458 "re2c-output.c"
+#line 479 "<stdout>"
 yy56:  yych = *++YYCURSOR;
        if(yych <= ','){
                if(yych != '+') goto yy2;
@@ -740,10 +820,10 @@ yy63:     yych = *++YYCURSOR;
 yy64:  yych = *++YYCURSOR;
        if(yych != ';') goto yy2;
        goto yy65;
-yy65:  yych = *++YYCURSOR;
+yy65:  ++YYCURSOR;
        goto yy66;
 yy66:
-#line 279 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 346 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
@@ -760,7 +840,7 @@ yy66:
 #endif
        return 1;
 }
-#line 535 "re2c-output.c"
+#line 558 "<stdout>"
 yy67:  yych = *++YYCURSOR;
        if(yych == 'N') goto yy64;
        goto yy2;
@@ -786,87 +866,72 @@ yy71:     if(yych <= '/') goto yy2;
        if(yych <= '9') goto yy70;
        if(yych != ';') goto yy2;
        goto yy72;
-yy72:  yych = *++YYCURSOR;
+yy72:  ++YYCURSOR;
        goto yy73;
 yy73:
-#line 272 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 339 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
        ZVAL_LONG(*rval, parse_iv(start + 2));
        return 1;
 }
-#line 571 "re2c-output.c"
+#line 595 "<stdout>"
 yy74:  yych = *++YYCURSOR;
-       if(yych <= ','){
-               if(yych != '+') goto yy2;
-               goto yy75;
-       } else {
-               if(yych <= '-') goto yy75;
-               if(yych <= '/') goto yy2;
-               if(yych <= '9') goto yy76;
-               goto yy2;
-       }
-yy75:  yych = *++YYCURSOR;
        if(yych <= '/') goto yy2;
-       if(yych >= ':') goto yy2;
+       if(yych >= '2') goto yy2;
+       goto yy75;
+yy75:  yych = *++YYCURSOR;
+       if(yych != ';') goto yy2;
        goto yy76;
 yy76:  ++YYCURSOR;
-       if(YYLIMIT == YYCURSOR) YYFILL(1);
-       yych = *YYCURSOR;
        goto yy77;
-yy77:  if(yych <= '/') goto yy2;
-       if(yych <= '9') goto yy76;
-       if(yych != ';') goto yy2;
-       goto yy78;
-yy78:  yych = *++YYCURSOR;
-       goto yy79;
-yy79:
-#line 265 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+yy77:
+#line 332 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
        ZVAL_BOOL(*rval, parse_iv(start + 2));
        return 1;
 }
-#line 604 "re2c-output.c"
-yy80:  yych = *++YYCURSOR;
-       goto yy81;
-yy81:
-#line 258 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 613 "<stdout>"
+yy78:  ++YYCURSOR;
+       goto yy79;
+yy79:
+#line 325 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
        *p = YYCURSOR;
        INIT_PZVAL(*rval);
        ZVAL_NULL(*rval);
        return 1;
 }
-#line 615 "re2c-output.c"
-yy82:  yych = *++YYCURSOR;
+#line 624 "<stdout>"
+yy80:  yych = *++YYCURSOR;
        if(yych <= ','){
                if(yych != '+') goto yy2;
-               goto yy83;
+               goto yy81;
        } else {
-               if(yych <= '-') goto yy83;
+               if(yych <= '-') goto yy81;
                if(yych <= '/') goto yy2;
-               if(yych <= '9') goto yy84;
+               if(yych <= '9') goto yy82;
                goto yy2;
        }
-yy83:  yych = *++YYCURSOR;
+yy81:  yych = *++YYCURSOR;
        if(yych <= '/') goto yy2;
        if(yych >= ':') goto yy2;
-       goto yy84;
-yy84:  ++YYCURSOR;
+       goto yy82;
+yy82:  ++YYCURSOR;
        if(YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-       goto yy85;
-yy85:  if(yych <= '/') goto yy2;
-       if(yych <= '9') goto yy84;
+       goto yy83;
+yy83:  if(yych <= '/') goto yy2;
+       if(yych <= '9') goto yy82;
        if(yych != ';') goto yy2;
-       goto yy86;
-yy86:  yych = *++YYCURSOR;
-       goto yy87;
-yy87:
-#line 239 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+       goto yy84;
+yy84:  ++YYCURSOR;
+       goto yy85;
+yy85:
+#line 304 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 {
        int id;
 
@@ -878,16 +943,18 @@ yy87:
                return 0;
        }
 
+       if (*rval != NULL) {
        zval_ptr_dtor(rval);
+       }
        *rval = *rval_ref;
        (*rval)->refcount++;
        (*rval)->is_ref = 1;
        
        return 1;
 }
-#line 660 "re2c-output.c"
+#line 672 "<stdout>"
 }
-#line 431 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
+#line 513 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re"
 
 
        return 0;