mirror of
https://github.com/php/php-src.git
synced 2025-08-18 15:08:55 +02:00
delete descriptor from the hash and avoid crashes on commit/rollback
This commit is contained in:
parent
f3275b2080
commit
1e3efec941
5 changed files with 88 additions and 13 deletions
|
@ -790,10 +790,25 @@ void php_oci_descriptor_flush_hash_dtor(void *data)
|
||||||
php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
|
php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
|
||||||
TSRMLS_FETCH();
|
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);
|
php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
|
||||||
descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
|
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 */
|
Commit connection */
|
||||||
int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
|
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->errcode = PHP_OCI_CALL(OCITransCommit, (connection->svc, connection->err, (ub4) 0));
|
||||||
connection->needs_commit = 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;
|
connection = (php_oci_connection *)le->ptr;
|
||||||
|
|
||||||
if (connection->used_this_request) {
|
if (connection->used_this_request) {
|
||||||
php_oci_connection_rollback(connection TSRMLS_CC);
|
|
||||||
|
|
||||||
if (connection->descriptors) {
|
if (connection->descriptors) {
|
||||||
zend_hash_destroy(connection->descriptors);
|
zend_hash_destroy(connection->descriptors);
|
||||||
efree(connection->descriptors);
|
efree(connection->descriptors);
|
||||||
connection->descriptors = NULL;
|
connection->descriptors = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
php_oci_connection_rollback(connection TSRMLS_CC);
|
||||||
|
|
||||||
if (OCI_G(persistent_timeout) > 0) {
|
if (OCI_G(persistent_timeout) > 0) {
|
||||||
connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
|
connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1058,7 +1058,9 @@ PHP_FUNCTION(oci_rollback)
|
||||||
PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
|
PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
|
||||||
|
|
||||||
if (connection->descriptors) {
|
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)) {
|
if (php_oci_connection_rollback(connection TSRMLS_CC)) {
|
||||||
|
@ -1082,7 +1084,9 @@ PHP_FUNCTION(oci_commit)
|
||||||
PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
|
PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
|
||||||
|
|
||||||
if (connection->descriptors) {
|
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)) {
|
if (php_oci_connection_commit(connection TSRMLS_CC)) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long typ
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor = emalloc(sizeof(php_oci_descriptor));
|
descriptor = ecalloc(1, sizeof(php_oci_descriptor));
|
||||||
descriptor->type = type;
|
descriptor->type = type;
|
||||||
|
|
||||||
OCI_G(errcode) = PHP_OCI_CALL(OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0));
|
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 */
|
/* add Lobs & Files to hash. we'll flush them at the end */
|
||||||
if (!connection->descriptors) {
|
if (!connection->descriptors) {
|
||||||
ALLOC_HASHTABLE(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);
|
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 */
|
Close LOB descriptor and free associated resources */
|
||||||
void php_oci_lob_free (php_oci_descriptor *descriptor TSRMLS_DC)
|
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 */
|
/* flushing Lobs & Files with buffering enabled */
|
||||||
if ((descriptor->type == OCI_DTYPE_FILE || descriptor->type == OCI_DTYPE_LOB) && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED) {
|
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);
|
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()
|
/* {{{ 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)
|
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;
|
php_oci_connection *connection = descriptor_first->connection;
|
||||||
|
|
|
@ -276,6 +276,7 @@ void php_oci_column_hash_dtor (void *data);
|
||||||
void php_oci_define_hash_dtor (void *data);
|
void php_oci_define_hash_dtor (void *data);
|
||||||
void php_oci_bind_hash_dtor (void *data);
|
void php_oci_bind_hash_dtor (void *data);
|
||||||
void php_oci_descriptor_flush_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_error (OCIError *, sword TSRMLS_DC);
|
||||||
sb4 php_oci_fetch_errmsg(OCIError *, text ** TSRMLS_DC);
|
sb4 php_oci_fetch_errmsg(OCIError *, text ** TSRMLS_DC);
|
||||||
|
|
49
ext/oci8/tests/descriptors.phpt
Normal file
49
ext/oci8/tests/descriptors.phpt
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue