From: Andrey Hristov Date: Thu, 22 Dec 2005 18:11:39 +0000 (+0000) Subject: fix for bug# 35759 X-Git-Tag: php-5.1.2RC2~108 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1c0971f3ce660d0a613709d086e6154387f33ef3;p=php fix for bug# 35759 (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. --- diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 7b44e9b929..ec17c0c66f 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -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); diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 3178ed8ee7..d814c9b090 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -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 index 0000000000..5f67a76247 --- /dev/null +++ b/ext/mysqli/tests/bug35759.phpt @@ -0,0 +1,44 @@ +--TEST-- +bug #35759 : mysqli_stmt_bind_result() makes huge allocation when column empty +--SKIPIF-- + +--FILE-- +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