tony2001                Thu Mar 29 09:30:25 2007 UTC

  Added files:                 
    /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:
  fix #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.26&r2=1.27&diff_format=u
Index: php-src/ext/oci8/oci8_lob.c
diff -u php-src/ext/oci8/oci8_lob.c:1.26 php-src/ext/oci8/oci8_lob.c:1.27
--- php-src/ext/oci8/oci8_lob.c:1.26    Mon Jan  1 09:29:26 2007
+++ php-src/ext/oci8/oci8_lob.c Thu Mar 29 09:30:25 2007
@@ -25,7 +25,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: oci8_lob.c,v 1.26 2007/01/01 09:29:26 sebastian Exp $ */
+/* $Id: oci8_lob.c,v 1.27 2007/03/29 09:30:25 tony2001 Exp $ */
 
 
 
@@ -161,7 +161,13 @@
        switch (piece)
        {
                case OCI_LAST_PIECE:
-                       *(ctx->lob_data) = erealloc(*(ctx->lob_data), (size_t) 
(*(ctx->lob_len) + lenp + TEXT_BYTES(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;
                        
@@ -174,14 +180,19 @@
 
                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;
 
                default:
                        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;
@@ -235,11 +246,13 @@
        int bytes_read, offset = 0;
        int requested_len = read_length; /* this is by default */
 #endif
+       sb4 bytes_per_char = 1;
 
        *data_len = 0;
        *data = NULL_ZSTR;
        ctx.lob_len = data_len;
        ctx.lob_data = &(data->s);
+       ctx.alloc_len = 0;
 
        if (php_oci_lob_get_length(descriptor, &length TSRMLS_CC)) {
                return 1;
@@ -282,6 +295,21 @@
                return 1;
        }
 
+       if (lob_type == OCI_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 + UBYTES(1)) * bytes_per_char;
+       data->s = ecalloc(bytes_per_char, requested_len + UBYTES(1));
+
 #ifdef HAVE_OCI_LOB_READ2
        if (lob_type == OCI_IS_CLOB) {
                chars_read = requested_len;
http://cvs.php.net/viewvc.cgi/php-src/ext/oci8/php_oci8_int.h?r1=1.33&r2=1.34&diff_format=u
Index: php-src/ext/oci8/php_oci8_int.h
diff -u php-src/ext/oci8/php_oci8_int.h:1.33 
php-src/ext/oci8/php_oci8_int.h:1.34
--- php-src/ext/oci8/php_oci8_int.h:1.33        Thu Mar  1 23:28:13 2007
+++ php-src/ext/oci8/php_oci8_int.h     Thu Mar 29 09:30:25 2007
@@ -25,7 +25,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: php_oci8_int.h,v 1.33 2007/03/01 23:28:13 tony2001 Exp $ */
+/* $Id: php_oci8_int.h,v 1.34 2007/03/29 09:30:25 tony2001 Exp $ */
 
 #if HAVE_OCI8
 # ifndef PHP_OCI8_INT_H
@@ -141,6 +141,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

Reply via email to