Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions ext/dba/dba.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,14 @@ static void dba_close_info(dba_info *info)
if (info->flags & DBA_PERSISTENT) {
php_stream_pclose(info->fp);
} else {
php_stream_close(info->fp);
php_stream_free(info->fp, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
}
}
if (info->lock.fp) {
if (info->flags & DBA_PERSISTENT) {
php_stream_pclose(info->lock.fp);
} else {
php_stream_close(info->lock.fp);
php_stream_free(info->lock.fp, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
}
}

Expand Down Expand Up @@ -518,6 +518,17 @@ static zend_always_inline zend_string *php_dba_zend_string_dup_safe(zend_string
}
}

/* See mysqlnd_fixup_regular_list */
static void php_dba_fixup_regular_list(php_stream *stream)
{
dtor_func_t origin_dtor = EG(regular_list).pDestructor;
EG(regular_list).pDestructor = NULL;
zend_hash_index_del(&EG(regular_list), stream->res->handle);
EG(regular_list).pDestructor = origin_dtor;
efree(stream->res);
stream->res = NULL;
}

/* {{{ php_dba_open */
static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
{
Expand Down Expand Up @@ -831,6 +842,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
/* do not log errors for .lck file while in read only mode on .lck file */
lock_file_mode = "rb";
connection->info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
if (connection->info->lock.fp && !persistent_flag) {
php_dba_fixup_regular_list(connection->info->lock.fp);
}
if (opened_path) {
zend_string_release_ex(opened_path, 0);
}
Expand All @@ -844,6 +858,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
zend_string *opened_path = NULL;
connection->info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
if (connection->info->lock.fp) {
if (!persistent_flag) {
php_dba_fixup_regular_list(connection->info->lock.fp);
}
if (is_db_lock) {
if (opened_path) {
/* replace the path info with the real path of the opened file */
Expand Down Expand Up @@ -880,6 +897,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
connection->info->fp = connection->info->lock.fp; /* use the same stream for locking and database access */
} else {
connection->info->fp = php_stream_open_wrapper(ZSTR_VAL(connection->info->path), file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
if (connection->info->fp && !persistent_flag) {
php_dba_fixup_regular_list(connection->info->fp);
}
}
if (!connection->info->fp) {
/* stream operation already wrote an error message */
Expand Down
20 changes: 20 additions & 0 deletions ext/dba/tests/gh19706.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
GH-19706 (dba stream resource mismanagement)
--EXTENSIONS--
dba
--FILE--
<?php
// Must be in the global scope such that it's part of the symbol table cleanup
$db = dba_open(__DIR__ . '/gh19706.cdb', 'n', 'cdb_make');
$db2 = $db;
var_dump($db, $db2);
?>
--CLEAN--
<?php
@unlink(__DIR__ . '/gh19706.cdb');
?>
--EXPECT--
object(Dba\Connection)#1 (0) {
}
object(Dba\Connection)#1 (0) {
}