]> granicus.if.org Git - php/commitdiff
Fix bug #73331 - do not try to serialize/unserialize objects wddx can not handle
authorStanislav Malyshev <stas@php.net>
Mon, 24 Oct 2016 03:07:47 +0000 (20:07 -0700)
committerStanislav Malyshev <stas@php.net>
Mon, 24 Oct 2016 03:09:23 +0000 (20:09 -0700)
Proper soltion would be to call serialize/unserialize and deal with the result,
but this requires more work that should be done by wddx maintainer (not me).

ext/pdo/pdo_stmt.c
ext/wddx/tests/bug45901.phpt
ext/wddx/tests/bug72790.phpt
ext/wddx/tests/bug73331.phpt [new file with mode: 0644]
ext/wddx/wddx.c

index f5c295c26c377545b1a5c72192bf086bfa636e8a..9f9ada9be3bfc1c088b166da9b69671aedabf5a9 100644 (file)
@@ -2338,6 +2338,7 @@ void pdo_stmt_init(TSRMLS_D)
        pdo_row_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; /* when removing this a lot of handlers need to be redone */
        pdo_row_ce->create_object = pdo_row_new;
        pdo_row_ce->serialize = pdo_row_serialize;
+       pdo_row_ce->unserialize = zend_class_unserialize_deny;
 }
 
 static void free_statement(pdo_stmt_t *stmt TSRMLS_DC)
index 4084ccbf202bfab469044fc30e4eaa3b07cebe90..e76e47eab72538de32a45c31e9d6e1c7e6e86540 100644 (file)
@@ -14,5 +14,7 @@ echo wddx_serialize_value($xml, 'Variables') . "\n";
 echo "DONE";
 ?>
 --EXPECTF--
-<wddxPacket version='1.0'><header><comment>Variables</comment></header><data><struct><var name='php_class_name'><string>SimpleXMLElement</string></var><var name='test'><struct><var name='php_class_name'><string>SimpleXMLElement</string></var></struct></var></struct></data></wddxPacket>
+
+Warning: wddx_serialize_value(): Class SimpleXMLElement can not be serialized in %sbug45901.php on line %d
+<wddxPacket version='1.0'><header><comment>Variables</comment></header><data></data></wddxPacket>
 DONE
\ No newline at end of file
index a60524bdaf19e37f9326b6111092a6423832dbf3..3b08e58cc6809312bc15dd77e0fd8ed83827b04f 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-Bug 72790: wddx_deserialize null dereference with invalid xml
+Bug #72790: wddx_deserialize null dereference with invalid xml
 --SKIPIF--
 <?php
 if (!extension_loaded('wddx')) {
diff --git a/ext/wddx/tests/bug73331.phpt b/ext/wddx/tests/bug73331.phpt
new file mode 100644 (file)
index 0000000..7e4cda1
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Bug #73331 (NULL Pointer Dereference in WDDX Packet Deserialization with PDORow)
+--SKIPIF--
+<?php if (!extension_loaded("wddx") || !extension_loaded("pdo")) print "skip"; ?>
+--FILE--
+<?php
+
+$wddx = "<wddxPacket version='1.0'><header/><data><struct><var name='php_class_name'><string>PDORow</string></var></struct></data></wddxPacket>";
+var_dump(wddx_deserialize($wddx));
+?>
+--EXPECTF--
+
+Warning: wddx_deserialize(): Class pdorow can not be unserialized in %s73331.php on line %d
+NULL
+
index 0e77826ce8476ea0cb0186dd7cec95b0c0129685..59cc8ddda8a955918e260f8249996c5bf244717e 100644 (file)
@@ -471,21 +471,26 @@ static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
        ulong idx;
        char tmp_buf[WDDX_BUF_LEN];
        HashTable *objhash, *sleephash;
+       zend_class_entry *ce;
+       PHP_CLASS_ATTRIBUTES;
        TSRMLS_FETCH();
 
+       PHP_SET_CLASS_ATTRIBUTES(obj);
+       ce = Z_OBJCE_P(obj);
+       if (!ce || ce->serialize || ce->unserialize) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s can not be serialized", class_name);
+               PHP_CLEANUP_CLASS_ATTRIBUTES();
+               return;
+       }
+
        MAKE_STD_ZVAL(fname);
        ZVAL_STRING(fname, "__sleep", 1);
-
        /*
         * We try to call __sleep() method on object. It's supposed to return an
         * array of property names to be serialized.
         */
        if (call_user_function_ex(CG(function_table), &obj, fname, &retval, 0, 0, 1, NULL TSRMLS_CC) == SUCCESS) {
                if (retval && (sleephash = HASH_OF(retval))) {
-                       PHP_CLASS_ATTRIBUTES;
-
-                       PHP_SET_CLASS_ATTRIBUTES(obj);
-
                        php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
                        snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR);
                        php_wddx_add_chunk(packet, tmp_buf);
@@ -494,8 +499,6 @@ static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
                        php_wddx_add_chunk_static(packet, WDDX_STRING_E);
                        php_wddx_add_chunk_static(packet, WDDX_VAR_E);
 
-                       PHP_CLEANUP_CLASS_ATTRIBUTES();
-
                        objhash = HASH_OF(obj);
 
                        for (zend_hash_internal_pointer_reset(sleephash);
@@ -516,10 +519,6 @@ static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
        } else {
                uint key_len;
 
-               PHP_CLASS_ATTRIBUTES;
-
-               PHP_SET_CLASS_ATTRIBUTES(obj);
-
                php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
                snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR);
                php_wddx_add_chunk(packet, tmp_buf);
@@ -528,8 +527,6 @@ static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
                php_wddx_add_chunk_static(packet, WDDX_STRING_E);
                php_wddx_add_chunk_static(packet, WDDX_VAR_E);
 
-               PHP_CLEANUP_CLASS_ATTRIBUTES();
-
                objhash = HASH_OF(obj);
                for (zend_hash_internal_pointer_reset(objhash);
                         zend_hash_get_current_data(objhash, (void**)&ent) == SUCCESS;
@@ -551,6 +548,8 @@ static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
                php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
        }
 
+       PHP_CLEANUP_CLASS_ATTRIBUTES();
+
        zval_dtor(fname);
        FREE_ZVAL(fname);
 
@@ -1012,26 +1011,30 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
                                                        pce = &PHP_IC_ENTRY;
                                                }
 
-                                               /* Initialize target object */
-                                               MAKE_STD_ZVAL(obj);
-                                               object_init_ex(obj, *pce);
-
-                                               /* Merge current hashtable with object's default properties */
-                                               zend_hash_merge(Z_OBJPROP_P(obj),
-                                                                               Z_ARRVAL_P(ent2->data),
-                                                                               (void (*)(void *)) zval_add_ref,
-                                                                               (void *) &tmp, sizeof(zval *), 0);
-
-                                               if (incomplete_class) {
-                                                       php_store_class_name(obj, Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data));
+                                               if (pce != &PHP_IC_ENTRY && ((*pce)->serialize || (*pce)->unserialize)) {
+                                                       ent2->data = NULL;
+                                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s can not be unserialized", Z_STRVAL_P(ent1->data));
+                                               } else {
+                                                       /* Initialize target object */
+                                                       MAKE_STD_ZVAL(obj);
+                                                       object_init_ex(obj, *pce);
+
+                                                       /* Merge current hashtable with object's default properties */
+                                                       zend_hash_merge(Z_OBJPROP_P(obj),
+                                                                                       Z_ARRVAL_P(ent2->data),
+                                                                                       (void (*)(void *)) zval_add_ref,
+                                                                                       (void *) &tmp, sizeof(zval *), 0);
+
+                                                       if (incomplete_class) {
+                                                               php_store_class_name(obj, Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data));
+                                                       }
+
+                                                       /* Clean up old array entry */
+                                                       zval_ptr_dtor(&ent2->data);
+
+                                                       /* Set stack entry to point to the newly created object */
+                                                       ent2->data = obj;
                                                }
-
-                                               /* Clean up old array entry */
-                                               zval_ptr_dtor(&ent2->data);
-
-                                               /* Set stack entry to point to the newly created object */
-                                               ent2->data = obj;
-
                                                /* Clean up class name var entry */
                                                zval_ptr_dtor(&ent1->data);
                                        } else if (Z_TYPE_P(ent2->data) == IS_OBJECT) {