Skip to content

Commit 366a5a2

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-19706: dba stream resource mismanagement
2 parents 9d8f2a4 + f744c82 commit 366a5a2

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

ext/dba/dba.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,14 @@ static void dba_close_info(dba_info *info)
256256
if (info->flags & DBA_PERSISTENT) {
257257
php_stream_pclose(info->fp);
258258
} else {
259-
php_stream_close(info->fp);
259+
php_stream_free(info->fp, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
260260
}
261261
}
262262
if (info->lock.fp) {
263263
if (info->flags & DBA_PERSISTENT) {
264264
php_stream_pclose(info->lock.fp);
265265
} else {
266-
php_stream_close(info->lock.fp);
266+
php_stream_free(info->lock.fp, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
267267
}
268268
}
269269

@@ -516,6 +516,17 @@ static zend_always_inline zend_string *php_dba_zend_string_dup_safe(zend_string
516516
}
517517
}
518518

519+
/* See mysqlnd_fixup_regular_list */
520+
static void php_dba_fixup_regular_list(php_stream *stream)
521+
{
522+
dtor_func_t origin_dtor = EG(regular_list).pDestructor;
523+
EG(regular_list).pDestructor = NULL;
524+
zend_hash_index_del(&EG(regular_list), stream->res->handle);
525+
EG(regular_list).pDestructor = origin_dtor;
526+
efree(stream->res);
527+
stream->res = NULL;
528+
}
529+
519530
/* {{{ php_dba_open */
520531
static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
521532
{
@@ -827,6 +838,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
827838
/* do not log errors for .lck file while in read only mode on .lck file */
828839
lock_file_mode = "rb";
829840
connection->info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, NULL);
841+
if (connection->info->lock.fp && !persistent_flag) {
842+
php_dba_fixup_regular_list(connection->info->lock.fp);
843+
}
830844
}
831845
if (!connection->info->lock.fp) {
832846
/* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
@@ -837,6 +851,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
837851
zend_string *opened_path = NULL;
838852
connection->info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
839853
if (connection->info->lock.fp) {
854+
if (!persistent_flag) {
855+
php_dba_fixup_regular_list(connection->info->lock.fp);
856+
}
840857
if (is_db_lock) {
841858
if (opened_path) {
842859
/* replace the path info with the real path of the opened file */
@@ -873,6 +890,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
873890
connection->info->fp = connection->info->lock.fp; /* use the same stream for locking and database access */
874891
} else {
875892
connection->info->fp = php_stream_open_wrapper(ZSTR_VAL(connection->info->path), file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
893+
if (connection->info->fp && !persistent_flag) {
894+
php_dba_fixup_regular_list(connection->info->fp);
895+
}
876896
}
877897
if (!connection->info->fp) {
878898
/* stream operation already wrote an error message */

ext/dba/tests/gh19706.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-19706 (dba stream resource mismanagement)
3+
--EXTENSIONS--
4+
dba
5+
--FILE--
6+
<?php
7+
// Must be in the global scope such that it's part of the symbol table cleanup
8+
$db = dba_open(__DIR__ . '/gh19706.cdb', 'n', 'cdb_make');
9+
$db2 = $db;
10+
var_dump($db, $db2);
11+
?>
12+
--CLEAN--
13+
<?php
14+
@unlink(__DIR__ . '/gh19706.cdb');
15+
?>
16+
--EXPECT--
17+
object(Dba\Connection)#1 (0) {
18+
}
19+
object(Dba\Connection)#1 (0) {
20+
}

0 commit comments

Comments
 (0)