Skip to content

Fix GH-15210: phpdbg_print_changed_zvals working on a real copy instead. #15229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sapi/phpdbg/phpdbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
HashTable watch_recreation; /* watch elements pending recreation of their respective watchpoints */
HashTable watch_free; /* pointers to watch for being freed */
HashTable *watchlist_mem; /* triggered watchpoints */
HashTable *original_watchlist_mem; /* the original allocation for watchlist_mem, used when watchlist_mem has changed temporarily */
HashTable *watchlist_mem_backup; /* triggered watchpoints backup table while iterating over it */
bool watchpoint_hit; /* a watchpoint was hit */
void (*original_free_function)(void *); /* the original AG(mm_heap)->_free function */
Expand Down
2 changes: 2 additions & 0 deletions sapi/phpdbg/phpdbg_prompt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,8 @@ int phpdbg_interactive(bool allow_async_unsafe, char *input) /* {{{ */
ret = phpdbg_stack_execute(&stack, allow_async_unsafe);
} zend_catch {
phpdbg_stack_free(&stack);
phpdbg_destroy_input(&input);
/* TODO: should use proper unwinding instead of bailing out */
zend_bailout();
} zend_end_try();

Expand Down
9 changes: 6 additions & 3 deletions sapi/phpdbg/phpdbg_watch.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,9 @@ phpdbg_watch_element *phpdbg_add_watch_element(phpdbg_watchpoint_t *watch, phpdb
phpdbg_watch_element *old_element;
watch = res->ptr;
if ((old_element = zend_hash_find_ptr(&watch->elements, element->str))) {
phpdbg_free_watch_element(element);
if (element != old_element) {
phpdbg_free_watch_element(element);
}
return old_element;
}
}
Expand Down Expand Up @@ -1471,6 +1473,7 @@ void phpdbg_setup_watchpoints(void) {

/* put these on a separate page, to avoid conflicts with other memory */
PHPDBG_G(watchlist_mem) = malloc(phpdbg_pagesize > sizeof(HashTable) ? phpdbg_pagesize : sizeof(HashTable));
PHPDBG_G(original_watchlist_mem) = PHPDBG_G(watchlist_mem);
zend_hash_init(PHPDBG_G(watchlist_mem), phpdbg_pagesize / (sizeof(Bucket) + sizeof(uint32_t)), NULL, NULL, 1);
PHPDBG_G(watchlist_mem_backup) = malloc(phpdbg_pagesize > sizeof(HashTable) ? phpdbg_pagesize : sizeof(HashTable));
zend_hash_init(PHPDBG_G(watchlist_mem_backup), phpdbg_pagesize / (sizeof(Bucket) + sizeof(uint32_t)), NULL, NULL, 1);
Expand Down Expand Up @@ -1517,8 +1520,8 @@ void phpdbg_destroy_watchpoints(void) {
zend_hash_destroy(&PHPDBG_G(watch_recreation));
zend_hash_destroy(&PHPDBG_G(watch_free));
zend_hash_destroy(&PHPDBG_G(watch_collisions));
zend_hash_destroy(PHPDBG_G(watchlist_mem));
free(PHPDBG_G(watchlist_mem));
zend_hash_destroy(PHPDBG_G(original_watchlist_mem));
free(PHPDBG_G(original_watchlist_mem));
zend_hash_destroy(PHPDBG_G(watchlist_mem_backup));
free(PHPDBG_G(watchlist_mem_backup));
}
Expand Down
30 changes: 30 additions & 0 deletions sapi/phpdbg/tests/gh15210_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--TEST--
GH-15210 use after free after continue
--PHPDBG--
b 4
r
w $a[0]
c
q
--FILE--
<?php
header_register_callback(function() { echo "sent";});
$a = [0];
$a[0] = 1;
?>
--EXPECTF--
[Successful compilation of %s]
prompt> [Breakpoint #0 added at %s:%d]
prompt> [Breakpoint #0 at %s:%d, hits: 1]
>00004: $a[0] = 1;
00005: ?>
00006:
prompt> [Added watchpoint #0 for $a[0]]
prompt> [Breaking on watchpoint $a[0]]
Old value: [Breaking on watchpoint $a[0]]
Old value: 0
New value: 1
>00002: header_register_callback(function() { echo "sent";});
00003: $a = [0];
00004: $a[0] = 1;
prompt> [$a[0] has been removed, removing watchpoint]
36 changes: 36 additions & 0 deletions sapi/phpdbg/tests/gh15210_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
GH-15210 use after free after continue
--PHPDBG--
b 4
r
w $a[0]
c
c
q
--FILE--
<?php
header_register_callback(function() { echo "sent";});
$a = [0];
$a[0] = 1;
?>
--EXPECTF--
[Successful compilation of %s]
prompt> [Breakpoint #0 added at %s:%d]
prompt> [Breakpoint #0 at %s:%d, hits: 1]
>00004: $a[0] = 1;
00005: ?>
00006:
prompt> [Added watchpoint #0 for $a[0]]
prompt> [Breaking on watchpoint $a[0]]
Old value: [Breaking on watchpoint $a[0]]
Old value: 0
New value: 1
>00002: header_register_callback(function() { echo "sent";});
00003: $a = [0];
00004: $a[0] = 1;
prompt> sent0
New value: 1

[$a[0] has been removed, removing watchpoint]
[Script ended normally]
prompt>
Loading