]> granicus.if.org Git - php/commitdiff
Fixed one major bug in phpdbg_btree_delete
authorBob Weinand <bobwei9@hotmail.com>
Mon, 17 Mar 2014 10:19:14 +0000 (06:19 -0400)
committerBob Weinand <bobwei9@hotmail.com>
Mon, 17 Mar 2014 10:19:14 +0000 (06:19 -0400)
There is some bug when arrays/property tables are deleted: the children are not notified

(Considering now to overwrite the dtor of the array)

phpdbg_btree.c
phpdbg_watch.c

index f60613548867ab1dce821caf4e10db070f297494..9eba9823de14b3e0a7ffc87ef79877c930bae935 100644 (file)
@@ -83,7 +83,7 @@ phpdbg_btree_result *phpdbg_btree_find_closest(phpdbg_btree *tree, zend_ulong id
                        }
                        /* reset state */
                        branch = tree->branch;
-                       i = sizeof(void *) * 8 - 1;
+                       i = tree->depth - 1;
                        /* follow branch according to bits in idx until the last lower branch before the impossible branch */
                        do {
                                CHOOSE_BRANCH((idx >> i) % 2 == 1 && branch->branches[1]);
@@ -200,14 +200,15 @@ check_branch_existence:
                tree->branch = NULL;
        } else {
                if (last_dual_branch->branches[last_dual_branch_branch] == last_dual_branch + 1) {
+                       phpdbg_btree_branch *original_branch = last_dual_branch->branches[!last_dual_branch_branch];
+
                        memcpy(last_dual_branch + 1, last_dual_branch->branches[!last_dual_branch_branch], i_last_dual_branch * sizeof(phpdbg_btree_branch));
                        efree(last_dual_branch->branches[!last_dual_branch_branch]);
                        last_dual_branch->branches[!last_dual_branch_branch] = last_dual_branch + 1;
 
                        branch = last_dual_branch->branches[!last_dual_branch_branch];
                        for (i = i_last_dual_branch; i--;) {
-                               branch->branches[!!branch->branches[1]] = last_dual_branch + i_last_dual_branch - i + 1;
-                               branch = branch->branches[!!branch->branches[1]];
+                               branch = (branch->branches[branch->branches[1] == ++original_branch] = last_dual_branch + i_last_dual_branch - i + 1);
                        }
                } else {
                        efree(last_dual_branch->branches[last_dual_branch_branch]);
index 1c4f6f895a37b1525cae6456e829384484c982fc..f2f127b61ebba70b7fe501189eb4004f6aedf49a 100644 (file)
@@ -66,11 +66,12 @@ static void phpdbg_change_watchpoint_access(phpdbg_watchpoint_t *watch, int acce
 
        /* pagesize is assumed to be in the range of 2^x */
        m = mprotect(phpdbg_get_page_boundary(watch->addr.ptr), phpdbg_get_total_page_size(watch->addr.ptr, watch->size), access);
-
+/*
        if (m == FAILURE) {
                phpdbg_error("Unable to (un)set watchpoint (mprotect() failed)");
                zend_bailout();
        }
+*/
 }
 
 static inline void phpdbg_activate_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) {
@@ -538,7 +539,7 @@ static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) {
        phpdbg_btree_position pos = phpdbg_btree_find_between(&PHPDBG_G(watchpoint_tree), (zend_ulong)dump->page, (zend_ulong)dump->page + dump->size);
        phpdbg_btree_result *result, *htresult;
        int elementDiff;
-       void **curTest;
+       void *curTest;
 
        dump->reenable_writing = 0;
 
@@ -548,15 +549,24 @@ static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) {
                char reenable = 1;
 
                /* Test if the zval was separated and if necessary move the watchpoint */
-               if (zend_hash_find(watch->parent_container, watch->name_in_parent, watch->name_in_parent_len, (void **) &curTest) == SUCCESS) {
+               if (zend_hash_find(watch->parent_container, watch->name_in_parent, watch->name_in_parent_len + 1, &curTest) == SUCCESS) {
                        if (watch->type == WATCH_ON_HASHTABLE) {
-                               curTest = (void **)&Z_ARRVAL_PP((zval **)curTest);
+                               switch (Z_TYPE_PP((zval **)curTest)) {
+                                       case IS_ARRAY:
+                                               curTest = (void *)Z_ARRVAL_PP((zval **)curTest);
+                                               break;
+                                       case IS_OBJECT:
+                                               curTest = (void *)Z_OBJPROP_PP((zval **)curTest);
+                                               break;
+                               }
+                       } else {
+                               curTest = *(void **)curTest;
                        }
 
-                       if (*curTest != watch->addr.ptr) {
+                       if (curTest != watch->addr.ptr) {
                                phpdbg_deactivate_watchpoint(watch TSRMLS_CC);
                                phpdbg_remove_watchpoint(watch TSRMLS_CC);
-                               watch->addr.ptr = *curTest;
+                               watch->addr.ptr = curTest;
                                phpdbg_store_watchpoint(watch TSRMLS_CC);
                                phpdbg_activate_watchpoint(watch TSRMLS_CC);
 
@@ -588,7 +598,7 @@ static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) {
 
                                                reenable = 0;
 
-                                               if (Z_TYPE_P((zval *)oldPtr) == IS_ARRAY) {
+                                               if (Z_TYPE_P((zval *)oldPtr) == IS_ARRAY || Z_TYPE_P((zval *)oldPtr) == IS_OBJECT) {
                                                        goto remove_ht_watch;
                                                }
 
@@ -599,7 +609,7 @@ static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) {
                                        zend_print_flat_zval_r(watch->addr.zv TSRMLS_CC);
                                        phpdbg_writeln("\nNew refcount: %d; New is_ref: %d", watch->addr.zv->refcount__gc, watch->addr.zv->is_ref__gc);
 
-                                       if (Z_TYPE_P((zval *)oldPtr) != IS_ARRAY || Z_ARRVAL_P(watch->addr.zv) == Z_ARRVAL_P((zval *)oldPtr)) {
+                                       if ((Z_TYPE_P((zval *)oldPtr) != IS_ARRAY || Z_ARRVAL_P(watch->addr.zv) == Z_ARRVAL_P((zval *)oldPtr)) && (Z_TYPE_P((zval *)oldPtr) != IS_OBJECT || Z_OBJ_HANDLE_P(watch->addr.zv) == Z_OBJ_HANDLE_P((zval *)oldPtr))) {
                                                break;
                                        }
 
@@ -693,4 +703,4 @@ void phpdbg_watch_efree(void *ptr) {
        }
 
        PHPDBG_G(original_free_function)(ptr);
-}
\ No newline at end of file
+}