From: Bob Weinand Date: Tue, 11 Mar 2014 13:11:27 +0000 (-0400) Subject: Added support for recursive watchpoints deletion X-Git-Tag: php-5.6.0beta2~1^2~37^2~31 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7a9e3e422f159175f7a94f43c411ec300009ba23;p=php Added support for recursive watchpoints deletion --- diff --git a/phpdbg_btree.c b/phpdbg_btree.c index f3b86dd91f..f3b6306a2a 100644 --- a/phpdbg_btree.c +++ b/phpdbg_btree.c @@ -28,6 +28,7 @@ void phpdbg_btree_init(phpdbg_btree *tree, zend_ulong depth) { tree->depth = depth; tree->branch = NULL; + tree->count = 0; } phpdbg_btree_result *phpdbg_btree_find(phpdbg_btree *tree, zend_ulong idx) { @@ -154,6 +155,7 @@ int phpdbg_btree_insert_or_update(phpdbg_btree *tree, zend_ulong idx, void *ptr, branch = &(*branch)->branches[(idx >> i) % 2]; *branch = ++memory; } while (i--); + tree->count++; } } else if (!(flags & PHPDBG_BTREE_UPDATE)) { return FAILURE; @@ -186,6 +188,8 @@ check_branch_existence: } } while (i--); + tree->count--; + if (i_last_dual_branch == -1) { efree(tree->branch); tree->branch = NULL; diff --git a/phpdbg_btree.h b/phpdbg_btree.h index 7bb40aefca..5fb217db35 100644 --- a/phpdbg_btree.h +++ b/phpdbg_btree.h @@ -35,6 +35,7 @@ union _phpdbg_btree_branch { }; typedef struct { + zend_ulong count; zend_ulong depth; phpdbg_btree_branch *branch; } phpdbg_btree; diff --git a/phpdbg_watch.c b/phpdbg_watch.c index 85451c88cb..f89b3277ad 100644 --- a/phpdbg_watch.c +++ b/phpdbg_watch.c @@ -112,6 +112,8 @@ void phpdbg_create_ht_watchpoint(HashTable *ht, phpdbg_watchpoint_t *watch) { } static int phpdbg_create_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { + watch->flags |= PHPDBG_WATCH_SIMPLE; + phpdbg_store_watchpoint(watch TSRMLS_CC); zend_hash_add(&PHPDBG_G(watchpoints), watch->str, watch->str_len, &watch, sizeof(phpdbg_watchpoint_t *), NULL); @@ -148,6 +150,7 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ return FAILURE; } + watch->flags |= PHPDBG_WATCH_RECURSIVE; phpdbg_create_watchpoint(watch TSRMLS_CC); switch (Z_TYPE_P(watch->addr.zv)) { @@ -171,12 +174,13 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ zend_hash_move_forward_ex(ht, &position)) { phpdbg_watchpoint_t *new_watch = emalloc(sizeof(phpdbg_watchpoint_t)); + new_watch->flags = PHPDBG_WATCH_RECURSIVE; new_watch->parent = watch; new_watch->parent_container = ht; zend_hash_get_current_key_zval_ex(ht, &key, &position); if (Z_TYPE(key) == IS_STRING) { - new_watch->name_in_parent = Z_STRVAL(key); + new_watch->name_in_parent = zend_strndup(Z_STRVAL(key), Z_STRLEN(key)); new_watch->name_in_parent_len = Z_STRLEN(key); } else { new_watch->name_in_parent = NULL; @@ -185,7 +189,6 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ new_watch->str = NULL; new_watch->str_len = asprintf(&new_watch->str, "%.*s%s%.*s%s", watch->str_len, watch->str, Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"[":"->", new_watch->name_in_parent_len, new_watch->name_in_parent, Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"]":""); - new_watch->flags = PHPDBG_WATCH_RECURSIVE; phpdbg_create_zval_watchpoint(*zv, new_watch); phpdbg_create_recursive_watchpoint(new_watch TSRMLS_CC); @@ -197,10 +200,10 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ new_watch->parent = watch; new_watch->parent_container = watch->parent_container; - new_watch->name_in_parent = watch->name_in_parent; + new_watch->name_in_parent = zend_strndup(watch->name_in_parent, watch->name_in_parent_len); new_watch->name_in_parent_len = watch->name_in_parent_len; - new_watch->str = watch->str; - new_watch->str_len = watch->str_len; + new_watch->str = NULL; + new_watch->str_len = asprintf(&new_watch->str, "%.*s[]", watch->str_len, watch->str); new_watch->flags = PHPDBG_WATCH_RECURSIVE; phpdbg_create_ht_watchpoint(ht, new_watch); @@ -210,10 +213,74 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ return SUCCESS; } -static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - int ret = zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); +static int phpdbg_delete_watchpoint_recursive(phpdbg_watchpoint_t *watch TSRMLS_DC) { + if (watch->type == WATCH_ON_HASHTABLE || (watch->type == WATCH_ON_ZVAL && (Z_TYPE_P(watch->addr.zv) == IS_ARRAY || Z_TYPE_P(watch->addr.zv) == IS_OBJECT))) { + HashTable *ht; + phpdbg_btree_result *result; - efree(watch); + if (watch->type == WATCH_ON_HASHTABLE) { + HashPosition position; + zval **zv; + zval key; + char *str; + int str_len; + phpdbg_watchpoint_t **watchpoint; + + ht = watch->addr.ht; + + for (zend_hash_internal_pointer_reset_ex(ht, &position); + zend_hash_get_current_data_ex(ht, (void **)&zv, &position) == SUCCESS; + zend_hash_move_forward_ex(ht, &position)) { + zend_hash_get_current_key_zval_ex(ht, &key, &position); + str = NULL; + if (Z_TYPE(key) == IS_STRING) { + str_len = asprintf(&str, "%.*s%s%.*s%s", watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"[":"->", Z_STRLEN(key), Z_STRVAL(key), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"]":""); + } else { + str_len = asprintf(&str, "%.*s%s%i%s", watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"[":"->", Z_LVAL(key), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"]":""); + } + + if (zend_hash_find(&PHPDBG_G(watchpoints), str, str_len, (void **) &watchpoint) == SUCCESS) { + phpdbg_delete_watchpoint_recursive(*watchpoint TSRMLS_CC); + } + } + } else { + switch (Z_TYPE_P(watch->addr.zv)) { + case IS_ARRAY: + ht = Z_ARRVAL_P(watch->addr.zv); + break; + case IS_OBJECT: + ht = Z_OBJPROP_P(watch->addr.zv); + break; + } + + if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) ht))) { + phpdbg_delete_watchpoint_recursive((phpdbg_watchpoint_t *) result->ptr TSRMLS_CC); + } + } + } + + return zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); +} + +static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch TSRMLS_DC) { + int ret; + phpdbg_watchpoint_t *watch; + phpdbg_btree_result *result; + + if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)tmp_watch->addr.ptr)) == NULL) { + return FAILURE; + } + + watch = result->ptr; + + if (watch->flags & PHPDBG_WATCH_RECURSIVE) { + ret = phpdbg_delete_watchpoint_recursive(watch TSRMLS_CC); + } else { + ret = zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + } + + free(tmp_watch->str); + efree(tmp_watch); return ret; } @@ -266,12 +333,13 @@ static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *par if (i == len || (i == len - 1 && input[len - 1] == ']')) { zval *key = emalloc(sizeof(zval)); phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); + watch->flags = 0; zend_hash_get_current_key_zval_ex(parent, key, &position); convert_to_string(key); - watch->str = emalloc(i + Z_STRLEN_P(key) + 2); + watch->str = malloc(i + Z_STRLEN_P(key) + 2); watch->str_len = sprintf(watch->str, "%.*s%.*s%s", i, input, Z_STRLEN_P(key), Z_STRVAL_P(key), input[len - 1] == ']'?"]":""); efree(key); - watch->name_in_parent = estrndup(last_index, index_len); + watch->name_in_parent = zend_strndup(last_index, index_len); watch->name_in_parent_len = index_len; watch->parent_container = parent; phpdbg_create_zval_watchpoint(*zv, watch); @@ -296,9 +364,10 @@ static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *par last_index[index_len] = last_chr; if (i == len) { phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); - watch->str = estrndup(input, len); + watch->flags = 0; + watch->str = zend_strndup(input, len); watch->str_len = len; - watch->name_in_parent = estrndup(last_index, index_len); + watch->name_in_parent = zend_strndup(last_index, index_len); watch->name_in_parent_len = index_len; watch->parent_container = parent; phpdbg_create_zval_watchpoint(*zv, watch); @@ -428,8 +497,8 @@ static void phpdbg_watch_dtor(void *pDest) { phpdbg_deactivate_watchpoint(watch TSRMLS_CC); phpdbg_remove_watchpoint(watch TSRMLS_CC); - efree(watch->str); - efree(watch->name_in_parent); + free(watch->str); + free(watch->name_in_parent); efree(watch); } diff --git a/phpdbg_watch.h b/phpdbg_watch.h index 37dcde6147..1aa3ad75b0 100644 --- a/phpdbg_watch.h +++ b/phpdbg_watch.h @@ -52,6 +52,7 @@ typedef enum { } phpdbg_watchtype; +#define PHPDBG_WATCH_SIMPLE 0 #define PHPDBG_WATCH_RECURSIVE 1 typedef struct _phpdbg_watchpoint_t phpdbg_watchpoint_t;