]> granicus.if.org Git - php/commitdiff
fix #37581 (oci_bind_array_by_name clobbers input array when using SQLT_AFC, AVC)
authorAntony Dovgal <tony2001@php.net>
Mon, 31 Jul 2006 10:28:46 +0000 (10:28 +0000)
committerAntony Dovgal <tony2001@php.net>
Mon, 31 Jul 2006 10:28:46 +0000 (10:28 +0000)
ext/oci8/bug37581.phpt [new file with mode: 0644]
ext/oci8/oci8.c
ext/oci8/oci8_statement.c
ext/oci8/php_oci8_int.h
ext/oci8/tests/array_bind_005.phpt

diff --git a/ext/oci8/bug37581.phpt b/ext/oci8/bug37581.phpt
new file mode 100644 (file)
index 0000000..ec86c51
--- /dev/null
@@ -0,0 +1,69 @@
+--TEST--
+Bug #37581 (oci_bind_array_by_name clobbers input array when using SQLT_AFC, AVC)
+--SKIPIF--
+<?php if (!extension_loaded("oci8")) print "skip"; ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$p1 = "create or replace package ARRAYBINDPKG1 as
+type str_array is table of char(2) index by binary_integer;
+procedure array_bind(in_str in str_array, out_str out string);
+end ARRAYBINDPKG1;";
+
+$p2 = "create or replace package body ARRAYBINDPKG1 as
+  procedure array_bind(in_str in str_array, out_str out string) is
+  begin
+    for i in 1 .. in_str.count loop
+      out_str := in_str(i);
+    end loop;
+  end array_bind;
+end ARRAYBINDPKG1;";
+
+$s1 = oci_parse($c, $p1);
+$s2 = oci_parse($c, $p2);
+oci_execute($s1);
+oci_execute($s2);
+
+
+$stmt           = oci_parse($c,'begin ARRAYBINDPKG1.array_bind(:in_arr, :out_str); end;');
+$strings        = array('A','B','C','D','E');
+
+oci_bind_array_by_name($stmt,':in_arr',$strings,5,1,SQLT_AFC);
+oci_bind_by_name($stmt,':out_str',$result,10);
+
+oci_execute($stmt);
+var_dump($strings);
+
+oci_execute($stmt);
+var_dump($strings);
+
+echo "Done\n";
+?>
+--EXPECTF--    
+array(5) {
+  [0]=>
+  string(1) "A"
+  [1]=>
+  string(1) "B"
+  [2]=>
+  string(1) "C"
+  [3]=>
+  string(1) "D"
+  [4]=>
+  string(1) "E"
+}
+array(5) {
+  [0]=>
+  string(1) "A"
+  [1]=>
+  string(1) "B"
+  [2]=>
+  string(1) "C"
+  [3]=>
+  string(1) "D"
+  [4]=>
+  string(1) "E"
+}
+Done
index 1015d5072352ec6978bc0c3cde69c3100e1dada5..623209773d673a00975aeeaf5ccb653b09365266 100644 (file)
@@ -775,9 +775,10 @@ void php_oci_bind_hash_dtor(void *data)
        if (bind->array.elements) {
                efree(bind->array.elements);
        }
-/*             if (bind->array.element_lengths) {
+       if (bind->array.element_lengths) {
                efree(bind->array.element_lengths);
        }
+/*
        if (bind->array.indicators) {
                efree(bind->array.indicators);
        } 
index 32cf84d913e583f88040ab806fb002f14c56b35c..819bf2405bb3828a3834f8a276f9f9f2580da9ef 100644 (file)
@@ -664,6 +664,8 @@ int php_oci_bind_post_exec(void *data TSRMLS_DC)
                zval **entry;
                HashTable *hash = HASH_OF(bind->zval);
        
+               zend_hash_internal_pointer_reset(hash);
+
                switch (bind->array.type) {
                        case SQLT_NUM:
                        case SQLT_INT:
@@ -731,7 +733,8 @@ int php_oci_bind_post_exec(void *data TSRMLS_DC)
                        case SQLT_STR:
                        case SQLT_LVC:
                                for (i = 0; i < bind->array.current_length; i++) {
-                                       int curr_element_length = strlen(((text *)bind->array.elements)+i*bind->array.max_length);
+                                       /* int curr_element_length = strlen(((text *)bind->array.elements)+i*bind->array.max_length); */
+                                       int curr_element_length = bind->array.element_lengths[i];
                                        if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
                                                zval_dtor(*entry);
                                                ZVAL_STRINGL(*entry, ((text *)bind->array.elements)+i*bind->array.max_length, curr_element_length, 1);
@@ -1174,7 +1177,7 @@ int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int nam
                                                                (sb4) bind->array.max_length,
                                                                type,
                                                                (dvoid *)0, /* bindp->array.indicators, */
-                                                               (ub2 *)0, /* bindp->array.element_lengths, */
+                                                               (ub2 *)bind->array.element_lengths,
                                                                (ub2 *)0, /* bindp->array.retcodes, */
                                                                (ub4) max_table_length,
                                                                (ub4 *) &(bindp->array.current_length),
@@ -1220,6 +1223,19 @@ php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length,
        bind->array.current_length      = zend_hash_num_elements(Z_ARRVAL_P(var));
        bind->array.old_length          = bind->array.current_length;
        bind->array.max_length          = maxlength;
+       bind->array.element_lengths     = ecalloc(1, max_table_length * sizeof(ub2));
+       
+       zend_hash_internal_pointer_reset(hash);
+       
+       for (i = 0; i < bind->array.current_length; i++) {
+               if (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
+                       convert_to_string_ex(entry);
+                       bind->array.element_lengths[i] = Z_STRLEN_PP(entry); 
+                       zend_hash_move_forward(hash);
+               } else {
+                       break;
+               }
+       }
 
        zend_hash_internal_pointer_reset(hash);
        for (i = 0; i < max_table_length; i++) {
@@ -1259,9 +1275,13 @@ php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length
        bind->array.current_length      = zend_hash_num_elements(Z_ARRVAL_P(var));
        bind->array.old_length          = bind->array.current_length;
        bind->array.max_length          = sizeof(ub4);
+       bind->array.element_lengths     = ecalloc(1, max_table_length * sizeof(ub2));
        
        zend_hash_internal_pointer_reset(hash);
        for (i = 0; i < max_table_length; i++) {
+               if (i < bind->array.current_length) {
+                       bind->array.element_lengths[i] = sizeof(ub4);
+               }
                if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
                        convert_to_long_ex(entry);
                        ((ub4 *)bind->array.elements)[i] = (ub4) Z_LVAL_PP(entry);
@@ -1292,9 +1312,13 @@ php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length
        bind->array.current_length      = zend_hash_num_elements(Z_ARRVAL_P(var));
        bind->array.old_length          = bind->array.current_length;
        bind->array.max_length          = sizeof(double);
+       bind->array.element_lengths     = ecalloc(1, max_table_length * sizeof(ub2));
        
        zend_hash_internal_pointer_reset(hash);
        for (i = 0; i < max_table_length; i++) {
+               if (i < bind->array.current_length) {
+                       bind->array.element_lengths[i] = sizeof(double);
+               }
                if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
                        convert_to_double_ex(entry);
                        ((double *)bind->array.elements)[i] = (double) Z_DVAL_PP(entry);
@@ -1325,10 +1349,14 @@ php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, p
        bind->array.current_length      = zend_hash_num_elements(Z_ARRVAL_P(var));
        bind->array.old_length          = bind->array.current_length;
        bind->array.max_length          = sizeof(OCIDate);
+       bind->array.element_lengths     = ecalloc(1, max_table_length * sizeof(ub2));
 
        zend_hash_internal_pointer_reset(hash);
        for (i = 0; i < max_table_length; i++) {
                OCIDate oci_date;
+               if (i < bind->array.current_length) {
+                       bind->array.element_lengths[i] = sizeof(OCIDate);
+               }
                if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
                        
                        convert_to_string_ex(entry);
index b3e2c461373ff752d649d2ca3f60c4f0d8eb30db..18e739f1cdb8457494c284fffe2fdba95cd31194 100644 (file)
@@ -178,9 +178,9 @@ typedef struct { /* php_oci_bind {{{ */
        php_oci_statement *parent_statement;     /* pointer to the parent statement */
        struct {
                void *elements;
-/*             ub2 *indicators;
+/*             ub2 *indicators; */
                ub2 *element_lengths;
-               ub2 *retcodes;          */
+/*             ub2 *retcodes;          */
                long current_length;
                long old_length;
                long max_length;
index 192d15563d357541cc5ef3b155fb9a5c665c2004..15278532eac41c5a253c043b8e083fcb78ed15ea 100644 (file)
@@ -58,7 +58,8 @@ var_dump($array);
 
 echo "Done\n";
 ?>
---EXPECT--     
+--EXPECTF--    
+Warning: oci_execute(): ORA-01405: fetched column value is NULL in %s on line %d
 array(5) {
   [0]=>
   string(0) ""