]> granicus.if.org Git - php/commitdiff
MFH: PECL Bug #16035 (oci_connect without ORACLE_HOME defined causes segfault)
authorChristopher Jones <sixd@php.net>
Mon, 9 Mar 2009 19:01:16 +0000 (19:01 +0000)
committerChristopher Jones <sixd@php.net>
Mon, 9 Mar 2009 19:01:16 +0000 (19:01 +0000)
ext/oci8/oci8.c
ext/oci8/tests/connect_without_oracle_home.phpt
ext/oci8/tests/connect_without_oracle_home_old.phpt
ext/oci8/tests/create_table.inc
ext/oci8/tests/details.inc
ext/oci8/tests/pecl_bug16035.phpt [new file with mode: 0644]

index bea6d7e153bec036918db7098faf41f40ba2c84e..85d77b3aaf37457598925650ac7c5717e88713c0 100644 (file)
@@ -80,6 +80,12 @@ zend_class_entry *oci_coll_class_entry_ptr;
 #define ONUPDATELONGFUNC OnUpdateInt
 #endif
 
+#ifdef ZTS
+#define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX)
+#else
+#define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT)
+#endif
+
 /* static protos {{{ */
 static void php_oci_connection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
 static void php_oci_pconnection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
@@ -967,60 +973,65 @@ PHP_INI_END()
  */
 static void php_oci_init_global_handles(TSRMLS_D)
 {
-       sword errcode;
-       sb4 error_code = 0;
-       text tmp_buf[PHP_OCI_ERRBUF_LEN];
+       sword errstatus;
+       sb4   ora_error_code = 0;
+       text  tmp_buf[PHP_OCI_ERRBUF_LEN];
 
-       errcode = OCIEnvNlsCreate(&OCI_G(env), OCI_DEFAULT, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
+       errstatus = OCIEnvNlsCreate(&OCI_G(env), PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
 
-       if (errcode == OCI_ERROR) {
-               goto oci_error;
+       if (errstatus == OCI_ERROR) {
+#ifdef HAVE_OCI_INSTANT_CLIENT
+# ifdef PHP_WIN32
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that PATH includes the directory with Oracle Instant Client libraries");
+# else
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that LD_LIBRARY_PATH includes the directory with Oracle Instant Client libraries");
+# endif
+#else
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME is set and points to the right directory");
+#endif
+               OCI_G(env) = NULL;
+               OCI_G(err) = NULL;
+               return;
        }
 
-       errcode = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
-
-       if (errcode == OCI_ERROR || errcode == OCI_SUCCESS_WITH_INFO) {
-               goto oci_error;
-       }
+       errstatus = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
 
+       if (errstatus == OCI_SUCCESS) {
 #if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11)
-       /* This works around PECL bug #15988 (sqlnet.ora not being read).
-        * The root cause was fixed in Oracle 10.2.0.4 but there is no
-        * compile time method to check for that precise patch level, nor
-        * can it be guaranteed that runtime will use the same patch level
-        * the code was compiled with.  So, we do this code for all non
-        * 11g versions.
-        */
-       OCICPool *cpoolh;
-       ub4 cpoolmode = 0x80000000;     /* Pass invalid mode to OCIConnectionPoolCreate */
-       PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
-       PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
-       PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
-       PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
+               /* This fixes PECL bug 15988 (sqlnet.ora not being read).  The
+                * root cause was fixed in Oracle 10.2.0.4 but there is no
+                * compile time method to check for that precise patch level,
+                * nor can it be guaranteed that runtime will use the same
+                * patch level the code was compiled with.  So, we do this
+                * code for all non 11g versions.
+                */
+               OCICPool *cpoolh;
+               ub4 cpoolmode = 0x80000000;     /* Pass invalid mode to OCIConnectionPoolCreate */
+               PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
+               PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
+               PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
+               PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
 #endif
+       } else {
+               OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
 
-       return;
-
-oci_error:
-
-       OCIErrorGet(OCI_G(env), (ub4)1, NULL, &error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
-
-       if (error_code) {
-               int tmp_buf_len = strlen((char *)tmp_buf);
-
-               if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
-                       tmp_buf[tmp_buf_len - 1] = '\0';
-               }
-
-               if (errcode != OCI_SUCCESS_WITH_INFO) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_ERROR: %s", tmp_buf);
-
-                       OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
-
-                       OCI_G(env) = NULL;
-                       OCI_G(err) = NULL;
-               } else {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
+               if (ora_error_code) {
+                       int tmp_buf_len = strlen((char *)tmp_buf);
+                       
+                       if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
+                               tmp_buf[tmp_buf_len - 1] = '\0';
+                       }
+                       
+                       if (errstatus == OCI_SUCCESS_WITH_INFO) {
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
+                       } else {
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_ERROR: %s", tmp_buf);
+                               
+                               OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
+                               
+                               OCI_G(env) = NULL;
+                               OCI_G(err) = NULL;
+                       }
                }
        }
 } /* }}} */
@@ -1062,14 +1073,6 @@ PHP_MINIT_FUNCTION(oci)
        zend_class_entry oci_lob_class_entry;
        zend_class_entry oci_coll_class_entry;
 
-#define PHP_OCI_INIT_MODE_TMP OCI_DEFAULT | OCI_OBJECT
-
-#ifdef ZTS
-#define PHP_OCI_INIT_MODE PHP_OCI_INIT_MODE_TMP | OCI_THREADED
-#else
-#define PHP_OCI_INIT_MODE PHP_OCI_INIT_MODE_TMP
-#endif
-
 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
        /* This check allows PECL builds from this file to be portable to older PHP releases */
        /* this is handled by new globals management code */
@@ -1684,6 +1687,14 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
                }
        }
 
+       /* Initialize global handles if they weren't initialized before */
+       if (OCI_G(env) == NULL) {
+               php_oci_init_global_handles(TSRMLS_C);
+               if (OCI_G(env) == NULL) {
+                       return NULL;
+               }
+       }
+
        /* We cannot use the new session create logic (OCISessionGet from
         * client-side session pool) when privileged connect or password
         * change is attempted or OCI_CRED_EXT mode is specified.
@@ -1715,11 +1726,6 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
        }
        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
 
-       /* Initialize global handles if they weren't initialized before */
-       if (OCI_G(env) == NULL) {
-               php_oci_init_global_handles(TSRMLS_C);
-       }
-
        if (charset && *charset) {
                PHP_OCI_CALL_RETURN(charsetid, OCINlsCharSetNameToId, (OCI_G(env), (CONST oratext *)charset));
                if (!charsetid) {
index 840693476f62cca8b2adeff7dc4e6347d0c0deb4..6839ec7d951d3c86bba92ca3a5ab267139e47723 100644 (file)
@@ -2,15 +2,23 @@
 oci_connect() without ORACLE_HOME set (OCIServerAttach() segfaults)
 --SKIPIF--
 <?php 
-/* disabled for a while */
-die("skip");
-
 if (!extension_loaded('oci8')) die("skip no oci8 extension"); 
+/* Disabled: Fix for PECL Bug #16035 stops a crash if ORACLE_HOME is not set when PHP starts. Using putenv('ORACLE_HOME=""') at runtime will still segfault */
+die("skip can't be tested with run-tests.php");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo);
+if ($ov !== 1) {
+       die ("skip Test only valid when OCI8 is built with an ORACLE_HOME");
+}
 ?>
 --FILE--
 <?php
 
-require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/details.inc";
+
+putenv('ORACLE_HOME=""');
 
 if (!empty($dbase)) {
        var_dump(oci_connect($user, $password, $dbase));
@@ -19,12 +27,10 @@ else {
        var_dump(oci_connect($user, $password));
 }
        
-echo "Done\n";
-
 ?>
+===DONE===
+<?php exit(0); ?>
 --EXPECTF--
-Warning: ocilogon(): _oci_open_server failed, check ORACLE_HOME and NLS_LANG variables: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor in %sconnect.inc on line %d
-
-Warning: oci_connect(): _oci_open_server failed, check ORACLE_HOME and NLS_LANG variables: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor in %sconnect_without_oracle_home.php on line %d
+Warning: oci_connect(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME is set and points to the right directory in %s on line %d
 bool(false)
-Done
+===DONE===
index 171ff45f519f668a703f6e39687157ed25160f9d..0affa01b8adab1e758c6d218d16bcb25db2411db 100644 (file)
@@ -2,14 +2,23 @@
 ocilogon() without ORACLE_HOME set (OCIServerAttach() segfaults)
 --SKIPIF--
 <?php 
-/* disabled for a while */
-die("skip");
 if (!extension_loaded('oci8')) die("skip no oci8 extension"); 
+/* Disabled: Fix for PECL Bug #16035 stops a crash if ORACLE_HOME is not set when PHP starts. Using putenv('ORACLE_HOME=""') at runtime will still segfault */
+die("skip can't be tested with run-tests.php");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo);
+if ($ov !== 1) {
+       die ("skip Test only valid when OCI8 is built with an ORACLE_HOME");
+}
 ?>
 --FILE--
 <?php
 
-require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/details.inc";
+
+putenv('ORACLE_HOME=""');
 
 if (!empty($dbase)) {
        var_dump(ocilogon($user, $password, $dbase));
@@ -18,12 +27,10 @@ else {
        var_dump(ocilogon($user, $password));
 }
        
-echo "Done\n";
-
 ?>
+===DONE===
+<?php exit(0); ?>
 --EXPECTF--
-Warning: ocilogon(): _oci_open_server failed, check ORACLE_HOME and NLS_LANG variables: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor in %sconnect.inc on line %d
-
-Warning: oci_connect(): _oci_open_server failed, check ORACLE_HOME and NLS_LANG variables: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor in %sconnect_without_oracle_home.php on line %d
+Warning: ocilogon(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME is set and points to the right directory in %s on line %d
 bool(false)
-Done
+===DONE===
index d6debf2339a7316cda9aacccdf04aef4cadf4d5d..afd1fceb9b9f0af38b002630f2f73c2a724bd2e1 100644 (file)
@@ -1,19 +1,11 @@
 <?php
-
     if ($c) {
-        $ora_sql = "DROP TABLE
-                                ".$schema.$table_name."
-                   ";
-
-        $statement = OCIParse($c, $ora_sql);
-        @OCIExecute($statement);
+        $ora_sql = "DROP TABLE ".$schema.$table_name;
+        $statement = oci_parse($c, $ora_sql);
+        @oci_execute($statement);
 
-        $ora_sql = "CREATE TABLE 
-                                ".$schema.$table_name." (id NUMBER, value NUMBER, blob BLOB, clob CLOB, string VARCHAR(10)) 
-                   ";
-                      
-        $statement = OCIParse($c,$ora_sql);
-        OCIExecute($statement);
+        $ora_sql = "CREATE TABLE ".$schema.$table_name." (id NUMBER, value NUMBER, blob BLOB, clob CLOB, string VARCHAR(10))";
+        $statement = oci_parse($c, $ora_sql);
+        oci_execute($statement);
     }
-
 ?>
index 9e8377c43c03c5431496158c056e9e6169338d8e..35c1e93b753258b0f5701f32eb6d98272985ce99 100644 (file)
@@ -32,9 +32,10 @@ if (false !== getenv('PHP_OCI8_TEST_DB')) {
        }
 } else {
        $user                                           = "system";
-       $password                                       = "system";
+       $password                                       = "oracle";
        $dbase                                          = "localhost/XE";
-       $oracle_on_localhost            = TRUE;
+       $dbase                                          = "ca-tools1.us.oracle.com/XE";
+       $oracle_on_localhost            = FALSE;
        $test_drcp                                      = FALSE;
 }
 
diff --git a/ext/oci8/tests/pecl_bug16035.phpt b/ext/oci8/tests/pecl_bug16035.phpt
new file mode 100644 (file)
index 0000000..017a488
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+PECL Bug #16035 (Crash with Oracle 10.2 connecting with a character set but ORACLE_HOME isn't set)
+--SKIPIF--
+<?php 
+if (!extension_loaded('oci8')) die ("skip no oci8 extension"); 
+/* Disabled: Fix for PECL Bug #16035 stops a crash if ORACLE_HOME is not set when PHP starts. Using putenv('ORACLE_HOME=""') at runtime will still segfault */
+die("skip can't be tested with run-tests.php");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo);
+if ($ov !== 1) {
+       die ("skip Test only valid when OCI8 is built with an ORACLE_HOME");
+}
+?>
+--FILE--
+<?php
+
+putenv('ORACLE_HOME=""');
+oci_connect('abc', 'def', 'ghi', 'jkl');
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+PHP Warning:  oci_connect(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME is set and points to the right directory in %s on line %d
+===DONE===