]> granicus.if.org Git - php/commitdiff
MFH: delete descriptor from the hash and avoid crashes on commit/rollback
authorAntony Dovgal <tony2001@php.net>
Thu, 5 Jan 2006 13:42:35 +0000 (13:42 +0000)
committerAntony Dovgal <tony2001@php.net>
Thu, 5 Jan 2006 13:42:35 +0000 (13:42 +0000)
ext/oci8/oci8.c
ext/oci8/oci8_interface.c
ext/oci8/oci8_lob.c
ext/oci8/php_oci8_int.h
ext/oci8/tests/descriptors.phpt [new file with mode: 0644]

index 9350b6ce442faa6524e53180d0033f41e3a1ed7f..38363f77acf4502f4e9a0ae9c44da02daed514ea 100644 (file)
@@ -761,7 +761,7 @@ void php_oci_bind_hash_dtor(void *data)
 /* {{{ php_oci_column_hash_dtor()
  Column hash destructor */
 void php_oci_column_hash_dtor(void *data)
-{      
+{
        php_oci_out_column *column = (php_oci_out_column *) data;
        TSRMLS_FETCH();
 
@@ -790,10 +790,25 @@ void php_oci_descriptor_flush_hash_dtor(void *data)
        php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
        TSRMLS_FETCH();
        
-       if (descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
+       if (descriptor && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
                php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
                descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
        }
+       data = NULL;
+}
+/* }}} */
+
+/* {{{ php_oci_descriptor_delete_from_hash()
+ Delete descriptor from the hash */
+int php_oci_descriptor_delete_from_hash(void *data, void *id TSRMLS_DC)
+{
+       php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
+       int *desc_id = (int *) id;
+       
+       if (descriptor && desc_id && descriptor->id == *desc_id) {
+               return 1;
+       }
+       return 0;
 }
 /* }}} */
 
@@ -1379,10 +1394,6 @@ int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC)
  Commit connection */
 int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
 {
-       if (connection->descriptors) {
-               zend_hash_apply(connection->descriptors,(apply_func_t) php_oci_descriptor_flush_hash_dtor TSRMLS_CC);
-       }
-
        connection->errcode = PHP_OCI_CALL(OCITransCommit, (connection->svc, connection->err, (ub4) 0));
        connection->needs_commit = 0;
 
@@ -1683,14 +1694,14 @@ static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
                connection = (php_oci_connection *)le->ptr;
 
                if (connection->used_this_request) {
-                       php_oci_connection_rollback(connection TSRMLS_CC);
-                       
                        if (connection->descriptors) {
                                zend_hash_destroy(connection->descriptors);
                                efree(connection->descriptors);
                                connection->descriptors = NULL;
                        }
                        
+                       php_oci_connection_rollback(connection TSRMLS_CC);
+                       
                        if (OCI_G(persistent_timeout) > 0) {
                                connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
                        }
index 688dad456913273733f68b5930ef8571fd00c8bc..7b75a77487aad03ef760aa0ee7ac16128e5f8865 100644 (file)
@@ -1058,7 +1058,9 @@ PHP_FUNCTION(oci_rollback)
        PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
 
        if (connection->descriptors) {
-               zend_hash_apply(connection->descriptors,(apply_func_t) php_oci_descriptor_flush_hash_dtor TSRMLS_CC);
+               zend_hash_destroy(connection->descriptors);
+               efree(connection->descriptors);
+               connection->descriptors = NULL;
        }
 
        if (php_oci_connection_rollback(connection TSRMLS_CC)) {
@@ -1082,7 +1084,9 @@ PHP_FUNCTION(oci_commit)
        PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
 
        if (connection->descriptors) {
-               zend_hash_apply(connection->descriptors,(apply_func_t) php_oci_descriptor_flush_hash_dtor TSRMLS_CC);
+               zend_hash_destroy(connection->descriptors);
+               efree(connection->descriptors);
+               connection->descriptors = NULL;
        }
        
        if (php_oci_connection_commit(connection TSRMLS_CC)) {
index 43cfa464908e98b3b3375215f7375f63c6fd6895..11e29f6d00b8c628eed3ccd0bc1ec848e457b80f 100644 (file)
@@ -67,7 +67,7 @@ php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long typ
                        break;
        }
 
-       descriptor = emalloc(sizeof(php_oci_descriptor));
+       descriptor = ecalloc(1, sizeof(php_oci_descriptor));
        descriptor->type = type;
 
        OCI_G(errcode) = PHP_OCI_CALL(OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0));
@@ -91,7 +91,7 @@ php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long typ
                /* add Lobs & Files to hash. we'll flush them at the end */
                if (!connection->descriptors) {
                        ALLOC_HASHTABLE(connection->descriptors);
-                       zend_hash_init(connection->descriptors, 13, NULL, php_oci_descriptor_flush_hash_dtor, 0);
+                       zend_hash_init(connection->descriptors, 0, NULL, php_oci_descriptor_flush_hash_dtor, 0);
                }
 
                zend_hash_next_index_insert(connection->descriptors,&descriptor,sizeof(php_oci_descriptor *),NULL);
@@ -473,6 +473,16 @@ int php_oci_lob_flush(php_oci_descriptor *descriptor, int flush_flag TSRMLS_DC)
  Close LOB descriptor and free associated resources */
 void php_oci_lob_free (php_oci_descriptor *descriptor TSRMLS_DC)
 {
+
+       if (!descriptor || !descriptor->connection) {
+               return;
+       }
+
+       if (descriptor->connection->descriptors) {
+               /* delete descriptor from the hash */
+               zend_hash_apply_with_argument(descriptor->connection->descriptors, php_oci_descriptor_delete_from_hash, (void *)&descriptor->id TSRMLS_CC);
+       }
+       
        /* flushing Lobs & Files with buffering enabled */
        if ((descriptor->type == OCI_DTYPE_FILE || descriptor->type == OCI_DTYPE_LOB) && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED) {
                php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
@@ -639,7 +649,7 @@ int php_oci_lob_erase (php_oci_descriptor *descriptor, long offset, long length,
 } /* }}} */
 
 /* {{{ php_oci_lob_is_equal() 
- Compare to LOB descriptors and figure out if they are pointing to the same LOB */
+ Compare two LOB descriptors and figure out if they are pointing to the same LOB */
 int php_oci_lob_is_equal (php_oci_descriptor *descriptor_first, php_oci_descriptor *descriptor_second, boolean *result TSRMLS_DC)
 {
        php_oci_connection *connection = descriptor_first->connection;
index 9dd28a3dcd9df5fad8b1eee1cdb8106b224ba33f..cf41cbd6216102122a864d92e100e7432585ae27 100644 (file)
@@ -276,6 +276,7 @@ void php_oci_column_hash_dtor (void *data);
 void php_oci_define_hash_dtor (void *data);
 void php_oci_bind_hash_dtor (void *data);
 void php_oci_descriptor_flush_hash_dtor (void *data);
+int php_oci_descriptor_delete_from_hash(void *data, void *id TSRMLS_DC);
 
 sb4 php_oci_error (OCIError *, sword TSRMLS_DC);
 sb4 php_oci_fetch_errmsg(OCIError *, text ** TSRMLS_DC);
diff --git a/ext/oci8/tests/descriptors.phpt b/ext/oci8/tests/descriptors.phpt
new file mode 100644 (file)
index 0000000..8be4f3a
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+commit connection after destroying the descriptor
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+                       ".$schema.$table_name." (blob)
+                       VALUES (empty_blob())
+                       RETURNING
+                       blob
+                       INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$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);
+
+unset($blob);
+unset($statement);
+
+oci_commit($c);
+
+$ora_sql = "SELECT blob FROM ".$schema.$table_name." ";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_assoc($statement));
+unset($row['BLOB']);
+
+oci_commit($c);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECTF--    
+array(1) {
+  ["BLOB"]=>
+  object(OCI-Lob)#%d (1) {
+    ["descriptor"]=>
+    resource(%d) of type (oci8 descriptor)
+  }
+}
+Done