Fix GH-13681: segfault when adding watchpoint fails.

thus when removing its entry, no watch point is set and crash on
pointer access.

close GH-14513
This commit is contained in:
David Carlier 2024-06-08 22:00:19 +01:00
parent 350af549a0
commit 03f0776d08
No known key found for this signature in database
GPG Key ID: D308BD11AB42D054
3 changed files with 51 additions and 6 deletions

3
NEWS
View File

@ -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)

View File

@ -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,
@ -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) {
@ -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);
}
}
}

View File

@ -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>