From: Antony Dovgal Date: Thu, 5 Jan 2006 13:42:35 +0000 (+0000) Subject: MFH: delete descriptor from the hash and avoid crashes on commit/rollback X-Git-Tag: php-5.1.2RC2~4 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8eb44c317edced283c9fe49e8e8e69a0cbc1bfc7;p=php MFH: delete descriptor from the hash and avoid crashes on commit/rollback --- diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 9350b6ce44..38363f77ac 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -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); } diff --git a/ext/oci8/oci8_interface.c b/ext/oci8/oci8_interface.c index 688dad4569..7b75a77487 100644 --- a/ext/oci8/oci8_interface.c +++ b/ext/oci8/oci8_interface.c @@ -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)) { diff --git a/ext/oci8/oci8_lob.c b/ext/oci8/oci8_lob.c index 43cfa46490..11e29f6d00 100644 --- a/ext/oci8/oci8_lob.c +++ b/ext/oci8/oci8_lob.c @@ -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; diff --git a/ext/oci8/php_oci8_int.h b/ext/oci8/php_oci8_int.h index 9dd28a3dcd..cf41cbd621 100644 --- a/ext/oci8/php_oci8_int.h +++ b/ext/oci8/php_oci8_int.h @@ -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 index 0000000000..8be4f3a06d --- /dev/null +++ b/ext/oci8/tests/descriptors.phpt @@ -0,0 +1,49 @@ +--TEST-- +commit connection after destroying the descriptor +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +array(1) { + ["BLOB"]=> + object(OCI-Lob)#%d (1) { + ["descriptor"]=> + resource(%d) of type (oci8 descriptor) + } +} +Done