sixd            Tue Jan 15 20:47:50 2008 UTC

  Modified files:              
    /php-src/ext/oci8   oci8.c oci8_lob.c php_oci8_int.h 
    /php-src/ext/oci8/tests     bug43497.phpt 
  Log:
  MFB: fix #43497 (OCI8 XML/getClobVal aka temporary LOBs leak UGA memory)
  
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/oci8.c?r1=1.339&r2=1.340&diff_format=u
Index: php-src/ext/oci8/oci8.c
diff -u php-src/ext/oci8/oci8.c:1.339 php-src/ext/oci8/oci8.c:1.340
--- php-src/ext/oci8/oci8.c:1.339       Mon Dec 31 07:12:12 2007
+++ php-src/ext/oci8/oci8.c     Tue Jan 15 20:47:50 2008
@@ -26,7 +26,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: oci8.c,v 1.339 2007/12/31 07:12:12 sebastian Exp $ */
+/* $Id: oci8.c,v 1.340 2008/01/15 20:47:50 sixd Exp $ */
 /* TODO
  *
  * file://localhost/www/docs/oci10/ociaahan.htm#423823 - implement lob_empty() 
with OCI_ATTR_LOBEMPTY
@@ -674,7 +674,7 @@
        php_info_print_table_start();
        php_info_print_table_row(2, "OCI8 Support", "enabled");
        php_info_print_table_row(2, "Version", "1.2.2");
-       php_info_print_table_row(2, "Revision", "$Revision: 1.339 $");
+       php_info_print_table_row(2, "Revision", "$Revision: 1.340 $");
 
        snprintf(buf, sizeof(buf), "%ld", OCI_G(num_persistent));
        php_info_print_table_row(2, "Active Persistent Connections", buf);
@@ -1645,7 +1645,10 @@
        php_oci_descriptor *descriptor;
        ub4 lob_length;
        int column_size;
-       zstr lob_buffer, zstr_data = ZSTR(column->data);
+       int lob_fetch_status;
+       zstr lob_buffer;
+       zstr zstr_data = ZSTR(column->data);
+       php_oci_lob_type lob_type;
        
        if (column->indicator == -1) { /* column is NULL */ 
                ZVAL_NULL(value); 
@@ -1674,17 +1677,15 @@
                }
 
                if (column->data_type != SQLT_RDD && (mode & 
PHP_OCI_RETURN_LOBS)) {
-                       php_oci_lob_type lob_type;
                        /* PHP_OCI_RETURN_LOBS means that we want the content 
of the LOB back instead of the locator */
                        
-                       if (php_oci_lob_read(descriptor, -1, 0, &lob_buffer, 
&lob_length TSRMLS_CC)) {
+                       lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, 
&lob_buffer, &lob_length TSRMLS_CC);
+                       lob_fetch_status |= (php_oci_lob_get_type(descriptor, 
&lob_type TSRMLS_CC) > 0);
+                       php_oci_temp_lob_close(descriptor);
+                       if (lob_fetch_status) {
                                ZVAL_FALSE(value);
                                return 1;
                        }
-                               
-                       if (php_oci_lob_get_type(descriptor, &lob_type 
TSRMLS_CC) > 0) {
-                               return 1;
-                       }
 
                        switch (lob_type) {
                                case OCI_IS_CLOB:
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/oci8_lob.c?r1=1.31&r2=1.32&diff_format=u
Index: php-src/ext/oci8/oci8_lob.c
diff -u php-src/ext/oci8/oci8_lob.c:1.31 php-src/ext/oci8/oci8_lob.c:1.32
--- php-src/ext/oci8/oci8_lob.c:1.31    Mon Dec 31 07:12:12 2007
+++ php-src/ext/oci8/oci8_lob.c Tue Jan 15 20:47:50 2008
@@ -25,7 +25,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: oci8_lob.c,v 1.31 2007/12/31 07:12:12 sebastian Exp $ */
+/* $Id: oci8_lob.c,v 1.32 2008/01/15 20:47:50 sixd Exp $ */
 
 
 
@@ -575,7 +575,6 @@
 int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
 {
        php_oci_connection *connection = descriptor->connection;
-       int is_temporary;
        
        PHP_OCI_CALL_RETURN(connection->errcode, OCILobClose, (connection->svc, 
connection->err, descriptor->descriptor));
 
@@ -584,7 +583,21 @@
                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                return 1;
        }
+
+       if (php_oci_temp_lob_close(descriptor)) {
+               return 1;
+       }
        
+       return 0;
+} /* }}} */
+
+/* {{{ php_oci_temp_lob_close() 
+   Close Temporary LOB */
+int php_oci_temp_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
+{
+       php_oci_connection *connection = descriptor->connection;
+       int is_temporary;
+
        PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsTemporary, 
(connection->env,connection->err, descriptor->descriptor, &is_temporary));
        
        if (connection->errcode != OCI_SUCCESS) {
@@ -594,7 +607,6 @@
        }
        
        if (is_temporary) {
-               
                PHP_OCI_CALL_RETURN(connection->errcode, OCILobFreeTemporary, 
(connection->svc, connection->err, descriptor->descriptor));
                
                if (connection->errcode != OCI_SUCCESS) {
@@ -606,6 +618,7 @@
        return 0;
 } /* }}} */
 
+
 /* {{{ php_oci_lob_flush() 
  Flush buffers for the LOB (only if they have been used) */
 int php_oci_lob_flush(php_oci_descriptor *descriptor, long flush_flag 
TSRMLS_DC)
@@ -652,7 +665,6 @@
  Close LOB descriptor and free associated resources */
 void php_oci_lob_free (php_oci_descriptor *descriptor TSRMLS_DC)
 {
-
        if (!descriptor || !descriptor->connection) {
                return;
        }
@@ -667,6 +679,12 @@
                php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
        }
 
+#ifdef HAVE_OCI8_TEMP_LOB
+       if (descriptor->type == OCI_DTYPE_LOB) {
+               php_oci_temp_lob_close(descriptor);
+       }
+#endif
+
        PHP_OCI_CALL(OCIDescriptorFree, (descriptor->descriptor, 
descriptor->type));
 
        zend_list_delete(descriptor->connection->rsrc_id);
@@ -899,7 +917,9 @@
        return php_oci_lob_write(descriptor, 0, data, data_len, &bytes_written 
TSRMLS_CC);
 } /* }}} */
 
-int php_oci_lob_get_type(php_oci_descriptor *descriptor, php_oci_lob_type 
*lob_type TSRMLS_DC) /* {{{ */
+/* {{{ php_oci_lob_get_type() 
+   Determine whether LOB is a CLOB or a BLOB */
+int php_oci_lob_get_type(php_oci_descriptor *descriptor, php_oci_lob_type 
*lob_type TSRMLS_DC)
 {
        php_oci_connection *connection = descriptor->connection;
 
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/php_oci8_int.h?r1=1.38&r2=1.39&diff_format=u
Index: php-src/ext/oci8/php_oci8_int.h
diff -u php-src/ext/oci8/php_oci8_int.h:1.38 
php-src/ext/oci8/php_oci8_int.h:1.39
--- php-src/ext/oci8/php_oci8_int.h:1.38        Mon Dec 31 07:12:12 2007
+++ php-src/ext/oci8/php_oci8_int.h     Tue Jan 15 20:47:50 2008
@@ -25,7 +25,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: php_oci8_int.h,v 1.38 2007/12/31 07:12:12 sebastian Exp $ */
+/* $Id: php_oci8_int.h,v 1.39 2008/01/15 20:47:50 sixd Exp $ */
 
 #if HAVE_OCI8
 # ifndef PHP_OCI8_INT_H
@@ -352,6 +352,7 @@
 int php_oci_lob_copy (php_oci_descriptor *, php_oci_descriptor *, long 
TSRMLS_DC);
 #ifdef HAVE_OCI8_TEMP_LOB
 int php_oci_lob_close (php_oci_descriptor * TSRMLS_DC);
+int php_oci_temp_lob_close (php_oci_descriptor * TSRMLS_DC);
 int php_oci_lob_write_tmp (php_oci_descriptor *, ub1, zstr, int TSRMLS_DC);
 #endif
 void php_oci_lob_free(php_oci_descriptor * TSRMLS_DC);
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/tests/bug43497.phpt?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/oci8/tests/bug43497.phpt
diff -u /dev/null php-src/ext/oci8/tests/bug43497.phpt:1.2
--- /dev/null   Tue Jan 15 20:47:50 2008
+++ php-src/ext/oci8/tests/bug43497.phpt        Tue Jan 15 20:47:50 2008
@@ -0,0 +1,294 @@
+--TEST--
+Bug #43497 (OCI8 XML/getClobVal aka temporary LOBs leak UGA memory)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+function sessionid($c)  // determines and returns current session ID
+{
+    $query = "select sid from v\$session where audsid = userenv('sessionid')";
+
+    $stmt = oci_parse($c, $query);
+
+    if (oci_execute($stmt, OCI_DEFAULT)) {
+               $row = oci_fetch($stmt);
+               return oci_result($stmt, 1);
+    }
+
+    return null;
+}
+
+
+function templobs($c, $sid)  // returns number of temporary LOBs
+{
+    $query = "select abstract_lobs from v\$temporary_lobs where sid = " . $sid;
+
+    $stmt = oci_parse($c, $query);
+
+    if (oci_execute($stmt, OCI_DEFAULT)) {
+               $row = oci_fetch($stmt);
+               $val = oci_result($stmt, 1);
+               oci_free_statement($stmt);
+               return $val;
+    }
+    return null;
+}
+
+
+// Read all XML data using explicit LOB locator
+function readxmltab_ex($c)
+{
+    $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from 
bug43497_tab");
+
+       $cntchk = 0;
+       if (oci_execute($stmt)) {
+               while ($result = oci_fetch_array($stmt, OCI_NUM)) {
+                       $result[0]->free();   // cleanup properly
+                       ++$cntchk;
+               }
+       }
+       echo "Loop count check = $cntchk\n";
+}
+
+// Read all XML data using explicit LOB locator but without freeing the temp 
lobs
+function readxmltab_ex_nofree($c)
+{
+    $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from 
bug43497_tab");
+
+       $cntchk = 0;
+       if (oci_execute($stmt)) {
+               while ($result = oci_fetch_array($stmt, OCI_NUM)) {
+                       ++$cntchk;
+               }
+       }
+       echo "Loop count check = $cntchk\n";
+}
+
+// Read all XML data using implicit LOB locator
+function readxmltab_im($c)
+{
+    $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from 
bug43497_tab");
+
+       $cntchk = 0;
+       if (oci_execute($stmt)) {
+               while ($result = oci_fetch_array($stmt, 
OCI_NUM+OCI_RETURN_LOBS)) {
+                       ++$cntchk;
+               }
+       }
+       echo "Loop count check = $cntchk\n";
+}
+
+function createxmltab($c)  // create table w/ field of XML type
+{
+       @dropxmltab($c);
+    $stmt = oci_parse($c, "create table bug43497_tab (id number primary key, 
xml xmltype)");
+    oci_execute($stmt);
+}
+
+function dropxmltab($c)  // delete table
+{
+    $stmt = oci_parse($c, "drop table bug43497_tab");
+    oci_execute($stmt);
+}
+
+
+function fillxmltab($c)
+{
+       for ($id = 1; $id <= 100; $id++) {
+               
+               // create an XML element string with random data                
+               $s = "<data>";
+               for ($j = 0; $j < 128; $j++) {
+                       $s .= rand();           
+               }
+               $s .= "</data>\n";              
+               for ($j = 0; $j < 4; $j++) {
+                       $s .= $s;
+               }               
+               $data = "<?xml version=\"1.0\"?><records>" . $s . "</records>";
+               
+               // insert XML data into database
+               
+               $stmt = oci_parse($c, "insert into bug43497_tab(id, xml) values 
(:id, sys.xmltype.createxml(:xml))");
+               oci_bind_by_name($stmt, ":id", $id);
+               $clob = oci_new_descriptor($c, OCI_D_LOB);
+               oci_bind_by_name($stmt, ":xml", $clob, -1, OCI_B_CLOB);
+               $clob->writetemporary($data);
+               oci_execute($stmt);
+               
+               $clob->close();
+               $clob->free();
+       }
+}
+
+
+// Initialize
+
+createxmltab($c);
+fillxmltab($c);
+
+// Run Test
+
+$sid = sessionid($c);
+
+echo "Explicit LOB use\n";
+for ($i = 1; $i <= 10; $i++) {
+    echo "\nRun              = " . $i . "\n";
+    echo "Temporary LOBs   = " . templobs($c, $sid) . "\n";
+    readxmltab_ex($c);
+}
+
+echo "\nImplicit LOB use\n";
+for ($i = 1; $i <= 10; $i++) {
+    echo "\nRun              = " . $i . "\n";
+    echo "Temporary LOBs   = " . templobs($c, $sid) . "\n";
+    readxmltab_im($c);
+}
+
+echo "\nExplicit LOB with no free (i.e. a temp lob leak)\n";
+for ($i = 1; $i <= 10; $i++) {
+    echo "\nRun              = " . $i . "\n";
+    echo "Temporary LOBs   = " . templobs($c, $sid) . "\n";
+    readxmltab_ex_nofree($c);
+}
+
+
+
+// Cleanup
+
+dropxmltab($c);
+
+oci_close($c);
+
+echo "Done\n";
+?>
+--EXPECT--
+Explicit LOB use
+
+Run              = 1
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 2
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 3
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 4
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 5
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 6
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 7
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 8
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 9
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 10
+Temporary LOBs   = 0
+Loop count check = 100
+
+Implicit LOB use
+
+Run              = 1
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 2
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 3
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 4
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 5
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 6
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 7
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 8
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 9
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 10
+Temporary LOBs   = 0
+Loop count check = 100
+
+Explicit LOB with no free (i.e. a temp lob leak)
+
+Run              = 1
+Temporary LOBs   = 0
+Loop count check = 100
+
+Run              = 2
+Temporary LOBs   = 99
+Loop count check = 100
+
+Run              = 3
+Temporary LOBs   = 198
+Loop count check = 100
+
+Run              = 4
+Temporary LOBs   = 297
+Loop count check = 100
+
+Run              = 5
+Temporary LOBs   = 396
+Loop count check = 100
+
+Run              = 6
+Temporary LOBs   = 495
+Loop count check = 100
+
+Run              = 7
+Temporary LOBs   = 594
+Loop count check = 100
+
+Run              = 8
+Temporary LOBs   = 693
+Loop count check = 100
+
+Run              = 9
+Temporary LOBs   = 792
+Loop count check = 100
+
+Run              = 10
+Temporary LOBs   = 891
+Loop count check = 100
+Done

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to