From: Alexander Nozdrin Date: May 5 2011 12:34pm Subject: bzr commit into mysql-5.5 branch (alexander.nozdrin:3490) Bug#12374486 List-Archive: http://lists.mysql.com/commits/136748 X-Bug: 12374486 Message-Id: <201105051234.p45CYd73025504@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2639273376419827867==" --===============2639273376419827867== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/alik/MySQL/bzr/00/bug12374486/mysql-5.5-bug12374486/ based on revid:alexander.nozdrin@stripped 3490 Alexander Nozdrin 2011-05-05 Patch for Bug#12374486 - SEVERE MEMORY LEAK IN PREPARED STATEMENTS THAT CALL STORED PROCEDURES. The bug was introduced by WL#4435. The problem was that if a stored procedure generated a few result sets with different set of columns, a new memory would be allocated after every EXECUTE for every result set. The fix is to introduce a new memory root in scope of MYSQL_STMT, and to store result-set metadata in that memory root. modified: include/mysql.h include/mysql.h.pp libmysql/libmysql.c === modified file 'include/mysql.h' --- a/include/mysql.h 2010-11-20 22:56:09 +0000 +++ b/include/mysql.h 2011-05-05 12:34:34 +0000 @@ -573,6 +573,8 @@ typedef struct st_mysql_bind } MYSQL_BIND; +struct st_mysql_stmt_extension; + /* statement handler */ typedef struct st_mysql_stmt { @@ -618,7 +620,7 @@ typedef struct st_mysql_stmt metadata fields when doing mysql_stmt_store_result. */ my_bool update_max_length; - void *extension; + struct st_mysql_stmt_extension *extension; } MYSQL_STMT; enum enum_stmt_attr_type === modified file 'include/mysql.h.pp' --- a/include/mysql.h.pp 2011-02-11 14:00:09 +0000 +++ b/include/mysql.h.pp 2011-05-05 12:34:34 +0000 @@ -512,6 +512,7 @@ typedef struct st_mysql_bind my_bool is_null_value; void *extension; } MYSQL_BIND; +struct st_mysql_stmt_extension; typedef struct st_mysql_stmt { MEM_ROOT mem_root; @@ -541,7 +542,7 @@ typedef struct st_mysql_stmt unsigned char bind_result_done; my_bool unbuffered_fetch_cancelled; my_bool update_max_length; - void *extension; + struct st_mysql_stmt_extension *extension; } MYSQL_STMT; enum enum_stmt_attr_type { === modified file 'libmysql/libmysql.c' --- a/libmysql/libmysql.c 2011-03-08 17:39:25 +0000 +++ b/libmysql/libmysql.c 2011-05-05 12:34:34 +0000 @@ -94,6 +94,11 @@ sig_handler my_pipe_sig_handler(int sig) static my_bool mysql_client_init= 0; static my_bool org_my_init_done= 0; +typedef struct st_mysql_stmt_extension +{ + MEM_ROOT fields_mem_root; +} MYSQL_STMT_EXT; + /* Initialize the MySQL client library @@ -1497,8 +1502,21 @@ mysql_stmt_init(MYSQL *mysql) stmt->read_row_func= stmt_read_row_no_result_set; stmt->prefetch_rows= DEFAULT_PREFETCH_ROWS; strmov(stmt->sqlstate, not_error_sqlstate); + /* The rest of statement members was bzeroed inside malloc */ + stmt->extension= alloc_root(&stmt->mem_root, sizeof (MYSQL_STMT_EXT)); + + if (!stmt->extension) + { + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); + DBUG_RETURN(0); + } + + bzero(stmt->extension, sizeof (MYSQL_STMT_EXT)); + + init_alloc_root(&stmt->extension->fields_mem_root, 2048, 0); + DBUG_RETURN(stmt); } @@ -1571,6 +1589,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, con stmt->bind_param_done= stmt->bind_result_done= FALSE; stmt->param_count= stmt->field_count= 0; free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC)); + free_root(&stmt->extension->fields_mem_root, MYF(0)); int4store(buff, stmt->stmt_id); @@ -1631,21 +1650,21 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, con static void alloc_stmt_fields(MYSQL_STMT *stmt) { MYSQL_FIELD *fields, *field, *end; - MEM_ROOT *alloc= &stmt->mem_root; + MEM_ROOT *fields_mem_root= &stmt->extension->fields_mem_root; MYSQL *mysql= stmt->mysql; - DBUG_ASSERT(mysql->field_count); + DBUG_ASSERT(stmt->field_count); - stmt->field_count= mysql->field_count; + free_root(fields_mem_root, MYF(0)); /* Get the field information for non-select statements like SHOW and DESCRIBE commands */ - if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc, + if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(fields_mem_root, sizeof(MYSQL_FIELD) * stmt->field_count)) || - !(stmt->bind= (MYSQL_BIND *) alloc_root(alloc, + !(stmt->bind= (MYSQL_BIND *) alloc_root(fields_mem_root, sizeof(MYSQL_BIND) * stmt->field_count))) { @@ -1658,18 +1677,36 @@ static void alloc_stmt_fields(MYSQL_STMT field && fields < end; fields++, field++) { *field= *fields; /* To copy all numeric parts. */ - field->catalog= strmake_root(alloc, fields->catalog, + field->catalog= strmake_root(fields_mem_root, + fields->catalog, fields->catalog_length); - field->db= strmake_root(alloc, fields->db, fields->db_length); - field->table= strmake_root(alloc, fields->table, fields->table_length); - field->org_table= strmake_root(alloc, fields->org_table, + field->db= strmake_root(fields_mem_root, + fields->db, + fields->db_length); + field->table= strmake_root(fields_mem_root, + fields->table, + fields->table_length); + field->org_table= strmake_root(fields_mem_root, + fields->org_table, fields->org_table_length); - field->name= strmake_root(alloc, fields->name, fields->name_length); - field->org_name= strmake_root(alloc, fields->org_name, + field->name= strmake_root(fields_mem_root, + fields->name, + fields->name_length); + field->org_name= strmake_root(fields_mem_root, + fields->org_name, fields->org_name_length); - field->def= fields->def ? strmake_root(alloc, fields->def, - fields->def_length) : 0; - field->def_length= field->def ? fields->def_length : 0; + if (fields->def) + { + field->def= strmake_root(fields_mem_root, + fields->def, + fields->def_length); + field->def_length= fields->def_length; + } + else + { + field->def= NULL; + field->def_length= 0; + } field->extension= 0; /* Avoid dangling links. */ field->max_length= 0; /* max_length is set in mysql_stmt_store_result() */ } @@ -2387,6 +2424,9 @@ static void reinit_result_set_metadata(M prepared statements can't send result set metadata for these queries on prepare stage. Read it now. */ + + stmt->field_count= stmt->mysql->field_count; + alloc_stmt_fields(stmt); } else @@ -2404,7 +2444,7 @@ static void reinit_result_set_metadata(M previous branch always works. TODO: send metadata only when it's really necessary and add a warning 'Metadata changed' when it's sent twice. - */ + */ update_stmt_fields(stmt); } } @@ -4603,6 +4643,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_S int rc= 0; DBUG_ENTER("mysql_stmt_close"); + free_root(&stmt->extension->fields_mem_root, MYF(0)); free_root(&stmt->result.alloc, MYF(0)); free_root(&stmt->mem_root, MYF(0)); @@ -4805,16 +4846,13 @@ int STDCALL mysql_stmt_next_result(MYSQL stmt->state= MYSQL_STMT_EXECUTE_DONE; stmt->bind_result_done= FALSE; + stmt->field_count= mysql->field_count; if (mysql->field_count) { alloc_stmt_fields(stmt); prepare_to_fetch_result(stmt); } - else - { - stmt->field_count= mysql->field_count; - } DBUG_RETURN(0); } --===============2639273376419827867== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/alexander.nozdrin@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: alexander.nozdrin@stripped\ # lyexykp9najusjcs # target_branch: file:///home/alik/MySQL/bzr/00/bug12374486/mysql-5.5-\ # bug12374486/ # testament_sha1: 5ac524203fab52ff1b4e05ebc7c666b5c347e257 # timestamp: 2011-05-05 16:34:38 +0400 # base_revision_id: alexander.nozdrin@stripped\ # rimt2b82bibh5vgm # # Begin bundle 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 --===============2639273376419827867==--