Commit b91ea8889cb for php

commit b91ea8889cb4e802a0764ecf7168118fcc765d40
Author: dev-null-undefined <martinkos007@gmail.com>
Date:   Wed Oct 21 20:29:06 2026 +0200

    Fix GH-24490: pdo_pgsql prepare() hangs on a query containing a NUL byte

    No rule in the scanner matches a NUL byte, so what re2c does with one
    is undefined. Before 5ccc56b1e4 it happened to skip one character. Now
    it returns a zero-length text token and pdo_parse_params() loops
    forever, or reads an uninitialized YYMARKER if the NUL is the first
    byte. Add a default rule so a NUL is skipped as one character of text
    again.

    Close GH-24496

diff --git a/NEWS b/NEWS
index 5155d8ede34..6bb8496271f 100644
--- a/NEWS
+++ b/NEWS
@@ -92,6 +92,8 @@ PHP                                                                        NEWS
   . Improved performance of the SQL parser that handles placeholders.
     (brainexe)
   . Improved performance of fetching integer columns. (brainexe)
+  . Fixed bug GH-24490 (pdo_pgsql prepare() hangs on a query containing a NUL
+    byte). (dev-null-undefined)

 - PGSQL:
   . Fixed pg_lo_write() rejecting data containing null bytes. (Ilia Alshanetsky)
diff --git a/ext/pdo_pgsql/pgsql_sql_parser.re b/ext/pdo_pgsql/pgsql_sql_parser.re
index ce89c32f535..5ecc6b1c01d 100644
--- a/ext/pdo_pgsql/pgsql_sql_parser.re
+++ b/ext/pdo_pgsql/pgsql_sql_parser.re
@@ -48,5 +48,6 @@ int pdo_pgsql_scanner(pdo_scanner_t *s)
 		COMMENTS								{ RET(PDO_PARSER_TEXT); }
 		/* Plain text may contain e/E, as long as it doesn't end with one, which could start an E'...' string */
 		([eE]* TEXTCHR)+						{ RET(PDO_PARSER_TEXT); }
+		*										{ SKIP_ONE(PDO_PARSER_TEXT); }
 	*/
 }
diff --git a/ext/pdo_pgsql/tests/gh24490.phpt b/ext/pdo_pgsql/tests/gh24490.phpt
new file mode 100644
index 00000000000..2cde8518ce2
--- /dev/null
+++ b/ext/pdo_pgsql/tests/gh24490.phpt
@@ -0,0 +1,32 @@
+--TEST--
+GH-24490 (pdo_pgsql: prepare() hangs on a query containing a NUL byte)
+--EXTENSIONS--
+pdo_pgsql
+--SKIPIF--
+<?php
+require __DIR__ . '/config.inc';
+require dirname(__DIR__, 2) . '/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(__DIR__ . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+foreach ([true, false] as $emulate) {
+    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, $emulate);
+    $db->prepare("SELECT 'abc\0def'");
+    $db->prepare("\0SELECT 1");
+    try {
+        $db->prepare("SELECT '\0', ?, :p");
+    } catch (\Throwable $e) {
+        echo $e::class, ": ", $e->getMessage(), "\n";
+    }
+}
+echo "Done\n";
+?>
+--EXPECT--
+PDOException: SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters
+PDOException: SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters
+Done