tony2001 Thu Mar 29 09:33:04 2007 UTC
Added files: (Branch: PHP_5_2)
/php-src/ext/oci8/tests pecl_bug10194.phpt pecl_bug10194_blob.phpt
Modified files:
/php-src/ext/oci8 oci8_lob.c php_oci8_int.h
Log:
MFH: fix PECL bug #10194 (crash in Oracle client when memory limit reached in
the callback)
preallocate the required buffer, so that it would fail earlier.
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/oci8_lob.c?r1=1.7.2.6.2.10&r2=1.7.2.6.2.11&diff_format=u
Index: php-src/ext/oci8/oci8_lob.c
diff -u php-src/ext/oci8/oci8_lob.c:1.7.2.6.2.10
php-src/ext/oci8/oci8_lob.c:1.7.2.6.2.11
--- php-src/ext/oci8/oci8_lob.c:1.7.2.6.2.10 Mon Jan 1 09:36:03 2007
+++ php-src/ext/oci8/oci8_lob.c Thu Mar 29 09:33:03 2007
@@ -25,7 +25,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: oci8_lob.c,v 1.7.2.6.2.10 2007/01/01 09:36:03 sebastian Exp $ */
+/* $Id: oci8_lob.c,v 1.7.2.6.2.11 2007/03/29 09:33:03 tony2001 Exp $ */
@@ -160,7 +160,12 @@
switch (piece)
{
case OCI_LAST_PIECE:
- *(ctx->lob_data) = erealloc(*(ctx->lob_data), (size_t)
(*(ctx->lob_len) + lenp + 1));
+ if ((*(ctx->lob_len) + lenp) > (ctx->alloc_len)) {
+ /* this should not happen ever */
+ *(ctx->lob_data) = NULL;
+ *(ctx->lob_len) = 0;
+ return OCI_ERROR;
+ }
memcpy(*(ctx->lob_data) + *(ctx->lob_len), bufxp,
(size_t) lenp);
*(ctx->lob_len) += lenp;
*(*(ctx->lob_data) + *(ctx->lob_len)) = 0x00;
@@ -168,7 +173,12 @@
case OCI_FIRST_PIECE:
case OCI_NEXT_PIECE:
- *(ctx->lob_data) = erealloc(*(ctx->lob_data), (size_t)
(*(ctx->lob_len) + lenp));
+ if ((*(ctx->lob_len) + lenp) > ctx->alloc_len) {
+ /* this should not happen ever */
+ *(ctx->lob_data) = NULL;
+ *(ctx->lob_len) = 0;
+ return OCI_ERROR;
+ }
memcpy(*(ctx->lob_data) + *(ctx->lob_len), bufxp,
(size_t) lenp);
*(ctx->lob_len) += lenp;
return OCI_CONTINUE;
@@ -176,7 +186,6 @@
default: {
TSRMLS_FETCH();
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected
LOB piece id received (value:%d)", piece);
- efree(*(ctx->lob_data));
*(ctx->lob_data) = NULL;
*(ctx->lob_len) = 0;
return OCI_ERROR;
@@ -226,16 +235,19 @@
oraub8 bytes_read, offset = 0;
oraub8 requested_len = read_length; /* this is by default */
oraub8 chars_read = 0;
- int is_clob = 0;
#else
int bytes_read, offset = 0;
int requested_len = read_length; /* this is by default */
#endif
+ int is_clob = 0;
+ sb4 bytes_per_char = 1;
*data_len = 0;
*data = NULL;
+
ctx.lob_len = data_len;
ctx.lob_data = data;
+ ctx.alloc_len = 0;
if (php_oci_lob_get_length(descriptor, &length TSRMLS_CC)) {
return 1;
@@ -272,9 +284,7 @@
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
- }
-#ifdef HAVE_OCI_LOB_READ2
- else {
+ } else {
ub2 charset_id = 0;
PHP_OCI_CALL_RETURN(connection->errcode, OCILobCharSetId,
(connection->env, connection->err, descriptor->descriptor, &charset_id));
@@ -291,6 +301,22 @@
}
if (is_clob) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCINlsNumericInfoGet,
(connection->env, connection->err, &bytes_per_char, OCI_NLS_CHARSET_MAXBYTESZ));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ php_oci_error(connection->err, connection->errcode
TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ } else {
+ /* BLOBs don't have encoding, so bytes_per_char == 1 */
+ }
+
+ ctx.alloc_len = (requested_len + 1) * bytes_per_char;
+ *data = ecalloc(bytes_per_char, requested_len + 1);
+
+#ifdef HAVE_OCI_LOB_READ2
+ if (is_clob) {
chars_read = requested_len;
bytes_read = 0;
} else {
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/php_oci8_int.h?r1=1.11.2.6.2.17&r2=1.11.2.6.2.18&diff_format=u
Index: php-src/ext/oci8/php_oci8_int.h
diff -u php-src/ext/oci8/php_oci8_int.h:1.11.2.6.2.17
php-src/ext/oci8/php_oci8_int.h:1.11.2.6.2.18
--- php-src/ext/oci8/php_oci8_int.h:1.11.2.6.2.17 Thu Mar 1 22:27:44 2007
+++ php-src/ext/oci8/php_oci8_int.h Thu Mar 29 09:33:03 2007
@@ -25,7 +25,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_oci8_int.h,v 1.11.2.6.2.17 2007/03/01 22:27:44 tony2001 Exp $ */
+/* $Id: php_oci8_int.h,v 1.11.2.6.2.18 2007/03/29 09:33:03 tony2001 Exp $ */
#if HAVE_OCI8
# ifndef PHP_OCI8_INT_H
@@ -134,6 +134,7 @@
typedef struct { /* php_oci_lob_ctx {{{ */
char **lob_data; /* address of pointer to LOB data */
ub4 *lob_len; /* address of LOB length variable (bytes) */
+ ub4 alloc_len;
} php_oci_lob_ctx; /* }}} */
typedef struct { /* php_oci_collection {{{ */
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/tests/pecl_bug10194.phpt?view=markup&rev=1.1
Index: php-src/ext/oci8/tests/pecl_bug10194.phpt
+++ php-src/ext/oci8/tests/pecl_bug10194.phpt
--TEST--
PECL Bug #10194 (segfault in Instant Client when memory_limit is reached inside
the callback)
--SKIPIF--
<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
--INI--
memory_limit=10M
--FILE--
<?php
require dirname(__FILE__).'/connect.inc';
require dirname(__FILE__).'/create_table.inc';
$ora_sql = "INSERT INTO
".$schema.$table_name." (clob)
VALUES (empty_clob())
";
$statement = oci_parse($c,$ora_sql);
oci_execute($statement);
$ora_sql = "SELECT clob FROM ".$schema.$table_name." FOR UPDATE";
$statement = oci_parse($c,$ora_sql);
oci_execute($statement, OCI_DEFAULT);
$row = oci_fetch_assoc($statement);
$string = str_repeat("test", 32768*4*4);
for ($i = 0; $i < 8; $i++) {
$row['CLOB']->write($string);
}
oci_commit($c);
$ora_sql = "SELECT clob FROM ".$schema.$table_name."";
$statement = oci_parse($c,$ora_sql);
oci_execute($statement);
$row = oci_fetch_assoc($statement);
var_dump(strlen($row['CLOB']->load())); /* here it should fail */
require dirname(__FILE__).'/drop_table.inc';
echo "Done\n";
?>
--EXPECTF--
Fatal error: Allowed memory size of 10485760 bytes exhausted at %s:%d (tried to
allocate %d bytes) in %s on line %d
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/tests/pecl_bug10194_blob.phpt?view=markup&rev=1.1
Index: php-src/ext/oci8/tests/pecl_bug10194_blob.phpt
+++ php-src/ext/oci8/tests/pecl_bug10194_blob.phpt
--TEST--
PECL Bug #10194 (segfault in Instant Client when memory_limit is reached inside
the callback)
--SKIPIF--
<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
--INI--
memory_limit=10M
--FILE--
<?php
require dirname(__FILE__).'/connect.inc';
require dirname(__FILE__).'/create_table.inc';
$ora_sql = "INSERT INTO
".$schema.$table_name." (blob)
VALUES (empty_blob())
";
$statement = oci_parse($c,$ora_sql);
oci_execute($statement);
$ora_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
$statement = oci_parse($c,$ora_sql);
oci_execute($statement, OCI_DEFAULT);
$row = oci_fetch_assoc($statement);
$string = str_repeat("test", 32768*4*4);
for ($i = 0; $i < 8; $i++) {
$row['BLOB']->write($string);
}
oci_commit($c);
$ora_sql = "SELECT blob FROM ".$schema.$table_name."";
$statement = oci_parse($c,$ora_sql);
oci_execute($statement);
$row = oci_fetch_assoc($statement);
var_dump(strlen($row['BLOB']->load())); /* here it should fail */
require dirname(__FILE__).'/drop_table.inc';
echo "Done\n";
?>
--EXPECTF--
Fatal error: Allowed memory size of %d bytes exhausted at %s:%d (tried to
allocate %d bytes) in %s on line %d
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php