|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2006-10-16 06:55 UTC] jfbustarret at tf1 dot fr
Description: ------------ On an apache webserver hosting various websites & connecting to various databases, we randomly get ORA-00942 errors (table or view does not exist). It looks like the oci8 mixes up persistent connections & uses one with the wrong credentials. Disabling persistent connections (oci8.max_persistent=0) solves the problem. Playing with ping_interval & persistent_timeout does not. oci8 version : 1.2.2 ($Revision: 1.269.2.16.2.21 $) Oracle client version : 9.2 PHP Version : 5.1.6 with hardening patch Reproduce code: --------------- No reproduce code. The errors are random (random times, random sql requests, random websites). PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Dec 17 06:00:01 2025 UTC |
I did add debug messages in oci8.c diff -rup oci8-1.2.2/oci8.c oci8-1.2.2.debug/oci8.c --- oci8-1.2.2/oci8.c 2006-08-24 14:05:19.000000000 +0200 +++ oci8-1.2.2.debug/oci8.c 2006-10-17 15:26:59.000000000 +0200 @@ -666,7 +666,7 @@ PHP_MINFO_FUNCTION(oci) php_info_print_table_start(); php_info_print_table_row(2, "OCI8 Support", "enabled"); - php_info_print_table_row(2, "Version", "1.2.1"); + php_info_print_table_row(2, "Version", "1.2.2.debug"); php_info_print_table_row(2, "Revision", "$Revision: 1.269.2.16.2.21 $"); sprintf(buf, "%ld", OCI_G(num_persistent)); @@ -1106,12 +1106,13 @@ php_oci_connection *php_oci_do_connect_e /* okay, the connection is open and the server is still alive */ connection->used_this_request = 1; - smart_str_free_ex(&hashed_details, 0); if (zend_list_find(connection->rsrc_id, &rsrc_type) && (rsrc_type == le_pconnection) && zend_list_addref(connection->rsrc_id) == SUCCESS) { /* do nothing */ } else { connection->rsrc_id = zend_list_insert(connection, le_pconnection); } + php_error_docref(NULL TSRMLS_CC, E_WARNING, "found persistent connection for %s : %s (rsrc_id %d)\n", hashed_details.c, connection->hash_key, connection->rsrc_id); + smart_str_free_ex(&hashed_details, 0); return connection; } } These debug message show different persistent connections using the same rsrc_id : Oct 17 16:00:35 [error] 2880 - www.olweb.fr - Environnement - Warning PHP : ociplogon() [<a href='function.ociplogon'>function.ociplogon</a>]: found persistent connection for oci8___[user1]__1442677164__[database].world__8710 : oci8___[user1]__1442677164__[database].world__8710 (rsrc_id 56) Oct 17 16:00:35 [error] 2880 - www.olweb.fr - Environnement - Warning PHP : ociplogon() [<a href='function.ociplogon'>function.ociplogon</a>]: found persistent connection for oci8___[user2]__2782104700__[database].world__8710 : oci8___[user2]__2782104700__[database].world__8710 (rsrc_id 56) After this rsrc_id mixup, the db requests for the second connection use the first one.Reproduce code : <?php ini_set("display_errors", "On"); $server = "..."; $passwd1 = $user1 = "..."; $passwd2 = $user2 = "..."; $table1 = "..."; $conn1 = OCIPLogon($user1, $passwd1, $server); $stmt = OCIParse($conn1, "select * from $table1"); OCIExecute($stmt); $erra=OCIError($conn1); if (!empty($erra['message'])) print "Error: ${erra['code']} ${erra['message']}"; OCIFreeStatement($stmt); $conn1 = OCIPLogon($user2, $passwd2, $server); $stmt = OCIParse($conn1, "select * from $table1"); OCIExecute($stmt); $erra=OCIError($conn1); if (!empty($erra['message'])) print "Error: ${erra['code']} ${erra['message']}"; Displays : Warning: ociexecute(): ORA-00942: table or view does not exist in /mnt/home_distant/jfb/testoci.php on line 17 Expected result : no errorNew reproduce code : <?php ini_set("display_errors", "On"); $server = "..."; $passwd1 = $user1 = "..."; $passwd2 = $user2 = "..."; $passwd3 = $user3 = "..."; $table1 = "..."; $table3 = "..."; // generate a random rsrc_id offset $conn3 = OCIPLogon($user3, $passwd3, $server); for ($i=1; $i<rand(1,2); $i++) { $stmt = OCIParse($conn3, "select * from $table3"); OCIExecute($stmt); } // conn1 will sometimes get conn2->rsrc_id $conn2 = OCIPLogon($user2, $passwd2, $server); $conn1 = OCIPLogon($user1, $passwd1, $server); // this will be randomly executed with user1 or user2 credentials $stmt = OCIParse($conn1, "select * from $table1"); OCIExecute($stmt); You have to call this multiple times through the HTTP server (apache in my case). The script should not generate an error, but randomly displays : <b>Warning</b>: ociexecute() [<a href='function.ociexecute'>function.ociexecute</a>]: ORA-00942: table or view does not exist in <b>/data/www/exploit/htdocs/testoci.php</b> on line <b>23</b> My understanding of the bug is that EG(regular_list) & all ressource ids are reset between requests. EG(persistent_list) is not reset, and connections store invalid rsrc_ids from previous requests. Shouldn't all persistent connections rsrc_ids be reset between requests ?Reverting to the oci8 version 1.1 way of using rsrc_id seems to solve the problem (reproduce code works without error, no error on the production platform for the last 30 minutes - 1 or 2 errors/minute before). --- oci8-1.2.2/oci8.c 2006-08-24 14:05:19.000000000 +0200 +++ oci8-1.2.2-jfb/oci8.c 2006-10-18 11:16:34.000000000 +0200 @@ -1107,11 +1107,7 @@ php_oci_connection *php_oci_do_connect_e /* okay, the connection is open and the server is still alive */ connection->used_this_request = 1; smart_str_free_ex(&hashed_details, 0); - if (zend_list_find(connection->rsrc_id, &rsrc_type) && (rsrc_type == le_pconnection) && zend_list_addref(connection->rsrc_id) == SUCCESS) { - /* do nothing */ - } else { - connection->rsrc_id = zend_list_insert(connection, le_pconnection); - } + connection->rsrc_id = zend_list_insert(connection, le_pconnection); return connection; } } Thanks for your help.Patch applied on PHP 5.1.6/oci8 1.2.2. It crashes on : hash_key_len = tmp ? strlen(tmp->hash_key) : 0; (gdb) print *tmp $3 = {env = 0x2, charset = 33656, server = 0x0, svc = 0x838f424, session = 0x838ed5c, err = 0x847ca58, errcode = 24, descriptors = 0x8480820, is_open = 0, is_attached = 0, is_persistent = 0, used_this_request = 0, needs_commit = 0, rsrc_id = 0, idle_expiry = 47, next_ping = 65537, hash_key = 0xb28863f1 <Address 0xb28863f1 out of bounds>} After applying this after your patch, it works : @@ -1108,9 +1108,9 @@ php_oci_connection *php_oci_do_connect_e /* okay, the connection is open and the server is still alive */ connection->used_this_request = 1; tmp = (php_oci_connection *)zend_list_find(connection->rsrc_id, &rsrc_type); - hash_key_len = tmp ? strlen(tmp->hash_key) : 0; + hash_key_len = tmp && rsrc_type == le_pconnection ? strlen(tmp->hash_key) : 0; - if (tmp != NULL && rsrc_type == le_pconnection && hash_key_len == hashed_details.len && + if (hash_key_len > 0 && hash_key_len == hashed_details.len && memcmp(tmp->hash_key, hashed_details.c, hashed_details.len) == 0 && zend_list_addref(connection->rsrc_id) == SUCCESS) { /* do nothing */ } else {