]> granicus.if.org Git - php/commitdiff
fix for bug# 35759
authorAndrey Hristov <andrey@php.net>
Thu, 22 Dec 2005 18:11:39 +0000 (18:11 +0000)
committerAndrey Hristov <andrey@php.net>
Thu, 22 Dec 2005 18:11:39 +0000 (18:11 +0000)
(mysqli_stmt_bind_result() makes huge allocation when column empty)
#this shows some leaks now, which has to be investigated but closes the
#bug report.

ext/mysqli/mysqli.c
ext/mysqli/mysqli_api.c
ext/mysqli/tests/bug35759.phpt [new file with mode: 0644]

index 7b44e9b9291c22c80231f210d1e678c055726bae..ec17c0c66f2976648ade383e7b6b6fcfbcf272eb 100644 (file)
@@ -155,11 +155,11 @@ static void mysqli_objects_destroy_object(void *object, zend_object_handle handl
                        MY_STMT *stmt = (MY_STMT *)my_res->ptr;
                        php_clear_stmt_bind(stmt);
                }
-       } else if (instanceof_function(intern->zo.ce, mysqli_result_class_entry TSRMLS_CC)) { /* stmt object */
+       } else if (instanceof_function(intern->zo.ce, mysqli_result_class_entry TSRMLS_CC)) { /* result object */
                if (my_res && my_res->ptr) {
                        mysql_free_result(my_res->ptr);
                }
-       } else if (instanceof_function(intern->zo.ce, mysqli_warning_class_entry TSRMLS_CC)) { /* stmt object */
+       } else if (instanceof_function(intern->zo.ce, mysqli_warning_class_entry TSRMLS_CC)) { /* warning object */
                if (my_res && my_res->ptr) {
                        php_clear_warnings((MYSQLI_WARNING *)my_res->info);
                }
@@ -459,7 +459,7 @@ PHP_MINIT_FUNCTION(mysqli)
        zend_hash_init(&mysqli_driver_properties, 0, NULL, NULL, 1);
        MYSQLI_ADD_PROPERTIES(&mysqli_driver_properties, mysqli_driver_property_entries);
        zend_hash_add(&classes, ce->name, ce->name_length+1, &mysqli_driver_properties, sizeof(mysqli_driver_properties), NULL);
-    ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
+       ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
 
        REGISTER_MYSQLI_CLASS_ENTRY("mysqli", mysqli_link_class_entry, mysqli_link_methods);
        ce = mysqli_link_class_entry;
@@ -469,7 +469,7 @@ PHP_MINIT_FUNCTION(mysqli)
 
        REGISTER_MYSQLI_CLASS_ENTRY("mysqli_warning", mysqli_warning_class_entry, mysqli_warning_methods);
        ce = mysqli_warning_class_entry;
-    ce->ce_flags |= ZEND_ACC_FINAL_CLASS | ZEND_ACC_PROTECTED;
+       ce->ce_flags |= ZEND_ACC_FINAL_CLASS | ZEND_ACC_PROTECTED;
        zend_hash_init(&mysqli_warning_properties, 0, NULL, NULL, 1);
        MYSQLI_ADD_PROPERTIES(&mysqli_warning_properties, mysqli_warning_property_entries);
        zend_hash_add(&classes, ce->name, ce->name_length+1, &mysqli_warning_properties, sizeof(mysqli_warning_properties), NULL);
index 3178ed8ee79d5e95807d23fb0855c3aefe4d17b0..d814c9b090222f105d178baedf01ee8cc68f2640 100644 (file)
@@ -323,20 +323,26 @@ PHP_FUNCTION(mysqli_stmt_bind_result)
 #ifdef FIELD_TYPE_NEWDECIMAL
                        case MYSQL_TYPE_NEWDECIMAL:
 #endif
+                       {
+                               ulong tmp;
                                stmt->result.buf[ofs].type = IS_STRING;
                                /*
                                        If the user has called $stmt->store_result() then we have asked
                                        max_length to be updated. this is done only for BLOBS because we don't want to allocate
                                        big chunkgs of memory 2^16 or 2^24 
                                */
-                               if (stmt->stmt->fields[ofs].max_length == 0) {
+                               if (stmt->stmt->fields[ofs].max_length == 0 &&
+                                       !mysql_stmt_attr_get(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp) && !tmp)
+                               {
                                        stmt->result.buf[ofs].buflen =
                                                (stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256;
                                } else {
                                        /*
                                                the user has called store_result(). if he does not there is no way to determine the
+                                               libmysql does not allow us to allocate 0 bytes for a buffer so we try 1
                                        */
-                                       stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length;
+                                       if (!(stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length))
+                                               ++stmt->result.buf[ofs].buflen;
                                }
                                stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
                                bind[ofs].buffer_type = MYSQL_TYPE_STRING;
@@ -345,6 +351,7 @@ PHP_FUNCTION(mysqli_stmt_bind_result)
                                bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
                                bind[ofs].length = &stmt->result.buf[ofs].buflen;
                                break;
+                       }
                        default:
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Server returned unknown type %ld. Probably your client library is incompatible with the server version you use!", col_type);
                                break;
diff --git a/ext/mysqli/tests/bug35759.phpt b/ext/mysqli/tests/bug35759.phpt
new file mode 100644 (file)
index 0000000..5f67a76
--- /dev/null
@@ -0,0 +1,44 @@
+--TEST--
+bug #35759 : mysqli_stmt_bind_result() makes huge allocation when column empty
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+
+$sql=<<<EOSQL
+CREATE TABLE blobby (
+  a1 MEDIUMBLOB NOT NULL,
+
+
+EOSQL;
+       include "connect.inc";
+       $col_num= 1000;
+
+       $mysql = new mysqli($host, $user, $passwd, "test");
+       $mysql->query("DROP TABLE IF EXISTS blobby");
+       $create = "CREATE TABLE blobby (a0 MEDIUMBLOB NOT NULL DEFAULT ''";
+       $i= 0;
+       while (++$i < $col_num) {
+               $create .= ", a$i MEDIUMBLOB NOT NULL DEFAULT ''";
+       }
+        $create .= ")";        
+          
+        $mysql->query($create);
+       $mysql->query("INSERT INTO blobby (a0) VALUES ('')");
+       
+       $stmt = $mysql->prepare("SELECT * FROM blobby");
+       $stmt->execute();
+       $stmt->store_result();
+       $params= array_pad(array(), $col_num, "");
+       call_user_func_array(array($stmt, "bind_result"), $params);
+       $stmt->fetch();
+       
+       $stmt->close();
+
+       $mysql->query("DROP TABLE blobby");
+
+       $mysql->close();
+       echo "OK\n";
+?>
+--EXPECT--
+OK