Skip to content

Commit

Permalink
Fix GH-13681: segfault when adding watchpoint fails.
Browse files Browse the repository at this point in the history
thus when removing its entry, no watch point is set and crash on
pointer access.

close GH-14513
  • Loading branch information
devnexen committed Jun 17, 2024
1 parent 350af54 commit 03f0776
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ PHP NEWS
- PDO ODBC:
. Fixed bug GH-14367 (incompatible SDWORD type with iODBC). (Calvin Buckley)

- PHPDBG:
. Fixed bug GH-13681 (segfault on watchpoint addition failure). (David Carlier)

- Soap:
. Fixed bug #47925 (PHPClient can't decompress response). (nielsdos)
. Fix missing error restore code. (nielsdos)
Expand Down
15 changes: 9 additions & 6 deletions sapi/phpdbg/phpdbg_watch.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ void *phpdbg_watchpoint_userfaultfd_thread(void *phpdbg_globals) {

struct uffd_msg fault_msg = {0};
while (read(globals->watch_userfaultfd, &fault_msg, sizeof(fault_msg)) == sizeof(fault_msg)) {
void *page = phpdbg_get_page_boundary((char *)(uintptr_t) fault_msg.arg.pagefault.address);
void *page = phpdbg_get_page_boundary((char *)(uintptr_t) fault_msg.arg.pagefault.address);
zend_hash_index_add_empty_element(globals->watchlist_mem, (zend_ulong) page);
struct uffdio_writeprotect unprotect = {
.mode = 0,
Expand Down Expand Up @@ -668,7 +668,7 @@ void phpdbg_watch_parent_ht(phpdbg_watch_element *element) {
}

void phpdbg_unwatch_parent_ht(phpdbg_watch_element *element) {
if (element->watch->type == WATCH_ON_BUCKET) {
if (element->watch && element->watch->type == WATCH_ON_BUCKET) {
phpdbg_btree_result *res = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong) element->parent_container);
ZEND_ASSERT(element->parent_container);
if (res) {
Expand Down Expand Up @@ -969,11 +969,14 @@ void phpdbg_remove_watchpoint(phpdbg_watchpoint_t *watch) {
}

void phpdbg_clean_watch_element(phpdbg_watch_element *element) {
HashTable *elements = &element->watch->elements;
phpdbg_unwatch_parent_ht(element);
zend_hash_del(elements, element->str);
if (zend_hash_num_elements(elements) == 0) {
phpdbg_remove_watchpoint(element->watch);

if (element->watch) {
HashTable *elements = &element->watch->elements;
zend_hash_del(elements, element->str);
if (zend_hash_num_elements(elements) == 0) {
phpdbg_remove_watchpoint(element->watch);
}
}
}

Expand Down
39 changes: 39 additions & 0 deletions sapi/phpdbg/tests/gh13681.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--TEST--
phpdbg_watch null pointer access
--CREDITS--
Yuancheng Jiang
--SKIPIF--
<?php
if (getenv('SKIP_ASAN')) {
die("skip intentionally causes segfaults");
}
?>
--FILE--
<?php
echo "*** Testing array_multisort() : Testing with anonymous arguments ***\n";
var_dump(array_multisort(array(1,3,2,4)));
$xconnect=$GLOBALS[array_rand($GLOBALS)];
echo "Done\n";
$a = [];
$a[0] = 1;
$a[0] = 2;
$a = [0 => 3, 1 => 4];
?>
--PHPDBG--
b 6
r
w a $a
c
q
--EXPECTF--
[Successful compilation of %s]
prompt> [Breakpoint #0 added at %s:%d]
prompt> *** Testing array_multisort() : Testing with anonymous arguments ***
bool(true)
Done
[Breakpoint #0 at %s:%d, hits: 1]
>00006: $a = [];
00007: $a[0] = 1;
00008: $a[0] = 2;
prompt> prompt> [Script ended normally]
prompt>

0 comments on commit 03f0776

Please sign in to comment.