]> granicus.if.org Git - php/commitdiff
OCI8: fix bug #44008 (OCI-Lob->close) & bug #44206 (ref cursor leak)
authorChristopher Jones <sixd@php.net>
Mon, 25 Feb 2008 23:49:51 +0000 (23:49 +0000)
committerChristopher Jones <sixd@php.net>
Mon, 25 Feb 2008 23:49:51 +0000 (23:49 +0000)
ext/oci8/oci8_interface.c
ext/oci8/oci8_lob.c
ext/oci8/oci8_statement.c
ext/oci8/php_oci8_int.h
ext/oci8/tests/bug43492_2.phpt [new file with mode: 0644]
ext/oci8/tests/bug44008.phpt [new file with mode: 0644]
ext/oci8/tests/bug44206.phpt [new file with mode: 0644]
ext/oci8/tests/lob_014.phpt
ext/oci8/tests/lob_021.phpt

index 7eeb1804d6afa67d2c75e48f851f56dc2bba978a..485692c5dc75489e4b12505f97863425367ac9e9 100644 (file)
@@ -1548,11 +1548,12 @@ PHP_FUNCTION(oci_free_statement)
        }
 
        PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
-       if (!statement->nested) {
-               /* nested cursors cannot be freed, they are allocated once and used during the fetch */
-               zend_list_delete(statement->id);
-       }
-       
+
+       zend_list_delete(statement->id);
+       if (statement->parent_stmtid) {
+               zend_list_delete(statement->parent_stmtid);
+       }       
+
        RETURN_TRUE;
 }
 /* }}} */
index 71dcad5c84d8e05a560f3e81a869b32930cbf599..6ee516867d490a87a4d7c96c0ae4122ecf7c8898 100644 (file)
@@ -88,6 +88,7 @@ php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long typ
        descriptor->buffering = PHP_OCI_LOB_BUFFER_DISABLED;                            /* buffering is off by default */
        descriptor->charset_form = SQLCS_IMPLICIT;      /* default value */
        descriptor->charset_id = connection->charset;
+       descriptor->is_open = 0;
 
        if (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE) {
                /* add Lobs & Files to hash. we'll flush them at the end */
@@ -576,7 +577,9 @@ int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
 {
        php_oci_connection *connection = descriptor->connection;
        
-       PHP_OCI_CALL_RETURN(connection->errcode, OCILobClose, (connection->svc, connection->err, descriptor->descriptor));
+       if (descriptor->is_open) {
+               PHP_OCI_CALL_RETURN(connection->errcode, OCILobClose, (connection->svc, connection->err, descriptor->descriptor));
+       }
 
        if (connection->errcode != OCI_SUCCESS) {
                php_oci_error(connection->err, connection->errcode TSRMLS_CC);
@@ -914,6 +917,8 @@ int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, ub1 type, zstr data,
                return 1;
        }
 
+       descriptor->is_open = 1;
+
        return php_oci_lob_write(descriptor, 0, data, data_len, &bytes_written TSRMLS_CC);
 } /* }}} */
 
index 6fed08492e6f79c6e30413911c468bf1489f474a..a97e06aa1c58503556a857feec5b009256278d32 100644 (file)
@@ -108,7 +108,7 @@ php_oci_statement *php_oci_statement_create (php_oci_connection *connection, zst
 
        statement->connection = connection;
        statement->has_data = 0;
-       statement->nested = 0;
+       statement->parent_stmtid = 0;
        zend_list_addref(statement->connection->rsrc_id);
 
        if (OCI_G(default_prefetch) > 0) {
@@ -344,6 +344,7 @@ sb4 php_oci_define_callback(dvoid *ctx, OCIDefine *define, ub4 iter, dvoid **buf
                                if (!nested_stmt) {
                                        return OCI_ERROR;
                                }
+                               nested_stmt->parent_stmtid = outcol->statement->id;
                                zend_list_addref(outcol->statement->id);
                                outcol->nested_statement = nested_stmt;
                                outcol->stmtid = nested_stmt->id;
index 81668b7f69cd612967ade080b8936912d6de23a1..0f1ff56968ef53c70993c6d4d1d6e1008be1dfda 100644 (file)
@@ -150,6 +150,7 @@ typedef struct { /* php_oci_descriptor {{{ */
        ub4 chunk_size;                                 /* chunk size of the LOB. 0 - unknown */
        ub1 charset_form;                               /* charset form, required for NCLOBs */
        ub2 charset_id;                                 /* charset ID */
+       unsigned is_open:1;                             /* helps to determine if lob is open or not */
        php_oci_lob_type lob_type;              /* CLOB/BLOB */
 } php_oci_descriptor; /* }}} */
 
@@ -180,6 +181,7 @@ typedef struct { /* php_oci_define {{{ */
 
 typedef struct { /* php_oci_statement {{{ */
        int id;
+       int parent_stmtid;                              /* parent statement id */
        php_oci_connection *connection; /* parent connection handle */
        sword errcode;                                  /* last errcode*/
        OCIError *err;                                  /* private error handle */
@@ -192,7 +194,6 @@ typedef struct { /* php_oci_statement {{{ */
        int ncolumns;                                   /* number of columns in the result */
        unsigned executed:1;                    /* statement executed flag */
        unsigned has_data:1;                    /* statement has more data flag */
-       unsigned nested:1;                      /* statement handle is valid */
        ub2 stmttype;                                   /* statement type */
 } php_oci_statement; /* }}} */
 
diff --git a/ext/oci8/tests/bug43492_2.phpt b/ext/oci8/tests/bug43492_2.phpt
new file mode 100644 (file)
index 0000000..fcf96e9
--- /dev/null
@@ -0,0 +1,369 @@
+--TEST--
+Bug #43492 (Nested cursor leaks after related bug #44206 fixed)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+// This test is similar to bug43492.phpt without the explict free.
+// Now that bug 44206 is fixed an automatic clean up will occur -
+// though it is still recommended in practice.
+
+require dirname(__FILE__).'/connect.inc';
+
+$stmtarray = array(
+    "DROP table bug43492_tab",
+    "CREATE TABLE bug43492_tab(col1 VARCHAR2(1))",
+    "INSERT INTO bug43492_tab VALUES ('A')",
+    "INSERT INTO bug43492_tab VALUES ('B')",
+    "INSERT INTO bug43492_tab VALUES ('C')",
+    "INSERT INTO bug43492_tab VALUES ('D')",
+    "INSERT INTO bug43492_tab VALUES ('E')",
+    "INSERT INTO bug43492_tab VALUES ('F')",
+    "INSERT INTO bug43492_tab VALUES ('G')",
+    "INSERT INTO bug43492_tab VALUES ('H')",
+    "INSERT INTO bug43492_tab VALUES ('I')",
+    "INSERT INTO bug43492_tab VALUES ('J')"
+);
+
+foreach ($stmtarray as $stmt) {
+    $s = oci_parse($c, $stmt);
+    @oci_execute($s);
+}
+
+function fetch($c, $i) {
+    $s = ociparse($c, 'select cursor(select * from bug43492_tab) c from bug43492_tab');
+    ociexecute($s, OCI_DEFAULT);
+    ocifetchinto($s, $result, OCI_ASSOC);
+    ociexecute($result['C'], OCI_DEFAULT);
+    return $result['C'];
+}
+
+for($i = 0; $i < 300; $i++) {
+    $cur = fetch($c, $i);
+    for($j = 0; $j < 10; $j++) {
+        ocifetchinto($cur, $row, OCI_NUM);
+        echo "$row[0] ";
+    }
+    echo "\n";
+    ocifreestatement($cur);
+}
+
+echo "Done\n";
+
+// Cleanup
+
+$stmtarray = array(
+    "DROP table bug43492_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+    $s = oci_parse($c, $stmt);
+    @oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+--EXPECT--
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+A B C D E F G H I J 
+Done
diff --git a/ext/oci8/tests/bug44008.phpt b/ext/oci8/tests/bug44008.phpt
new file mode 100644 (file)
index 0000000..fd10b26
--- /dev/null
@@ -0,0 +1,54 @@
+--TEST--
+Bug #44008 (Incorrect usage of OCI-Lob->close doesn't crash PHP)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Initialization
+
+$stmtarray = array(
+               "create or replace procedure bug44008_proc (p in out clob)
+               as begin p := 'A';
+               end;"
+);
+
+foreach ($stmtarray as $stmt) {
+        $s = oci_parse($c, $stmt);
+        @oci_execute($s);
+}
+
+// Run Test
+
+$s = oci_parse($c, 'begin bug44008_proc(:data); end;');
+$textLob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ":data", $textLob, -1, OCI_B_CLOB);
+oci_execute($s, OCI_DEFAULT);
+$r = $textLob->load();
+echo "$r\n";
+
+// Incorrectly closing the lob doesn't cause a crash.
+// OCI-LOB->close() is documented for use only with OCI-Lob->writeTemporary()
+$textLob->close();
+
+// Cleanup
+
+$stmtarray = array(
+        "drop procedure bug44008_proc"
+);
+
+foreach ($stmtarray as $stmt) {
+        $s = oci_parse($c, $stmt);
+        oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+A
+Done
diff --git a/ext/oci8/tests/bug44206.phpt b/ext/oci8/tests/bug44206.phpt
new file mode 100644 (file)
index 0000000..e5771e4
--- /dev/null
@@ -0,0 +1,43 @@
+--TEST--
+Bug #44206 (Test if selecting ref cursors leads to ORA-1000 maximum open cursors reached)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Run Test
+
+for ($x = 0; $x < 400; $x++)
+{
+       $stmt = "select cursor (select $x from dual) a,
+                cursor (select $x from dual) b 
+                from dual";
+       $s = oci_parse($c, $stmt);
+       $r = oci_execute($s);
+        if (!$r) {
+                echo "Exiting $x\n";
+                exit;
+        }
+       $mode = OCI_ASSOC | OCI_RETURN_NULLS;
+       $result = oci_fetch_array($s, $mode);
+       oci_execute($result['A']);
+       oci_execute($result['B']);
+       oci_fetch_array($result['A'], $mode);
+       oci_fetch_array($result['B'], $mode);
+       oci_free_statement($result['A']);
+       oci_free_statement($result['B']);
+       oci_free_statement($s);
+}
+
+echo "Completed $x\n";
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Completed 400
+Done
index b32ab0b8950facc69a2333c39ed8c53bf8a1277e..5badb20232e8981fcf62afc811268b765e44a5b1 100644 (file)
@@ -43,9 +43,7 @@ echo "Done\n";
 ?>
 --EXPECTF--
 int(4)
-
-Warning: OCI-Lob::close(): ORA-22289: cannot perform  operation on an unopened file or LOB in %slob_014.php on line %d
-bool(false)
+bool(true)
 int(4)
 bool(true)
 
index 008afd73bb7456a868b35122aaad13d88fedf1d0..aa2a3762fd89e9bf1100a4dc7499c02a1ee804e8 100644 (file)
@@ -48,9 +48,7 @@ echo "Done\n";
 ?>
 --EXPECTF--
 int(4)
-
-Warning: OCI-Lob::close(): ORA-22289: cannot perform  operation on an unopened file or LOB in %s on line %d
-bool(false)
+bool(true)
 int(4)
 bool(true)