@@ -133,6 +133,16 @@ const phpdbg_command_t phpdbg_watch_commands[] = {
133133#define HT_WATCH_HT (watch ) HT_PTR_HT((watch)->addr.ptr)
134134
135135/* ### PRINTING POINTER DIFFERENCES ### */
136+ static bool phpdbg_check_zval_watch_diff (zval * oldPtr , zval * newPtr ) {
137+ if (Z_TYPE_INFO_P (oldPtr ) != Z_TYPE_INFO_P (newPtr )) {
138+ return true;
139+ }
140+ if (Z_TYPE_P (oldPtr ) < IS_LONG ) {
141+ return false;
142+ }
143+ return memcmp (oldPtr , newPtr , sizeof (zend_value )) != 0 ;
144+ }
145+
136146bool phpdbg_check_watch_diff (phpdbg_watchtype type , void * oldPtr , void * newPtr ) {
137147 switch (type ) {
138148 case WATCH_ON_BUCKET :
@@ -142,7 +152,7 @@ bool phpdbg_check_watch_diff(phpdbg_watchtype type, void *oldPtr, void *newPtr)
142152 /* Fall through to also compare the value from the bucket. */
143153 ZEND_FALLTHROUGH ;
144154 case WATCH_ON_ZVAL :
145- return memcmp ( oldPtr , newPtr , sizeof ( zend_value ) + sizeof ( uint32_t ) /* value + typeinfo */ ) != 0 ;
155+ return phpdbg_check_zval_watch_diff (( zval * ) oldPtr , ( zval * ) newPtr ) ;
146156 case WATCH_ON_HASHTABLE :
147157 return zend_hash_num_elements (HT_PTR_HT (oldPtr )) != zend_hash_num_elements (HT_PTR_HT (newPtr ));
148158 case WATCH_ON_REFCOUNTED :
@@ -568,9 +578,26 @@ phpdbg_watch_element *phpdbg_add_watch_element(phpdbg_watchpoint_t *watch, phpdb
568578 return element ;
569579}
570580
571- phpdbg_watch_element * phpdbg_add_bucket_watch_element (Bucket * bucket , phpdbg_watch_element * element , bool * is_new ) {
581+ static bool phpdbg_zval_is_bucket_of (HashTable * ht , zval * zv ) {
582+ if (!ht || HT_IS_PACKED (ht )) {
583+ return false;
584+ }
585+ if ((uintptr_t ) zv < (uintptr_t ) ht -> arData
586+ || (uintptr_t ) zv >= (uintptr_t ) (ht -> arData + ht -> nNumUsed )) {
587+ return false;
588+ }
589+ ZEND_ASSERT (((uintptr_t ) zv - (uintptr_t ) ht -> arData ) % sizeof (Bucket ) == 0 );
590+ return true;
591+ }
592+
593+ phpdbg_watch_element * phpdbg_add_bucket_watch_element (zval * zv , phpdbg_watch_element * element , bool * is_new ) {
572594 phpdbg_watchpoint_t watch ;
573- phpdbg_set_bucket_watchpoint (bucket , & watch );
595+
596+ if (phpdbg_zval_is_bucket_of (element -> parent_container , zv )) {
597+ phpdbg_set_bucket_watchpoint ((Bucket * ) zv , & watch );
598+ } else {
599+ phpdbg_set_zval_watchpoint (zv , & watch );
600+ }
574601 bool added_new ;
575602 phpdbg_watch_element * added = phpdbg_add_watch_element (& watch , element , & added_new );
576603 if (added_new ) {
@@ -637,7 +664,7 @@ void phpdbg_add_recursive_watch_from_ht(phpdbg_watch_element *element, zend_long
637664 return ;
638665 }
639666 bool added_new ;
640- phpdbg_add_bucket_watch_element (( Bucket * ) zv , child , & added_new );
667+ phpdbg_add_bucket_watch_element (zv , child , & added_new );
641668 if (added_new ) {
642669 zend_hash_add_ptr (& element -> child_container , child -> str , child );
643670 }
@@ -697,7 +724,7 @@ void phpdbg_recurse_watch_element(phpdbg_watch_element *element) {
697724}
698725
699726void phpdbg_watch_parent_ht (phpdbg_watch_element * element ) {
700- if (element -> watch -> type == WATCH_ON_BUCKET ) {
727+ if (element -> watch -> type == WATCH_ON_BUCKET || element -> watch -> type == WATCH_ON_ZVAL ) {
701728 phpdbg_btree_result * res ;
702729 phpdbg_watch_ht_info * hti ;
703730 ZEND_ASSERT (element -> parent_container );
@@ -716,14 +743,17 @@ void phpdbg_watch_parent_ht(phpdbg_watch_element *element) {
716743 hti = (phpdbg_watch_ht_info * ) res -> ptr ;
717744 }
718745
719- zend_hash_add_ptr (& hti -> watches , element -> name_in_parent , element );
746+ if (zend_hash_add_ptr (& hti -> watches , element -> name_in_parent , element )) {
747+ element -> flags |= PHPDBG_WATCH_HT_REGISTERED ;
748+ }
720749 }
721750}
722751
723752void phpdbg_unwatch_parent_ht (phpdbg_watch_element * element ) {
724- if (element -> watch && element -> watch -> type == WATCH_ON_BUCKET ) {
753+ if (element -> flags & PHPDBG_WATCH_HT_REGISTERED ) {
725754 phpdbg_btree_result * res = phpdbg_btree_find (& PHPDBG_G (watch_HashTables ), (zend_ulong ) element -> parent_container );
726755 ZEND_ASSERT (element -> parent_container );
756+ element -> flags &= ~PHPDBG_WATCH_HT_REGISTERED ;
727757 if (res ) {
728758 phpdbg_watch_ht_info * hti = res -> ptr ;
729759
@@ -809,7 +839,7 @@ bool phpdbg_try_re_adding_watch_element(zval *parent, phpdbg_watch_element *elem
809839 return false;
810840 }
811841 element -> parent_container = ht ;
812- element = phpdbg_add_bucket_watch_element (( Bucket * ) zv , element , NULL );
842+ element = phpdbg_add_bucket_watch_element (zv , element , NULL );
813843 } else {
814844 return false;
815845 }
@@ -1320,7 +1350,7 @@ static phpdbg_watch_add_result phpdbg_create_simple_watchpoint(zval *zv, phpdbg_
13201350 phpdbg_watch_element * added ;
13211351 (* element )-> flags = PHPDBG_WATCH_SIMPLE ;
13221352 bool added_new ;
1323- added = phpdbg_add_bucket_watch_element (( Bucket * ) zv , * element , & added_new );
1353+ added = phpdbg_add_bucket_watch_element (zv , * element , & added_new );
13241354 if (!added_new ) {
13251355 * element = added ;
13261356 return PHPDBG_WATCH_ADD_DUPLICATE ;
@@ -1344,7 +1374,7 @@ static phpdbg_watch_add_result phpdbg_create_array_watchpoint(zval *zv, phpdbg_w
13441374 element -> str = str ;
13451375 element -> flags = PHPDBG_WATCH_IMPLICIT ;
13461376 bool added_new ;
1347- added = phpdbg_add_bucket_watch_element (( Bucket * ) orig_zv , element , & added_new );
1377+ added = phpdbg_add_bucket_watch_element (orig_zv , element , & added_new );
13481378 if (!added_new ) {
13491379 * element_ptr = added ;
13501380 return PHPDBG_WATCH_ADD_DUPLICATE ;
@@ -1372,7 +1402,7 @@ static phpdbg_watch_add_result phpdbg_create_recursive_watchpoint(zval *zv, phpd
13721402 (* element )-> flags = PHPDBG_WATCH_RECURSIVE | PHPDBG_WATCH_RECURSIVE_ROOT ;
13731403 (* element )-> child = NULL ;
13741404 bool added_new ;
1375- added = phpdbg_add_bucket_watch_element (( Bucket * ) zv , * element , & added_new );
1405+ added = phpdbg_add_bucket_watch_element (zv , * element , & added_new );
13761406 if (!added_new ) {
13771407 * element = added ;
13781408 return PHPDBG_WATCH_ADD_DUPLICATE ;
@@ -1451,7 +1481,7 @@ static int phpdbg_watchpoint_parse_step(char *name, size_t namelen, char *key, s
14511481 element -> name_in_parent = zend_string_init (key , keylen , 0 );
14521482 element -> parent_container = parent ;
14531483 element -> parent = PHPDBG_G (watch_tmp );
1454- element = phpdbg_add_bucket_watch_element (( Bucket * ) zv , element , NULL );
1484+ element = phpdbg_add_bucket_watch_element (zv , element , NULL );
14551485
14561486 efree (name );
14571487 efree (key );
0 commit comments