Skip to content

Commit 6e87107

Browse files
committed
ext/mysqlnd: Fix persistent free of non-persistent connect_attr key.
set_client_option_2d() built the temporary key string with the connection's persistent flag but always released it with persistent=1. On a duplicate-key update of the connect_attr hash, zend_hash_update() does not retain the passed key, so the caller-owned non-persistent string was freed via free() instead of efree(), tripping the IS_STR_PERSISTENT assertion in debug builds and mismatching allocators in release. Reachable by retrying mysqli_real_connect() on a handle whose first connect failed, since mysqlnd re-adds _client_name and _server_host on every connect attempt. close phpGH-21931
1 parent 7192664 commit 6e87107

3 files changed

Lines changed: 32 additions & 6 deletions

File tree

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.4.22
44

5+
- MySQLnd:
6+
. Fix persistent free of non-persistent connect_attr key (David Carlier).
7+
58
- Opcache:
69
. Fixed tracing JIT crash when a VM interrupt is handled during an observed
710
user function call. (Levi Morrison)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
mysqli_real_connect() retry on same handle does not corrupt mysqlnd connect_attr
3+
--EXTENSIONS--
4+
mysqli
5+
--SKIPIF--
6+
<?php
7+
require_once 'skipifconnectfailure.inc';
8+
?>
9+
--FILE--
10+
<?php
11+
12+
require 'connect.inc';
13+
14+
$link = mysqli_init();
15+
@mysqli_real_connect($link, $host, $user, 'bogus_password_to_force_failure', $db, $port, $socket);
16+
17+
if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
18+
printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
19+
}
20+
21+
mysqli_close($link);
22+
23+
print "done!";
24+
?>
25+
--EXPECT--
26+
done!

ext/mysqlnd/mysqlnd_connection.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,17 +1572,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * cons
15721572
zval attrz;
15731573
zend_string *str;
15741574

1575+
str = zend_string_init(key, strlen(key), conn->persistent);
1576+
ZVAL_NEW_STR(&attrz, zend_string_init(value, strlen(value), conn->persistent));
15751577
if (conn->persistent) {
1576-
str = zend_string_init(key, strlen(key), 1);
15771578
GC_MAKE_PERSISTENT_LOCAL(str);
1578-
ZVAL_NEW_STR(&attrz, zend_string_init(value, strlen(value), 1));
15791579
GC_MAKE_PERSISTENT_LOCAL(Z_COUNTED(attrz));
1580-
} else {
1581-
str = zend_string_init(key, strlen(key), 0);
1582-
ZVAL_NEW_STR(&attrz, zend_string_init(value, strlen(value), 0));
15831580
}
15841581
zend_hash_update(conn->options->connect_attr, str, &attrz);
1585-
zend_string_release_ex(str, 1);
1582+
zend_string_release_ex(str, conn->persistent);
15861583
}
15871584
break;
15881585
default:

0 commit comments

Comments
 (0)