Skip to content

Commit 42ee12b

Browse files
committed
ext/pdo_firebird: Fix GH-25006 getColumnMeta() bounds check
pdo_firebird_stmt_get_column_meta() indexed out_sqlda.sqlvar before the core rejected an out-of-range column. column_count is the number of XSQLVAR slots from XSQLDA_LENGTH(). The hook now returns success without reading sqlvar, and the existing check raises SQLSTATE 07009. describe and get_col stay inside their callers' column loops. param_hook already rejects paramno >= sqld. Returning FAILURE here would yield false, because the statement error is cleared before the hook runs. Fixes GH-25006
1 parent e31cab6 commit 42ee12b

3 files changed

Lines changed: 85 additions & 2 deletions

File tree

‎NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ PHP NEWS
176176
. Fixed a duplicate warning when ATTR_STATEMENT_CLASS is rejected on a
177177
persistent connection. (Ilia Alshanetsky)
178178

179+
- PDO_Firebird:
180+
. Fixed bug GH-25006 (getColumnMeta() reads out of bounds for an
181+
out-of-range column index). (Ilia Alshanetsky)
182+
179183
- Phar:
180184
. Fixed bug GH-24740 (Oversized tar metadata exhausts the memory limit).
181185
(Lazizbek Ergashev)

‎ext/pdo_firebird/firebird_statement.c‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,15 @@ static int pdo_firebird_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
342342
static int pdo_firebird_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
343343
{
344344
pdo_firebird_stmt *S = (pdo_firebird_stmt *) stmt->driver_data;
345-
XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
346-
345+
XSQLVAR *var;
347346
enum pdo_param_type param_type;
347+
348+
if (colno >= stmt->column_count) {
349+
array_init(return_value);
350+
return 1;
351+
}
352+
353+
var = &S->out_sqlda.sqlvar[colno];
348354
if (var->sqlscale < 0) {
349355
param_type = PDO_PARAM_STR;
350356
} else {
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
--TEST--
2+
GH-25006 (PDO_Firebird::getColumnMeta() reads out of bounds for an out-of-range column index)
3+
--EXTENSIONS--
4+
pdo_firebird
5+
--SKIPIF--
6+
<?php
7+
require 'skipif.inc';
8+
?>
9+
--XLEAK--
10+
A bug in firebird causes a memory leak when calling `isc_attach_database()`.
11+
See https://github.com/FirebirdSQL/firebird/issues/7849
12+
--FILE--
13+
<?php
14+
require 'testdb.inc';
15+
16+
$dbh = getDbConnection();
17+
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
18+
19+
$stmt = $dbh->prepare('SELECT 1 AS one, 2 AS two FROM RDB$DATABASE');
20+
21+
echo "before execute: ";
22+
try {
23+
var_dump($stmt->getColumnMeta(2));
24+
} catch (Throwable $e) {
25+
echo $e::class, ': ', $e->getMessage(), "\n";
26+
}
27+
28+
$stmt->execute();
29+
30+
echo "column 0: ";
31+
$meta = $stmt->getColumnMeta(0);
32+
echo $meta['name'], ' ', $meta['pdo_type'], "\n";
33+
34+
echo "column 1: ";
35+
$meta = $stmt->getColumnMeta(1);
36+
echo $meta['name'], ' ', $meta['pdo_type'], "\n";
37+
38+
foreach ([2, 1000000] as $col) {
39+
echo "column $col: ";
40+
try {
41+
var_dump($stmt->getColumnMeta($col));
42+
} catch (Throwable $e) {
43+
echo $e::class, ': ', $e->getMessage(), "\n";
44+
}
45+
}
46+
47+
echo "no output columns: ";
48+
$empty = $dbh->prepare('EXECUTE BLOCK AS BEGIN END');
49+
echo $empty->columnCount(), ' ';
50+
try {
51+
var_dump($empty->getColumnMeta(0));
52+
} catch (Throwable $e) {
53+
echo $e::class, ': ', $e->getMessage(), "\n";
54+
}
55+
56+
echo "negative: ";
57+
try {
58+
var_dump($stmt->getColumnMeta(-1));
59+
} catch (Throwable $e) {
60+
echo $e::class, ': ', $e->getMessage(), "\n";
61+
}
62+
63+
echo "done\n";
64+
?>
65+
--EXPECT--
66+
before execute: PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index
67+
column 0: ONE 1
68+
column 1: TWO 1
69+
column 2: PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index
70+
column 1000000: PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index
71+
no output columns: 0 PDOException: SQLSTATE[07009]: Invalid descriptor index: invalid column index
72+
negative: ValueError: PDOStatement::getColumnMeta(): Argument #1 ($column) must be greater than or equal to 0
73+
done

0 commit comments

Comments
 (0)