Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions ext/pdo_firebird/firebird_statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param)
pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
pdo_firebird_db_handle *H = S->H;
isc_blob_handle h = PDO_FIREBIRD_HANDLE_INITIALIZER;
zval data;
zend_ulong put_cnt = 0, rem_cnt;
unsigned short chunk_size;
int result = 1;
Expand All @@ -422,22 +423,26 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param)
return 0;
}

SEPARATE_ZVAL(param);
convert_to_string_ex(param);
data = *param;

for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size) {
if (Z_TYPE_P(param) != IS_STRING) {
zval_copy_ctor(&data);
convert_to_string(&data);
}

for (rem_cnt = Z_STRLEN(data); rem_cnt > 0; rem_cnt -= chunk_size) {
chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;

if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL_P(param)[put_cnt])) {
if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL(data)[put_cnt])) {
RECORD_ERROR(stmt);
result = 0;
break;
}
put_cnt += chunk_size;
}

zval_dtor(param);
if (Z_TYPE_P(param) != IS_STRING) {
zval_dtor(&data);
}

if (isc_close_blob(H->isc_status, &h)) {
RECORD_ERROR(stmt);
Expand Down Expand Up @@ -542,8 +547,19 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
S->H->last_app_error = "Cannot bind to array field";
return 0;

case SQL_BLOB:
case SQL_BLOB: {
if (Z_TYPE_P(parameter) == IS_NULL) {
/* Check if field allow NULL values */
if (~var->sqltype & 1) {
strcpy(stmt->error_code, "HY105");
S->H->last_app_error = "Parameter requires non-null value";
return 0;
}
*var->sqlind = -1;
return 1;
}
return firebird_bind_blob(stmt, (ISC_QUAD*)var->sqldata, parameter);
}
}

/* check if a NULL should be inserted */
Expand Down
26 changes: 26 additions & 0 deletions ext/pdo_firebird/tests/bug_73087.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
PDO_Firebird: bug 73087 segfault binding blob parameter
--SKIPIF--
<?php if (!extension_loaded('interbase') || !extension_loaded('pdo_firebird')) die('skip'); ?>
--FILE--
<?php
require 'testdb.inc';
$C = new PDO('firebird:dbname='.$test_base, $user, $password) or die;
@$C->exec('drop table atable');
$C->exec('create table atable (id integer not null, content blob sub_type 1 segment size 80)');
$S = $C->prepare('insert into atable (id, content) values (:id, :content)');
for ($I = 1; $I < 10; $I++) {
$Params = [
'id' => $I,
'content' => base64_encode(random_bytes(10))
];
foreach ($Params as $Param => $Value)
$S->bindValue($Param, $Value);
$S->execute();
}
unset($S);
unset($C);
echo 'OK';
?>
--EXPECT--
OK