[php-src] Issue #24293: mysqlnd: segfault on connect with an empty password to a MariaDB PAM account

From: Date: Tue, 13 Oct 2026 12:38:17 +0000
Subject: [php-src] Issue #24293: mysqlnd: segfault on connect with an empty password to a MariaDB PAM account
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-252984@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/24293 Author: clamy54 ### Description ### Description Connecting with mysqli to a MariaDB account that authenticates through PAM with pam_use_cleartext_plugin=ON crashes the PHP process (SIGSEGV) when the password is empty. The server sends an auth switch request to mysql_clear_password; with an empty password mysqlnd dereferences a NULL buffer instead of sending a single NUL byte. With a non-empty password the same connection works. It showed up with Adminer 6, which reconnects with an empty password right after login. Every MySQL login ended with the php-fpm worker exiting on signal 11 and nginx answering 502. Reproducer: ```php <?php mysqli_report(MYSQLI_REPORT_OFF); $m = mysqli_init(); $r = @$m->real_connect('db', 'pamuser', '', null, 3306); echo $r ? "connected\n" : "error: {$m->connect_error}\n"; ``` Server side (MariaDB official image, tested with pam_permit): ``` # /etc/mysql/conf.d/pam.cnf [mariadbd] plugin-load-add = auth_pam.so pam_use_cleartext_plugin = ON # /etc/pam.d/mariadb auth required pam_permit.so account required pam_permit.so CREATE USER 'pamuser'@'%' IDENTIFIED VIA pam USING 'mariadb'; ``` Resulted in this output: ``` (no output, exit code 139) Program received signal SIGSEGV, Segmentation fault. #0 0x00007ffff746185a in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #1-#7 ?? () in the php binary (no symbols) #8 mysqlnd_connection_connect () #9 mysqli_common_connect () from .../mysqli.so ``` But I expected this output instead: ``` error: Access denied for user 'pamuser'@'...' (using password: NO) ``` ### Code mysql_clear_password goes through mysqlnd_pam_auth_get_auth_data(): https://github.com/php/php-src/blob/8db886e419a6aba1903ec97754b0548051b55f9c/ext/mysqlnd/mysqlnd_auth.c#L620-L627 ```c if (passwd && passwd_len) { ret = (zend_uchar*) zend_strndup(passwd, passwd_len); } *auth_data_len = passwd_len + 1; ``` Empty password: ret stays NULL, auth_data_len is 1. On the write side, php_mysqlnd_change_auth_response_write() copies auth_data_len bytes from auth_data: https://github.com/php/php-src/blob/8db886e419a6aba1903ec97754b0548051b55f9c/ext/mysqlnd/mysqlnd_wireprotocol.c#L867-L868 For comparison, the sha256 clear text path (L903-L906, changed in GH-11440) allocates the buffer whatever the password length. ### PHP Version ```plain PHP 8.3.35, 8.4.26 and 8.5.11 (official docker images php:8.x-cli and php:8.3-fpm-bookworm) MariaDB 10.11.19 and 11.4.13 ``` ### Operating System Debian (official PHP docker images)

« previous php.bugs (#252984) next »