From ba873a7f4109aec31870ea49507e544b4fff45db Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 4 Apr 2025 20:48:57 +0100 Subject: [PATCH] Fixed GH-18247: dba_popen() memory leak on invalid path. and a handful more error code paths. --- ext/dba/dba.c | 25 +++++++++++++------------ ext/dba/tests/gh18247.phpt | 12 ++++++++++++ 2 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 ext/dba/tests/gh18247.phpt diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 2205b13dfe050..7982e4255b07c 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -864,9 +864,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) } if (!connection->info->lock.fp) { /* stream operation already wrote an error message */ - efree(resource_key); - zval_ptr_dtor(return_value); - RETURN_FALSE; + goto fail; } if (!error && !php_stream_supports_lock(connection->info->lock.fp)) { error = "Stream does not support locking"; @@ -885,9 +883,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) } if (!connection->info->fp) { /* stream operation already wrote an error message */ - efree(resource_key); - zval_ptr_dtor(return_value); - RETURN_FALSE; + goto fail; } if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) { /* Needed because some systems do not allow to write to the original @@ -895,9 +891,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) */ if (SUCCESS != php_stream_cast(connection->info->fp, PHP_STREAM_AS_FD, (void*)&connection->info->fd, 1)) { php_error_docref(NULL, E_WARNING, "Could not cast stream"); - efree(resource_key); - zval_ptr_dtor(return_value); - RETURN_FALSE; + goto fail; #ifdef F_SETFL } else if (modenr == DBA_CREAT) { int flags = fcntl(connection->info->fd, F_GETFL); @@ -931,9 +925,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) php_error_docref(NULL, E_WARNING, "Driver initialization failed for handler: %s", hptr->name); } } - efree(resource_key); - zval_ptr_dtor(return_value); - RETURN_FALSE; + goto fail; } connection->info->hnd = hptr; @@ -942,6 +934,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) if (zend_register_persistent_resource(resource_key, resource_key_len, connection->info, le_pdb) == NULL) { php_error_docref(NULL, E_WARNING, "Could not register persistent resource"); efree(resource_key); + dba_close_connection(connection); zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -949,6 +942,14 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) zend_hash_add_new(&DBA_G(connections), connection->hash, return_value); efree(resource_key); + return; +fail: + efree(resource_key); + zend_string_release_ex(connection->hash, persistent); + dba_close_info(connection->info); + connection->info = NULL; + zval_ptr_dtor(return_value); + RETURN_FALSE; } /* }}} */ diff --git a/ext/dba/tests/gh18247.phpt b/ext/dba/tests/gh18247.phpt new file mode 100644 index 0000000000000..bb757452321d9 --- /dev/null +++ b/ext/dba/tests/gh18247.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-18247: dba_open() memory leak on invalid path +--EXTENSIONS-- +dba +--FILE-- + +--EXPECTF-- + +Warning: dba_popen(/inexistent): Failed to open stream: No such file or directory in %s on line %d +bool(false)