From d3b0efe9d7b2943797e19fc10e395755e8c9438c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 18 Oct 2024 21:00:29 +0200 Subject: [PATCH] Fix GH-16390: dba_open() can segfault for "pathless" streams `dba_open()` accepts arbitrary stream wrapper paths, but unless no locking (`-`) is specified, we try to determine the underlying file path. If that fails, we need to error out. Closes GH-16498. --- NEWS | 3 +++ ext/dba/dba.c | 17 ++++++++++++----- ext/dba/tests/gh16390.phpt | 11 +++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 ext/dba/tests/gh16390.phpt diff --git a/NEWS b/NEWS index b96cdd8223625..b28d0dafb8202 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,9 @@ PHP NEWS (cmb) . Fixed bug GH-16037 (Assertion failure in ext/date/php_date.c). (Derick) +- DBA: + . Fixed bug GH-16390 (dba_open() can segfault for "pathless" streams). (cmb) + - DOM: . Fixed bug GH-16316 (DOMXPath breaks when not initialized properly). (nielsdos) diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 7e0f56b443e09..e25a801323349 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -772,11 +772,18 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path); if (info->lock.fp) { if (is_db_lock) { - /* replace the path info with the real path of the opened file */ - pefree(info->path, persistent); - info->path = pestrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path), persistent); + if (opened_path) { + /* replace the path info with the real path of the opened file */ + pefree(info->path, persistent); + info->path = pestrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path), persistent); + } else { + error = "Unable to determine path for locking"; + } } + } + if (opened_path) { zend_string_release_ex(opened_path, 0); + opened_path = NULL; } } if (!is_db_lock) { @@ -788,10 +795,10 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) FREE_PERSISTENT_RESOURCE_KEY(); RETURN_FALSE; } - if (!php_stream_supports_lock(info->lock.fp)) { + if (!error && !php_stream_supports_lock(info->lock.fp)) { error = "Stream does not support locking"; } - if (php_stream_lock(info->lock.fp, lock_mode)) { + if (!error && php_stream_lock(info->lock.fp, lock_mode)) { error = "Unable to establish lock"; /* force failure exit */ } } diff --git a/ext/dba/tests/gh16390.phpt b/ext/dba/tests/gh16390.phpt new file mode 100644 index 0000000000000..a5e4d9810964c --- /dev/null +++ b/ext/dba/tests/gh16390.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-16390 (dba_open() can segfault for "pathless" streams) +--EXTENSIONS-- +dba +--FILE-- + +--EXPECTF-- +Warning: dba_open(): Driver initialization failed for handler: inifile: Unable to determine path for locking in %s on line %d