diff options
author | Christopher Jones <sixd@php.net> | 2008-02-25 23:50:51 +0000 |
---|---|---|
committer | Christopher Jones <sixd@php.net> | 2008-02-25 23:50:51 +0000 |
commit | b4b099ae1971a3987b83ef64f96b91e7cb6ddd81 (patch) | |
tree | e132736ec54b941f9b682c0aec11372fc530232c /ext | |
parent | 6e46f25b129ba5e1575b2160e1168bf4d017e1ca (diff) | |
download | php-git-b4b099ae1971a3987b83ef64f96b91e7cb6ddd81.tar.gz |
MFH: OCI8: fix bug #44008 (OCI-Lob->close) & bug #44206 (ref cursor leak)
Diffstat (limited to 'ext')
-rw-r--r-- | ext/oci8/oci8_interface.c | 9 | ||||
-rw-r--r-- | ext/oci8/oci8_lob.c | 7 | ||||
-rw-r--r-- | ext/oci8/oci8_statement.c | 3 | ||||
-rw-r--r-- | ext/oci8/php_oci8_int.h | 3 | ||||
-rw-r--r-- | ext/oci8/tests/bug43492_2.phpt | 369 | ||||
-rw-r--r-- | ext/oci8/tests/bug44008.phpt | 54 | ||||
-rw-r--r-- | ext/oci8/tests/bug44206.phpt | 43 | ||||
-rw-r--r-- | ext/oci8/tests/lob_014.phpt | 4 | ||||
-rw-r--r-- | ext/oci8/tests/lob_021.phpt | 6 |
9 files changed, 483 insertions, 15 deletions
diff --git a/ext/oci8/oci8_interface.c b/ext/oci8/oci8_interface.c index f093c45a1e..40efb9ce0c 100644 --- a/ext/oci8/oci8_interface.c +++ b/ext/oci8/oci8_interface.c @@ -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; } diff --git a/ext/oci8/oci8_lob.c b/ext/oci8/oci8_lob.c index 1b87616df6..83a6719df0 100644 --- a/ext/oci8/oci8_lob.c +++ b/ext/oci8/oci8_lob.c @@ -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); @@ -909,6 +912,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); } /* }}} */ diff --git a/ext/oci8/oci8_statement.c b/ext/oci8/oci8_statement.c index 17822d5b3b..a07937a9a4 100644 --- a/ext/oci8/oci8_statement.c +++ b/ext/oci8/oci8_statement.c @@ -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; diff --git a/ext/oci8/php_oci8_int.h b/ext/oci8/php_oci8_int.h index f71d99c046..8e381e45f6 100644 --- a/ext/oci8/php_oci8_int.h +++ b/ext/oci8/php_oci8_int.h @@ -143,6 +143,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 {{{ */ @@ -171,6 +172,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 */ @@ -183,7 +185,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 index 0000000000..fcf96e984e --- /dev/null +++ b/ext/oci8/tests/bug43492_2.phpt @@ -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 index 0000000000..fd10b26b8b --- /dev/null +++ b/ext/oci8/tests/bug44008.phpt @@ -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 index 0000000000..e5771e4182 --- /dev/null +++ b/ext/oci8/tests/bug44206.phpt @@ -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 diff --git a/ext/oci8/tests/lob_014.phpt b/ext/oci8/tests/lob_014.phpt index 60ed945312..1ba29ee649 100644 --- a/ext/oci8/tests/lob_014.phpt +++ b/ext/oci8/tests/lob_014.phpt @@ -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) diff --git a/ext/oci8/tests/lob_021.phpt b/ext/oci8/tests/lob_021.phpt index 32ef6f9fef..0ae6b377ab 100644 --- a/ext/oci8/tests/lob_021.phpt +++ b/ext/oci8/tests/lob_021.phpt @@ -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) |