Skip to content

Commit 916288e

Browse files
ext/pdo_firebird: Throw ValueError if cursor name is too long (#17173)
Co-authored-by: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com>
1 parent 91b7f12 commit 916288e

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

ext/pdo_firebird/firebird_statement.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -887,15 +887,25 @@ static int pdo_firebird_stmt_set_attribute(pdo_stmt_t *stmt, zend_long attr, zva
887887
default:
888888
return 0;
889889
case PDO_ATTR_CURSOR_NAME:
890-
if (!try_convert_to_string(val)) {
890+
zend_string *str_val = zval_try_get_string(val);
891+
if (str_val == NULL) {
892+
return 0;
893+
}
894+
// TODO Check cursor name does not have null bytes?
895+
if (ZSTR_LEN(str_val) >= sizeof(S->name)) {
896+
zend_value_error("Cursor name must not be longer than %zu bytes", sizeof(S->name) - 1);
897+
zend_string_release(str_val);
891898
return 0;
892899
}
893900

894-
if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) {
901+
if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, ZSTR_VAL(str_val), 0)) {
895902
php_firebird_error_stmt(stmt);
903+
zend_string_release(str_val);
896904
return 0;
897905
}
898-
strlcpy(S->name, Z_STRVAL_P(val), sizeof(S->name));
906+
/* Include trailing nul byte */
907+
memcpy(S->name, ZSTR_VAL(str_val), ZSTR_LEN(str_val) + 1);
908+
zend_string_release(str_val);
899909
break;
900910
}
901911
return 1;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Throw value error if cursor name is too long
3+
--EXTENSIONS--
4+
pdo_firebird
5+
--SKIPIF--
6+
<?php require 'skipif.inc'; ?>
7+
--XLEAK--
8+
A bug in firebird causes a memory leak when calling `isc_attach_database()`.
9+
See https://github.com/FirebirdSQL/firebird/issues/7849
10+
--FILE--
11+
<?php
12+
require 'testdb.inc';
13+
14+
$dbh = getDbConnection();
15+
$query = 'SELECT 1 FROM RDB$DATABASE';
16+
$stmt = $dbh->query($query);
17+
18+
try {
19+
$stmt->setAttribute(PDO::ATTR_CURSOR_NAME, str_repeat('a', 35));
20+
} catch (Throwable $e) {
21+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
22+
}
23+
24+
?>
25+
--EXPECT--
26+
ValueError: Cursor name must not be longer than 31 bytes

0 commit comments

Comments
 (0)