diff options
| author | Christopher Jones <sixd@php.net> | 2008-02-25 23:52:10 +0000 |
|---|---|---|
| committer | Christopher Jones <sixd@php.net> | 2008-02-25 23:52:10 +0000 |
| commit | 2ce86f5e5a5fd56a64db87e57892455b6eafb7dc (patch) | |
| tree | cf46d0fc496c6391783c8e8ac23019b01f60cbda | |
| parent | 9b730870a118b7ebb59c7cae7b92e940b86dd01f (diff) | |
| download | php-git-2ce86f5e5a5fd56a64db87e57892455b6eafb7dc.tar.gz | |
OCI8: fix bug #44008 (OCI-Lob->close) & bug #44206 (ref cursor leak)
| -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 | 41 | ||||
| -rw-r--r-- | ext/oci8/tests/lob_014.phpt | 4 | ||||
| -rw-r--r-- | ext/oci8/tests/lob_021.phpt | 6 |
9 files changed, 481 insertions, 15 deletions
diff --git a/ext/oci8/oci8_interface.c b/ext/oci8/oci8_interface.c index 22993f9838..4031142b2d 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 89e4882010..d498ded32e 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); @@ -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); } /* }}} */ 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 aaa10087af..43f185a872 100644 --- a/ext/oci8/php_oci8_int.h +++ b/ext/oci8/php_oci8_int.h @@ -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 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..ebf31f7152 --- /dev/null +++ b/ext/oci8/tests/bug44206.phpt @@ -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 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) |
