]> granicus.if.org Git - php/commitdiff
Fix Bug #55801 Behavior of unserialize has changed:
authorMichael Wallner <mike@php.net>
Wed, 19 Oct 2011 10:09:24 +0000 (10:09 +0000)
committerMichael Wallner <mike@php.net>
Wed, 19 Oct 2011 10:09:24 +0000 (10:09 +0000)
 (un)serialize in __wakeup/__sleep now use clean var_hashes

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

index 9e68fd4f7783081d2a8a6d1c61092c33653175fc..e7c66e6cf6d0072e2864aebaeb5dc94c002c77c6 100644 (file)
@@ -204,6 +204,7 @@ typedef struct _php_basic_globals {
 
        /* var.c */
        zend_class_entry *incomplete_class;
+       unsigned serialize_lock; /* whether to use the locally supplied var_hash instead (__sleep/__wakeup) */
        struct {
                void *var_hash;
                unsigned level;
index 70054fce25e6cc067ced051dd376576d9302ca3c..4f0d57fa0d186920eb5849e7dd7fd4ae52923f74 100644 (file)
@@ -12,7 +12,7 @@
    | obtain it through the world-wide-web, please send a note to          |
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
-   | Author: Jani Lehtimäki <jkl@njet.net>                                |
+   | Author: Jani Lehtimäki <jkl@njet.net>                                |
    +----------------------------------------------------------------------+
 */
 
@@ -54,52 +54,62 @@ PHPAPI int php_var_unserialize(zval **rval, const unsigned char **p, const unsig
 
 #define PHP_VAR_SERIALIZE_INIT(var_hash_ptr) \
 do  { \
-       if (BG(serialize).level) { \
-               (var_hash_ptr) = BG(serialize).var_hash; \
-               ++BG(serialize).level; \
-       } else { \
+       /* fprintf(stderr, "SERIALIZE_INIT      == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
+       if (BG(serialize_lock) || !BG(serialize).level) { \
                ALLOC_HASHTABLE(var_hash_ptr); \
                zend_hash_init((var_hash_ptr), 10, NULL, NULL, 0); \
-               BG(serialize).var_hash = (var_hash_ptr); \
-               BG(serialize).level = 1; \
+               if (!BG(serialize_lock)) { \
+                       BG(serialize).var_hash = (var_hash_ptr); \
+                       BG(serialize).level = 1; \
+               } \
+       } else { \
+               (var_hash_ptr) = BG(serialize).var_hash; \
+               ++BG(serialize).level; \
        } \
 } while(0)
 
 #define PHP_VAR_SERIALIZE_DESTROY(var_hash_ptr) \
 do { \
-       if (BG(serialize).level) { \
+       /* fprintf(stderr, "SERIALIZE_DESTROY   == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
+       if (BG(serialize_lock) || !BG(serialize).level) { \
+               zend_hash_destroy((var_hash_ptr)); \
+               FREE_HASHTABLE(var_hash_ptr); \
+       } else { \
                if (!--BG(serialize).level) { \
                        zend_hash_destroy(BG(serialize).var_hash); \
                        FREE_HASHTABLE(BG(serialize).var_hash); \
                        BG(serialize).var_hash = NULL; \
                } \
-       } else { \
-               zend_hash_destroy((var_hash_ptr)); \
        } \
 } while (0)
 
 #define PHP_VAR_UNSERIALIZE_INIT(var_hash_ptr) \
 do { \
-       if (BG(unserialize).level) { \
+       /* fprintf(stderr, "UNSERIALIZE_INIT    == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */ \
+       if (BG(serialize_lock) || !BG(unserialize).level) { \
+               (var_hash_ptr) = ecalloc(1, sizeof(struct php_unserialize_data)); \
+               if (!BG(serialize_lock)) { \
+                       BG(unserialize).var_hash = (var_hash_ptr); \
+                       BG(unserialize).level = 1; \
+               } \
+       } else { \
                (var_hash_ptr) = BG(unserialize).var_hash; \
                ++BG(unserialize).level; \
-       } else { \
-               (var_hash_ptr) = ecalloc(1, sizeof(struct php_unserialize_data)); \
-               BG(unserialize).var_hash = (var_hash_ptr); \
-               BG(unserialize).level = 1; \
        } \
 } while (0)
 
 #define PHP_VAR_UNSERIALIZE_DESTROY(var_hash_ptr) \
 do { \
-       if (BG(unserialize).level) { \
+       /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */ \
+       if (BG(serialize_lock) || !BG(unserialize).level) { \
+               var_destroy(&(var_hash_ptr)); \
+               efree(var_hash_ptr); \
+       } else { \
                if (!--BG(unserialize).level) { \
                        var_destroy(&(var_hash_ptr)); \
                        efree((var_hash_ptr)); \
                        BG(unserialize).var_hash = NULL; \
                } \
-       } else { \
-               var_destroy(&(var_hash_ptr)); \
        } \
 } while (0)
 
index a70438bc7fa575c4afc696bc130e8481d14d044d..104b4a4a60c98d3f01f618eb45aae36b4f6da142 100644 (file)
@@ -12,7 +12,7 @@
    | obtain it through the world-wide-web, please send a note to          |
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
-   | Authors: Jani Lehtimäki <jkl@njet.net>                               |
+   | Authors: Jani Lehtimäki <jkl@njet.net>                               |
    |          Thies C. Arntzen <thies@thieso.net>                         |
    |          Sascha Schumann <sascha@schumann.cx>                        |
    +----------------------------------------------------------------------+
@@ -788,7 +788,9 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
                                if (ce && ce != PHP_IC_ENTRY && zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) {
                                        INIT_PZVAL(&fname);
                                        ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0);
+                                       BG(serialize_lock)++;
                                        res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
+                                       BG(serialize_lock)--;
 
                                        if (res == SUCCESS && !EG(exception)) {
                                                if (retval_ptr) {
index ae2c606d22fea07163b3da73e05e9a4235473395..278186f4c7a1a162200253bf5ae6c1b59b1e29cd 100644 (file)
@@ -392,7 +392,9 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
                zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) {
                INIT_PZVAL(&fname);
                ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0);
+               BG(serialize_lock)++;
                call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
+               BG(serialize_lock)--;
        }
 
        if (retval_ptr)