[CONC-131] Memory leak in mysql_close() with MYSQL_OPT_NONBLOCK Created: 2015-06-14  Updated: 2015-07-30  Resolved: 2015-06-26

Status: Closed
Project: MariaDB Connector/C
Component/s: None
Affects Version/s: 2.1
Fix Version/s: 3.0.0, 2.2.0

Type: Bug Priority: Major
Reporter: René Cannaò Assignee: Georg Richter
Resolution: Fixed Votes: 0
Labels: None


 Description   

When a mysql connection is created and is set to not blocking, mysql_close() doesn't free the memory associate with async causing a severe memory leak.

Depending from the the speed of your CPU and your available memory, the follow code can eat all available memory in just few seconds:

#include <mysql.h>
#include <stdio.h>
int main() {
  while(1) {
  MYSQL *mysql=mysql_init(NULL);
  mysql_options(mysql, MYSQL_OPT_NONBLOCK, 0);  // this line triggers the bug
  mysql_close(mysql);
  }
  return 0;
}



 Comments   
Comment by René Cannaò [ 2015-06-14 ]

Quick patch in mysql_close_options() :

2194a2195,2202
>     {
>       struct mysql_async_context *ctxt;
>       if ((ctxt = mysql->options.extension->async_context) != 0)
>       {
>         my_context_destroy(&ctxt->async_context);
>         my_free((gptr)ctxt, MYF(0));
>       }
>     }

Comment by René Cannaò [ 2015-07-30 ]

Because non blocking API is implemented using coroutine, it is possible that the stack is freed while being used by another function. This will lead to invalid read/write on memory already freed.
I think this is a better patch:

@@ -2192,6 +2192,16 @@
     my_free(mysql->options.extension->ssl_crlpath, MYF(MY_ALLOW_ZERO_PTR));
     if(hash_inited(&mysql->options.extension->connect_attrs))
       hash_free(&mysql->options.extension->connect_attrs);
+    {
+     struct mysql_async_context *ctxt;
+     if ((ctxt = mysql->options.extension->async_context) != 0) {
+       if (ctxt->active==0) {
+         my_context_destroy(&ctxt->async_context);
+         my_free((gptr)ctxt, MYF(0));
+         mysql->options.extension->async_context=NULL;
+       }
+     }
+   }
   }
   my_free((gptr)mysql->options.extension, MYF(MY_ALLOW_ZERO_PTR));
   /* clear all pointer */

Generated at Thu Feb 08 03:03:06 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.