Summary
With PDO::ATTR_POOL_ENABLED, Pdo\Mysql::getWarningCount() segfaults unconditionally. One line of userland PHP is enough.
In pool mode the userland PDO object's pdo_dbh_t is a template whose driver_data is always NULL — real connections live in pool slots. getWarningCount() reads driver_data off Z_PDO_DBH_P(ZEND_THIS) (always the template) and dereferences it.
ext/pdo_mysql/pdo_mysql.c:96-97:
H = dbh->driver_data;
RETURN_LONG(mysql_warning_count(H->server)); /* H == NULL in pool mode */
Reproducer
<?php
$pdo = new Pdo\Mysql(
'mysql:host=localhost;unix_socket=/var/run/mysqld/mysqld.sock;dbname=test',
'test', 'test',
[PDO::ATTR_POOL_ENABLED => true, PDO::ATTR_POOL_MIN => 1, PDO::ATTR_POOL_MAX => 4]
);
echo "constructed pooled Pdo\\Mysql\n";
echo "getWarningCount() = ", $pdo->getWarningCount(), "\n";
constructed pooled Pdo\Mysql
getWarningCount() = Segmentation fault (core dumped) # exit 139
Crashes even when a slot connection is live (i.e. right after a successful query), because the template is what gets dereferenced, not the slot.
Suggested fix
Route through pdo_pool_peek_conn(dbh) and return 0 when no slot connection is bound to the current context — same shape as the existing lastInsertId / errorInfo handling.
Related
ext/pdo_mysql/pdo_mysql.c:74 pdo_mysql_convert_zv_to_mysqlnd (the mysqlnd reverse-API entry point) reads driver_data the same way. Not executed, so unconfirmed, but it looks like the same defect.
Environment
PHP 8.6.0-dev (cli) (ZTS DEBUG TrueAsync ABI v0.24.0)
true_async 0.7.10
pdo_mysql 8.6.0-dev
OS Linux 6.6.114.1-microsoft-standard-WSL2
Found while auditing the pool code path for #200; pre-existing, independent of that fix.
Summary
With
PDO::ATTR_POOL_ENABLED,Pdo\Mysql::getWarningCount()segfaults unconditionally. One line of userland PHP is enough.In pool mode the userland PDO object's
pdo_dbh_tis a template whosedriver_datais alwaysNULL— real connections live in pool slots.getWarningCount()readsdriver_dataoffZ_PDO_DBH_P(ZEND_THIS)(always the template) and dereferences it.ext/pdo_mysql/pdo_mysql.c:96-97:Reproducer
Crashes even when a slot connection is live (i.e. right after a successful query), because the template is what gets dereferenced, not the slot.
Suggested fix
Route through
pdo_pool_peek_conn(dbh)and return0when no slot connection is bound to the current context — same shape as the existinglastInsertId/errorInfohandling.Related
ext/pdo_mysql/pdo_mysql.c:74pdo_mysql_convert_zv_to_mysqlnd(the mysqlnd reverse-API entry point) readsdriver_datathe same way. Not executed, so unconfirmed, but it looks like the same defect.Environment
Found while auditing the pool code path for #200; pre-existing, independent of that fix.