Product: PHP Version: 8.5.0-DEV (CLI) CWE-ID: CWE-476: NULL Pointer Dereference CVSS vector v.4.0: 8.2 (AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N) Description: A NULL pointer dereference occurs when the application dereferences a pointer that it expects to be valid, but is NULL, typically causing a crash or exit. Exploitation conditions: An unauthorized user Mitigation: Explicitly check whether a NULL pointer exists before dereferencing it. Researcher: Aleksey Solovev (Positive Technologies)
Research
The vulnerable source code is the ZSTR_LEN(plc->quoted) macro call in the pdo_parse_params function in php-src/ext/pdo/pdo_sql_parser.re. Inside the ZSTR_LEN(plc->quoted) macro, the len field is accessed.
Figure 1. The ZSTR_LEN macro
However, when using a special character sequence, plc->quoted is equal to 0x0.
Figure 2. The vulnerable source code
The plc->quoted field is generated in this case on line 302 when calling the stmt->dbh->methods->quoter function.
Figure 3. plc->quoted initialization
When calling stmt->dbh->methods->quoter, the quoting function pgsql_handle_quoter for PG will be called. On line 407, it will call the PG library function PQescapeStringConn, which will return an error when processing the special sequence, returning NULL as a result. This result will be assigned to the plc->quoted field.
Figure 4. Returning NULL when error occurs
Vulnerability reproduction
The PHP language was compiled using the following commands.
Listing 1. Compiling PHP
$ git clone https://github.com/php/php-src.git
$ cd php-src
$ ./buildconf
$ ./configure CFLAGS="-fsanitize=address -g" CXXFLAGS="-fsanitize=address -g"
LDFLAGS="-fsanitize=address" --with-pdo-pgsql --enable-debug
$ make -j8
$ ./sapi/cli/php -v
PHP 8.5.0-dev (cli) (built: Sep 22 2025 13:24:35) (NTS DEBUG)
Copyright (c) The PHP Group
Zend Engine v4.5.0-dev, Copyright (c) Zend Technologies
with Zend OPcache v8.5.0-dev, Copyright (c), by Zend Technologies
Next, the following PHP code was placed on the server, causing to Segmentation fault.
Enabling the PDO::ATTR_EMULATE_PREPARES mode is the key element of this code.
The problem is caused by a non-existent sequence of characters in hexadecimal notation, for example \x99.
Listing 2. Source code on the server
true
]);
$sql = "SELECT * FROM users where username = :username";
$stmt = $pdo->prepare($sql);
$p1 = "alice\x99";
$stmt->execute(['username' => $p1]);
foreach ($stmt as $row) {
print_r($row);
}
} catch (PDOException $e) { echo $e->getMessage(); }
?>
Executing the following PHP code results in Segmentation fault, which leads to Denial of Service (DoS).
Figure 5. Demonstration of the vulnerability
Security impact
If there is no extra validaiton for zero byte of the quoted user input, then it could lead to a potential DoS and for ZTS mode stopping all other currently served requests in the process.
Credits
Aleksey Solovev (Positive Technologies)