From: Bob Weinand Date: Mon, 17 Mar 2014 10:19:14 +0000 (-0400) Subject: Fixed one major bug in phpdbg_btree_delete X-Git-Tag: php-5.6.0beta2~1^2~37^2~27 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1401314a1b707f74ffa1e864c1c5c2fcb372e020;p=php Fixed one major bug in phpdbg_btree_delete There is some bug when arrays/property tables are deleted: the children are not notified (Considering now to overwrite the dtor of the array) --- diff --git a/phpdbg_btree.c b/phpdbg_btree.c index f606135488..9eba9823de 100644 --- a/phpdbg_btree.c +++ b/phpdbg_btree.c @@ -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]); diff --git a/phpdbg_watch.c b/phpdbg_watch.c index 1c4f6f895a..f2f127b61e 100644 --- a/phpdbg_watch.c +++ b/phpdbg_watch.c @@ -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 +}