Bug #62245 mysql_stmt_prepare() would lead to memory leaks in libmysqld
Submitted: 24 Aug 2011 5:20 Modified: 20 Feb 2012 18:46
Reporter: Qi Zhou Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Embedded Library ( libmysqld ) Severity:S2 (Serious)
Version:5.5.15, 5.5.22 OS:Any
Assigned to: CPU Architecture:Any
Tags: mysql_stmt_prepare mem leaks

[24 Aug 2011 5:20] Qi Zhou
Description:
mysql_stmt_prepare() would call emb_read_prepare_result(), there is a bug will lead to memory leak:
 235 static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
 236 {
 237   THD *thd= (THD*) mysql->thd;
 238   MYSQL_DATA *res;
 239 
 240   stmt->stmt_id= thd->client_stmt_id;
 241   stmt->param_count= thd->client_param_count;
 242   stmt->field_count= 0;
 243   mysql->warning_count= thd->warning_info->statement_warn_count();
 244 
 245   if (thd->first_data)
 246   {
 247     if (emb_read_query_result(mysql))
 248       return 1;
 249     stmt->field_count= mysql->field_count;
 250     mysql->status= MYSQL_STATUS_READY;
 251     res= thd->cur_data;                                                                                                                                                                                   
 252     thd->cur_data= NULL;
 253     if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
 254       mysql->server_status|= SERVER_STATUS_IN_TRANS;
 255 
 256     stmt->fields= mysql->fields;
 257     stmt->mem_root= res->alloc;
 258     mysql->fields= NULL;
 259     my_free(res);
 260   }
 261 
 262   return 0;
 263 }

note line 257, the old mem_root is not freed yet.
(
although you called:
 free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
in the mysql_stmt_prepare(), but the prealloced memory would be reserved.
)

How to repeat:
you can run any case using mysql_stmt_prepare() and check it with valgrind.
[20 Feb 2012 18:46] Sveta Smirnova
Thank you for the report.

Verified as described:

==2590== 2,064 bytes in 1 blocks are definitely lost in loss record 3 of 3
==2590==    at 0x4A05FDE: malloc (vg_replace_malloc.c:236)
==2590==    by 0x5462A9: my_malloc (my_malloc.c:38)
==2590==    by 0x532974: init_alloc_root (my_alloc.c:63)
==2590==    by 0x43AA7F: mysql_stmt_init (libmysql.c:1500)
==2590==    by 0x437A43: main (bug62136.cpp:53)

To repeat compile test case from bug 62136, then run it as: valgrind --leak-check=full ./bug62136
[20 Feb 2012 18:49] Sveta Smirnova
Problem is not repeatable without embedded server.