php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #42841 oci_new_cursor PHP crash
Submitted: 2007-10-03 15:39 UTC Modified: 2008-01-31 00:38 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:0 (0.0%)
From: pr0head at gmail dot com Assigned:
Status: Closed Package: OCI8 related
PHP Version: 5.2.4 OS: Linux version 2.6.20-gentoo-r8
Private report: No CVE-ID:
 [2007-10-03 15:39 UTC] pr0head at gmail dot com
Description:
------------
If you have two or more times the same stored procedure where the cursor name the same ( :cursor ), PHP stop work.

Reproduce code:
---------------
$connection = oci_connect( .... );

// First execute SP
$sql = "BEGIN sp_vadik_1( :cursor ); END;";
$stmt = oci_parse( $connection, $sql );
$cursor = oci_new_cursor( $connection );
oci_bind_by_name( $stmt, ":cursor", $cursor, -1, OCI_B_CURSOR );

oci_execute( $stmt, OCI_DEFAULT );
oci_execute( $cursor );

while( $row = oci_fetch_array( $cursor ) ) { .... }

oci_free_statement( $stmt );
oci_free_statement( $cursor );

Expected result:
----------------
If the cursor names are not different ( first - :cursor1, second - :cursor2), the challenges are successful.

If not cleaned cursor to the first call, and declare it in the second, the queries are also successful.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-10-04 00:27 UTC] sixd@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc. If the script requires a 
database to demonstrate the issue, please make sure it creates 
all necessary tables, stored procedures etc.

Please avoid embedding huge scripts into the report.


+------------------------------------------------------------
| I couldn't reproduce it.
| Thanks for reporting the bug, but please include a complete
| testcase so I don't have to guess what the code might be.
| Also, what does "stop work" mean?
+------------------------------------------------------------
 [2007-10-04 08:14 UTC] pr0head at gmail dot com
<?php

/**
* ORACLE Storage Procedure
*
* create or replace procedure sp_vadik_1 ( out_1 out sys_refcursor ) is begin
* open out_1 for select 11 from dual union all select 12 from dual union all select 13 from dual;
* end sp_vadik_1; 
*/

$params_db = array( 'host' => "localhost", 'username' => "username", 'password' => "password", 'dbname' => "db" );

putenv( 'ORACLE_SID=' . $params_db['dbname'] );
$conn_string = '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=' . $params_db['host'] . ')(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=' . $params_db['dbname'] . ')))';

$connection = @oci_connect( $params_db['username'], $params_db['password'], $conn_string );



//------------ START EXECUTE 1 ---------------//
$sql = "BEGIN sp_vadik_1( :cursor ); END;";
$stmt = oci_parse( $connection, $sql );
$cursor = oci_new_cursor( $connection );
oci_bind_by_name( $stmt, ":cursor", $cursor, -1, OCI_B_CURSOR );

oci_execute( $stmt, OCI_DEFAULT );
oci_execute( $cursor );

while( $row = oci_fetch_array( $cursor, OCI_ASSOC + OCI_RETURN_LOBS ) )
{
    $data[] = $row;
}

oci_free_statement( $stmt );
oci_free_statement( $cursor );
//------------ STOP EXECUTE 1 ---------------//



//------------ START EXECUTE 2 ---------------//
$sql = "BEGIN sp_vadik_1( :cursor1 ); END;";
$stmt = oci_parse( $connection, $sql );
$cursor = oci_new_cursor( $connection );
oci_bind_by_name( $stmt, ":cursor1", $cursor, -1, OCI_B_CURSOR );

oci_execute( $stmt, OCI_DEFAULT );
oci_execute( $cursor );

while( $row = oci_fetch_array( $cursor, OCI_ASSOC + OCI_RETURN_LOBS ) )
{
    $data[] = $row;
}

oci_free_statement( $stmt );
oci_free_statement( $cursor );
var_dump($cur2);
//------------ STOP EXECUTE 2 ---------------//

oci_close( $connection );


?>
 [2007-10-04 08:27 UTC] pr0head at gmail dot com
Sorry, need change lines in EXECUTE 2 (for reproduction errors).
SQL and bind param must be the same for both executions:

$sql = "BEGIN sp_vadik_1( :cursor ); END;";
oci_bind_by_name( $stmt, ":cursor", $cursor, -1, OCI_B_CURSOR );
 [2007-10-04 08:38 UTC] pr0head at gmail dot com
"stop work" - this crash PHP.
If run this script in command line, i see error "segmentation false"
 [2007-11-12 10:35 UTC] tony2001@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a backtrace to see what is happening behind the scenes. To
find out how to generate a backtrace, please read
http://bugs.php.net/bugs-generating-backtrace.php for *NIX and
http://bugs.php.net/bugs-generating-backtrace-win32.php for Win32

Once you have generated a backtrace, please submit it to this bug
report and change the status back to "Open". Thank you for helping
us make PHP better.


 [2007-11-20 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2007-11-20 09:46 UTC] pr0head at gmail dot com
This script working normally if not reopen cursor.

Bad result:
$sql = "BEGIN sp_vadik_1( :cursor ); END;";
$stmt = oci_parse( $connection, $sql );
$cursor = oci_new_cursor( $connection );
oci_bind_by_name( $stmt, ":cursor", $cursor, -1, OCI_B_CURSOR );
oci_execute( $stmt, OCI_DEFAULT );
oci_execute( $cursor );
oci_free_statement( $stmt );
oci_free_statement( $cursor );

$sql = "BEGIN sp_vadik_1( :cursor ); END;";
$stmt = oci_parse( $connection, $sql );
$cursor = oci_new_cursor( $connection );
oci_bind_by_name( $stmt, ":cursor", $cursor, -1, OCI_B_CURSOR );
oci_execute( $stmt, OCI_DEFAULT );
oci_execute( $cursor );
oci_free_statement( $stmt );
oci_free_statement( $cursor );

Good result:
$sql = "BEGIN sp_vadik_1( :cursor ); END;";
$stmt = oci_parse( $connection, $sql );
$cursor = oci_new_cursor( $connection );
oci_bind_by_name( $stmt, ":cursor", $cursor, -1, OCI_B_CURSOR );
oci_execute( $stmt, OCI_DEFAULT );
oci_execute( $cursor );
oci_free_statement( $stmt );

$sql = "BEGIN sp_vadik_1( :cursor ); END;";
$stmt = oci_parse( $connection, $sql );
oci_bind_by_name( $stmt, ":cursor", $cursor, -1, OCI_B_CURSOR );
oci_execute( $stmt, OCI_DEFAULT );
oci_execute( $cursor );
oci_free_statement( $stmt );
oci_free_statement( $cursor );
 [2007-12-11 20:39 UTC] sixd@php.net
I reproduced the crash.  The problem appears to be the same as reported in http://bugs.php.net/bug.php?id=43340.  If you change the PL/SQL package definition so out_1 is an "IN OUT" parameter, there is no crash.
 [2007-12-14 18:53 UTC] michael dot virnstein at brodos dot de
This fix only works for out parameters, not for return values from functions. I can't change thosea.
I also filed the bug (Bug #43449), haven't found the other two.
 [2008-01-09 19:40 UTC] sixd@php.net
The original testcase (with the parameter only as OUT) does not crash with OCI8 1.3.0 Beta from PECL.
 [2008-01-30 18:49 UTC] sixd@php.net
This was a latent bug exposed when statement caching was fixed.
The temporary workaround is to set oci8.statement_cache_size=0

The real solution (thanks to Sree) is to add a missing case for
cursors to the out-bind callback:

diff -u oci8_statement.c.orig oci8_statement.c
--- oci8_statement.c.orig	2008-01-30 10:37:32.000000000 -0800
+++ oci8_statement.c	2008-01-30 10:21:31.000000000 -0800
@@ -1174,6 +1174,14 @@
 	}
 
 	if (Z_TYPE_P(val) == IS_RESOURCE) {
+		/* Processing for ref-cursor out binds */
+		if (phpbind->statement != NULL) {
+			*bufpp = phpbind->statement;
+			*alenpp = &phpbind->dummy_len;
+			*piecep = OCI_ONE_PIECE;
+			*rcodepp = &phpbind->retcode;
+			*indpp = &phpbind->indicator;
+		}
 		retval = OCI_CONTINUE;
 	} else if (Z_TYPE_P(val) == IS_OBJECT) {
 		if (!phpbind->descriptor) {


 [2008-01-31 00:38 UTC] sixd@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Fri Apr 18 20:01:57 2014 UTC