From: Alexander Nozdrin Date: May 5 2011 6:55am Subject: bzr commit into mysql-5.5 branch (alexander.nozdrin:3490) Bug#12374486 List-Archive: http://lists.mysql.com/commits/136708 X-Bug: 12374486 Message-Id: <201105050655.p456txjj031350@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============7950782356353497568==" --===============7950782356353497568== 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 06:55:53 +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 06:55:53 +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 06:55:53 +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,19 @@ 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)); + DBUG_RETURN(stmt); } @@ -1571,6 +1587,8 @@ 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)); + if (alloc_root_inited(&stmt->extension->fields_mem_root)) + free_root(&stmt->extension->fields_mem_root, MYF(MY_KEEP_PREALLOC)); int4store(buff, stmt->stmt_id); @@ -1631,21 +1649,24 @@ 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; + if (alloc_root_inited(&stmt->extension->fields_mem_root)) + free_root(&stmt->extension->fields_mem_root, MYF(0)); + + init_alloc_root(&stmt->extension->fields_mem_root, 2048, 2048); /* 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 +1679,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 +2426,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 +2446,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 +4645,9 @@ my_bool STDCALL mysql_stmt_close(MYSQL_S int rc= 0; DBUG_ENTER("mysql_stmt_close"); + if (alloc_root_inited(&stmt->extension->fields_mem_root)) + 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 +4850,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); } --===============7950782356353497568== 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\ # 8npzausp47pdnm3b # target_branch: file:///home/alik/MySQL/bzr/00/bug12374486/mysql-5.5-\ # bug12374486/ # testament_sha1: 4b601a2feb00ff519b16296d0d54e5e4159185e5 # timestamp: 2011-05-05 10:55:56 +0400 # base_revision_id: alexander.nozdrin@stripped\ # rimt2b82bibh5vgm # # Begin bundle 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 vMswzl/Q3O4/4i7kinChIU9XQ4Y= --===============7950782356353497568==--