From c03196a5be14cd4f1a9cf42d77791d892317a60d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 29 Jun 2024 11:53:34 +0100 Subject: [PATCH] Fix GH-14712: segfault on invalid object. If the extension does not allow to get a property pointer (like PDORow object), we fallback to the read property cb anyway. --- NEWS | 4 ++++ Zend/zend_execute.c | 3 +++ ext/pdo/pdo_stmt.c | 12 +++++++++++- ext/pdo_sqlite/tests/gh14712.phpt | 18 ++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_sqlite/tests/gh14712.phpt diff --git a/NEWS b/NEWS index 74b925bf113..1ae1996bb4a 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,10 @@ PHP NEWS - LibXML: . Fixed bug GH-14563 (Build failure with libxml2 v2.13.0). (nielsdos) +- PDO: + . Fixed bug GH-14712 (Crash with PDORow access to null property). + (David Carlier) + - Phar: . Fixed bug GH-14603 (null string from zip entry). (David Carlier) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5a060540db0..3de48fb1358 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3127,6 +3127,9 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } } + /* Pointer on property callback is required */ + ZEND_ASSERT(zobj->handlers->get_property_ptr_ptr != NULL); + if (prop_op_type == IS_CONST) { name = Z_STR_P(prop_ptr); } else { diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index e11d0f4288c..239b8d6a99b 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2453,6 +2453,16 @@ static zend_function *row_get_ctor(zend_object *object) return NULL; } +static zval *pdo_row_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot) +{ + ZEND_IGNORE_VALUE(object); + ZEND_IGNORE_VALUE(name); + ZEND_IGNORE_VALUE(type); + ZEND_IGNORE_VALUE(cache_slot); + + return NULL; +} + void pdo_row_free_storage(zend_object *std) { pdo_row_t *row = (pdo_row_t *)std; @@ -2492,7 +2502,7 @@ void pdo_stmt_init(void) memcpy(&pdo_row_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); pdo_row_object_handlers.free_obj = pdo_row_free_storage; pdo_row_object_handlers.clone_obj = NULL; - pdo_row_object_handlers.get_property_ptr_ptr = NULL; + pdo_row_object_handlers.get_property_ptr_ptr = pdo_row_get_property_ptr_ptr; pdo_row_object_handlers.read_property = row_prop_read; pdo_row_object_handlers.write_property = row_prop_write; pdo_row_object_handlers.has_property = row_prop_exists; diff --git a/ext/pdo_sqlite/tests/gh14712.phpt b/ext/pdo_sqlite/tests/gh14712.phpt new file mode 100644 index 00000000000..d565abacdcd --- /dev/null +++ b/ext/pdo_sqlite/tests/gh14712.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-14712: segfault on PDORow +--EXTENSIONS-- +pdo_sqlite +--CREDITS-- +YuanchengJiang +--FILE-- +query("select 1 as queryStringxx")->fetch(PDO::FETCH_LAZY)->documentElement->firstChild->nextElementSibling->textContent = "é"; +} catch (Error $e) { + echo $e->getMessage(); +} +?> +--EXPECT-- +Attempt to modify property "firstChild" on null