From cb00636b1dadb2462ff634f13ed89c3d6cba569b Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Mon, 24 Aug 2026 18:32:11 -0400 Subject: [PATCH] [PDO] Bound-check column index in getColumnMeta() PDOStatement::getColumnMeta() indexed stmt->columns as soon as the driver hook reported success, without checking that the columns had been described or that the index was in range, so pdo_odbc, whose hook always reports success, read out of bounds and crashed. Raise SQLSTATE 07009 and return false instead, matching what the drivers that bound-check the index in their own hook already return. --- NEWS | 4 ++ ext/pdo/pdo_stmt.c | 7 +++ ext/pdo_odbc/tests/getcolumnmeta_bounds.phpt | 49 ++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 ext/pdo_odbc/tests/getcolumnmeta_bounds.phpt diff --git a/NEWS b/NEWS index 3346d38ea898..3f93ac74c1e2 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ PHP NEWS registrations are freed while still reachable from the cycle collector. (Ilia Alshanetsky) +- PDO: + . Fixed PDOStatement::getColumnMeta() reading out of bounds for an invalid + column index. (Ilia Alshanetsky) + 24 Sep 2026, PHP 8.4.26 diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 51c2f58c6c2a..8612a01e0444 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -1700,6 +1700,13 @@ PHP_METHOD(PDOStatement, getColumnMeta) RETURN_FALSE; } + if (stmt->columns == NULL || colno >= stmt->column_count) { + zval_ptr_dtor(return_value); + ZVAL_UNDEF(return_value); + pdo_raise_impl_error(stmt->dbh, stmt, "07009", "invalid column index"); + RETURN_FALSE; + } + /* add stock items */ col = &stmt->columns[colno]; add_assoc_str(return_value, "name", zend_string_copy(col->name)); diff --git a/ext/pdo_odbc/tests/getcolumnmeta_bounds.phpt b/ext/pdo_odbc/tests/getcolumnmeta_bounds.phpt new file mode 100644 index 000000000000..6561b926531c --- /dev/null +++ b/ext/pdo_odbc/tests/getcolumnmeta_bounds.phpt @@ -0,0 +1,49 @@ +--TEST-- +PDO_odbc getColumnMeta() bounds checking on unexecuted statements and invalid indexes +--EXTENSIONS-- +pdo_odbc +--SKIPIF-- + +--FILE-- + PDO::ERRMODE_EXCEPTION]); +$stmt = $pdo->prepare('SELECT 1 AS one'); + +try { + var_dump($stmt->getColumnMeta(0)); +} catch (PDOException $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +$stmt->execute(); +var_dump($stmt->getColumnMeta(0)); + +try { + var_dump($stmt->getColumnMeta(5)); +} catch (PDOException $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +echo "done\n"; +?> +--EXPECTF-- +PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index +array(4) { + ["pdo_type"]=> + int(2) + ["name"]=> + string(3) "one" + ["len"]=> + int(%d) + ["precision"]=> + int(%d) +} +PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index +done