Skip to content

Commit 12d54fa

Browse files
committed
MFH: fix #40078 (ORA-01405 when fetching NULL values using oci_bind_array_by_name())
1 parent 5e74c60 commit 12d54fa

File tree

5 files changed

+72
-4
lines changed

5 files changed

+72
-4
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ PHP NEWS
99
- Fixed bug #40083 (milter SAPI functions always return false/null). (Tony)
1010
- Fixed bug #40079 (php_get_current_user() not thread safe). (Ilia, wharmby
1111
at uk dot ibm dot com)
12+
- Fixed bug #40078 (ORA-01405 when fetching NULL values using
13+
oci_bind_array_by_name()). (Tony)
1214
- Fixed bug #40076 (zend_alloc.c: Value of enumeration constant must be in
1315
range of signed integer). (Dmitry)
1416
- Fixed bug #40073 (exif_read_data dies on certain images). (Tony, Marcus)

ext/oci8/oci8.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,13 +778,16 @@ void php_oci_bind_hash_dtor(void *data)
778778
if (bind->array.elements) {
779779
efree(bind->array.elements);
780780
}
781+
781782
if (bind->array.element_lengths) {
782783
efree(bind->array.element_lengths);
783784
}
784-
/*
785+
785786
if (bind->array.indicators) {
786787
efree(bind->array.indicators);
787-
}
788+
}
789+
790+
/*
788791
if (bind->array.retcodes) {
789792
efree(bind->array.retcodes);
790793
}

ext/oci8/oci8_statement.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int nam
12701270
(dvoid *) bindp->array.elements,
12711271
(sb4) bind->array.max_length,
12721272
type,
1273-
(dvoid *)0, /* bindp->array.indicators, */
1273+
(dvoid *)bindp->array.indicators,
12741274
(ub2 *)bind->array.element_lengths,
12751275
(ub2 *)0, /* bindp->array.retcodes, */
12761276
(ub4) max_table_length,
@@ -1320,13 +1320,18 @@ php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length,
13201320
bind->array.max_length = maxlength;
13211321
bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
13221322
memset(bind->array.element_lengths, 0, max_table_length*sizeof(ub2));
1323+
bind->array.indicators = safe_emalloc(max_table_length, sizeof(sb2), 0);
1324+
memset(bind->array.indicators, 0, max_table_length*sizeof(sb2));
13231325

13241326
zend_hash_internal_pointer_reset(hash);
13251327

13261328
for (i = 0; i < bind->array.current_length; i++) {
13271329
if (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
13281330
convert_to_string_ex(entry);
13291331
bind->array.element_lengths[i] = Z_STRLEN_PP(entry);
1332+
if (Z_STRLEN_PP(entry) == 0) {
1333+
bind->array.indicators[i] = -1;
1334+
}
13301335
zend_hash_move_forward(hash);
13311336
} else {
13321337
break;
@@ -1372,6 +1377,7 @@ php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length
13721377
bind->array.max_length = sizeof(ub4);
13731378
bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
13741379
memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1380+
bind->array.indicators = NULL;
13751381

13761382
zend_hash_internal_pointer_reset(hash);
13771383
for (i = 0; i < max_table_length; i++) {
@@ -1409,6 +1415,7 @@ php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length
14091415
bind->array.max_length = sizeof(double);
14101416
bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
14111417
memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1418+
bind->array.indicators = NULL;
14121419

14131420
zend_hash_internal_pointer_reset(hash);
14141421
for (i = 0; i < max_table_length; i++) {
@@ -1446,6 +1453,7 @@ php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, p
14461453
bind->array.max_length = sizeof(OCIDate);
14471454
bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
14481455
memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1456+
bind->array.indicators = NULL;
14491457

14501458
zend_hash_internal_pointer_reset(hash);
14511459
for (i = 0; i < max_table_length; i++) {

ext/oci8/php_oci8_int.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ typedef struct { /* php_oci_bind {{{ */
180180
php_oci_statement *parent_statement; /* pointer to the parent statement */
181181
struct {
182182
void *elements;
183-
/* ub2 *indicators; */
183+
sb2 *indicators;
184184
ub2 *element_lengths;
185185
/* ub2 *retcodes; */
186186
ub4 current_length;

ext/oci8/tests/bug40078.phpt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
Bug #40078 (ORA-01405 when fetching NULL values using oci_bind_array_by_name())
3+
--SKIPIF--
4+
<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
5+
--FILE--
6+
<?php
7+
8+
require dirname(__FILE__).'/connect.inc';
9+
10+
$create_pkg = "
11+
CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
12+
TYPE ARRTYPE IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
13+
PROCEDURE nullbind(c1 OUT ARRTYPE);
14+
END ARRAYBINDPKG1;";
15+
$statement = oci_parse($c, $create_pkg);
16+
oci_execute($statement);
17+
18+
$create_pkg_body = "
19+
CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
20+
PROCEDURE nullbind(c1 OUT ARRTYPE) IS
21+
BEGIN
22+
c1(1) := 'one';
23+
c1(2) := 'two';
24+
c1(3) := '';
25+
c1(4) := 'four';
26+
c1(5) := 'five';
27+
END nullbind;
28+
END ARRAYBINDPKG1;";
29+
$statement = oci_parse($c, $create_pkg_body);
30+
oci_execute($statement);
31+
32+
$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.nullbind(:c1); END;");
33+
34+
oci_bind_array_by_name($statement, ":c1", $array, 5, 20, SQLT_CHR);
35+
36+
oci_execute($statement);
37+
38+
var_dump($array);
39+
40+
echo "Done\n";
41+
?>
42+
--EXPECTF--
43+
array(5) {
44+
[0]=>
45+
string(3) "one"
46+
[1]=>
47+
string(3) "two"
48+
[2]=>
49+
string(0) ""
50+
[3]=>
51+
string(4) "four"
52+
[4]=>
53+
string(4) "five"
54+
}
55+
Done

0 commit comments

Comments
 (0)