Commit 5577b0b5400 for php

commit 5577b0b54006c02cfcbfa4f1e29a57eeb95922e2
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Wed Oct 28 13:06:39 2026 -0400

    ext/pdo_firebird: Fix getColumnMeta() bounds check

    The driver hook runs before PDO checks the upper column bound. Return an
    empty array for an invalid index without reading sqlvar, allowing PDO to
    report SQLSTATE 07009 as before. Returning failure without setting a driver
    error would instead return false.

    Fixes GH-25006
    Closes GH-25016

diff --git a/NEWS b/NEWS
index edd2429a340..718e381b746 100644
--- a/NEWS
+++ b/NEWS
@@ -196,6 +196,10 @@ PHP                                                                        NEWS
   . Fixed a duplicate warning when ATTR_STATEMENT_CLASS is rejected on a
     persistent connection. (Ilia Alshanetsky)

+- PDO_Firebird:
+  . Fixed bug GH-25006 (getColumnMeta() reads out of bounds for an
+    out-of-range column index). (Ilia Alshanetsky)
+
 - Phar:
   . Fixed bug GH-24740 (Oversized tar metadata exhausts the memory limit).
     (Lazizbek Ergashev)
diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
index b8802751bf9..c166833c000 100644
--- a/ext/pdo_firebird/firebird_statement.c
+++ b/ext/pdo_firebird/firebird_statement.c
@@ -342,9 +342,15 @@ static int pdo_firebird_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
 static int pdo_firebird_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
 {
 	pdo_firebird_stmt *S = (pdo_firebird_stmt *) stmt->driver_data;
-	XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
-
+	XSQLVAR *var;
 	enum pdo_param_type param_type;
+
+	if (colno >= stmt->column_count) {
+		ZVAL_EMPTY_ARRAY(return_value);
+		return 1;
+	}
+
+	var = &S->out_sqlda.sqlvar[colno];
 	if (var->sqlscale < 0) {
 		param_type = PDO_PARAM_STR;
 	} else {
diff --git a/ext/pdo_firebird/tests/gh25006.phpt b/ext/pdo_firebird/tests/gh25006.phpt
new file mode 100644
index 00000000000..d0e9918322a
--- /dev/null
+++ b/ext/pdo_firebird/tests/gh25006.phpt
@@ -0,0 +1,73 @@
+--TEST--
+GH-25006 (PDO_Firebird::getColumnMeta() reads out of bounds for an out-of-range column index)
+--EXTENSIONS--
+pdo_firebird
+--SKIPIF--
+<?php
+require 'skipif.inc';
+?>
+--XLEAK--
+A bug in firebird causes a memory leak when calling `isc_attach_database()`.
+See https://github.com/FirebirdSQL/firebird/issues/7849
+--FILE--
+<?php
+require 'testdb.inc';
+
+$dbh = getDbConnection();
+$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+$stmt = $dbh->prepare('SELECT 1 AS one, 2 AS two FROM RDB$DATABASE');
+
+echo "before execute: ";
+try {
+    var_dump($stmt->getColumnMeta(2));
+} catch (Throwable $e) {
+    echo $e::class, ': ', $e->getMessage(), "\n";
+}
+
+$stmt->execute();
+
+echo "column 0: ";
+$meta = $stmt->getColumnMeta(0);
+echo $meta['name'], ' ', $meta['pdo_type'], "\n";
+
+echo "column 1: ";
+$meta = $stmt->getColumnMeta(1);
+echo $meta['name'], ' ', $meta['pdo_type'], "\n";
+
+foreach ([2, 1000000] as $col) {
+    echo "column $col: ";
+    try {
+        var_dump($stmt->getColumnMeta($col));
+    } catch (Throwable $e) {
+        echo $e::class, ': ', $e->getMessage(), "\n";
+    }
+}
+
+echo "no output columns: ";
+$empty = $dbh->prepare('EXECUTE BLOCK AS BEGIN END');
+echo $empty->columnCount(), ' ';
+try {
+    var_dump($empty->getColumnMeta(0));
+} catch (Throwable $e) {
+    echo $e::class, ': ', $e->getMessage(), "\n";
+}
+
+echo "negative: ";
+try {
+    var_dump($stmt->getColumnMeta(-1));
+} catch (Throwable $e) {
+    echo $e::class, ': ', $e->getMessage(), "\n";
+}
+
+echo "done\n";
+?>
+--EXPECT--
+before execute: PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index
+column 0: ONE 1
+column 1: TWO 1
+column 2: PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index
+column 1000000: PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index
+no output columns: 0 PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index
+negative: ValueError: PDOStatement::getColumnMeta(): Argument #1 ($column) must be greater than or equal to 0
+done