]> 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:52:10 +0000 (23:52 +0000)
committerChristopher Jones <sixd@php.net>
Mon, 25 Feb 2008 23:52:10 +0000 (23:52 +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 22993f98388202f174528d01b7a0e429d91172a9..4031142b2de1e54dbb95a957fa323db9dacf5630 100644 (file)
@@ -1509,10 +1509,11 @@ 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 89e4882010b09ec202c0e7139a04d036e609eefa..d498ded32e9fc484150376459cdab1e30809122f 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 */
@@ -571,7 +572,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);
@@ -908,6 +911,8 @@ int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, ub1 type, char *data,
                return 1;
        }
 
+       descriptor->is_open = 1;
+
        return php_oci_lob_write(descriptor, 0, data, data_len, &bytes_written TSRMLS_CC);
 } /* }}} */
 
index 17822d5b3bcecb36b0a83449b6d1d6b44325ca5e..a07937a9a413c1d806904f65d1205ce18121333b 100644 (file)
@@ -106,7 +106,7 @@ php_oci_statement *php_oci_statement_create (php_oci_connection *connection, cha
 
        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) {
@@ -336,6 +336,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 aaa10087afdd6167fe4561f5477c0600dc722c05..43f185a872c06bb70895795b0e3e39474dc4db17 100644 (file)
@@ -130,6 +130,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_descriptor; /* }}} */
 
 typedef struct { /* php_oci_lob_ctx {{{ */
@@ -158,6 +159,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 */
@@ -170,7 +172,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..ebf31f7
--- /dev/null
@@ -0,0 +1,41 @@
+--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;
+       }
+       $result = oci_fetch_array($s, OCI_ASSOC);
+       oci_execute($result['A']);
+       oci_execute($result['B']);
+       oci_fetch_array($result['A'], OCI_ASSOC);
+       oci_fetch_array($result['B'], OCI_ASSOC);
+       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 60ed94531291bd97dad8a29ae65b96b30c748e8b..1ba29ee649999c08d455f584c1ec3b838eec8c30 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 32ef6f9fef89227d9d7adfca3c6466fc5941e2d4..0ae6b377abb7aff8e0503b396993335f9ccb37fb 100644 (file)
@@ -20,8 +20,6 @@ $blob = oci_new_descriptor($c,OCI_D_LOB);
 oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
 oci_execute($statement, OCI_DEFAULT);
 
-$blob;
-
 var_dump($blob->write("test"));
 var_dump($blob->close());
 var_dump($blob->write("test"));
@@ -50,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)