Bug #7344 Use of unallocated memory causing crash in clients
Submitted: 16 Dec 2004 8:31 Modified: 25 Apr 2005 23:10
Reporter: Jim Perry Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:4.1.7 OS:Linux (Linux)
Assigned to: Alexey Botchkov CPU Architecture:Any

[16 Dec 2004 8:31] Jim Perry
Description:
mysql_server_end() calls my_end(), which deallocates all memory allocated by my_once_alloc().  This includes charset information loaded from the various XML files in charset.c.  free_charsets(), however, is never called.  As a result, if the library is reinitialized using mysql_server_init(), the charset data will *not* be reinitialized and all_charsets will contain pointers to unallocated memory (as well as valid pointers to the compiled-in charset data).

While using these embedded server calls in a normal library seems a little silly, Qt 3.3.3 calls them regularly (causing a number of Qt applications to crash).

How to repeat:
Call mysql_server_init(), use the library, call mysql_server_end(), use memory until you happen to overwrite the charset data, then reinitialize the library and try to use it.

Suggested fix:
Call free_charsets() in my_end().
[18 Dec 2004 0:23] MySQL Verification Team
Could you please provide a test code that can makes more easy to
understand what you meant in your description ?.

Thanks in advance.
[18 Dec 2004 1:32] Jim Perry
The computer I was having this problem on is being moved, so I can't actually write out some test code, but the basic idea is:

int main()
{
   mysql_server_init( 0, NULL, NULL );
   mysql_server_end();
   mysql_server_init( 0, NULL, NULL );
   // all_charsets now contains pointers to unalllocated memory
   // do some malloc()s until we happen to reallocate and overwrite this memory
   mysql_real_connect( ...);  // this call will crash in get_charset_by_name
}
[30 Dec 2004 21:56] Jim Perry
Sorry, left something out of my example code.  The charset list has to be initialized, and I think it's not initialized until you use a mysql call (could be wrong about this).  This code should crash when run with Purify or something similar:

int main()
{
   mysql_server_init( 0, NULL, NULL );
   mysql_real_connect( ... );
   mysql_server_end();
   mysql_server_init( 0, NULL, NULL );
   // all_charsets now contains pointers to unalllocated memory
   // do some malloc()s until we happen to reallocate and overwrite this memory
   mysql_real_connect( ...);  // this call will crash in get_charset_by_name
}
[11 Jan 2005 16:31] Aleksey Kishkin
testcase.

Attachment: test7344.c (text/x-csrc), 918 bytes.

[11 Jan 2005 16:35] Aleksey Kishkin
add some test case according to your description. It looks like all_charsets _is_ initialized. Could you please check this testcase?
[11 Jan 2005 18:27] Hartmut Holzgraefe
test code showing mysql_embedded: File '(built-in)' not found (Errcode: 2)

Attachment: testprog.c (text/plain), 1.22 KiB.

[11 Jan 2005 18:29] Hartmut Holzgraefe
when testing this with the code i just attached i get:

 round 1
 round 2 
 mysql_embedded: File '(built-in)' not found (Errcode: 2)
 
looks like

./myisam/ft_stopwords.c:106:    ft_stopword_file="(built-in)"; /* for SHOW VARIABLES */

causes it

on round 1 ft_stopword_file is unset so the built in default is used

on round 2 ft_stopword_file is "(built-in)" but there is obviously no file by that name
[15 Feb 2005 1:00] Jim Perry
Apologies; I haven't had the time to look over the code again.  I'm not sure whether it makes a difference or not, but I actually wasn't compiling an embedded version.  I was compiling a fairly standard Linux version.  In particular, it was crashing when used with MythTV (which uses QT in a way that calls server_init and _done in the way I mentioned previously).  

It's been a while since I looked at the source, but I seem to recall that all_charsets or something similar was allocated during the first call (or init), and that the memory was freed in the server_done call in my_end() or something similar.  However, an init flag which marks the memory as freed is not used.

I found the patch that I used at the time.  Sorry that I can't be any more specific, but I don't have much free time right now.  Hopefully the patch will help elucidate the problem (if it hasn't been fixed already).  It's not a clean way of fixing it, but I was in a rush, and it worked like a charm.

> I managed to get MythTV to play nice with MySQL 4.1.7.  I was having some
> horrific instability as well, and after about 6 years of debugging found
> the bug.  It's actually a mysql bug, believe it or not.
> 
> Solution: edit libmysql/my_init.c
> search for "my_once_free" (it only occurs once)
> add "free_charsets();" immediately before it.
> recompile, etc etc.
[16 Feb 2005 2:39] Jim Perry
Here's a stack trace that I shamelessly borrowed from someone having an identical problem.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1242564896 (LWP 18431)]
0xb5afb720 in my_strcasecmp_8bit () from /usr/lib/libmysqlclient.so.14

Thread 1 (Thread -1242564896 (LWP 18431)):
#0  0xb5afb720 in my_strcasecmp_8bit () from /usr/lib/libmysqlclient.so.14
No symbol table info available.
#1  0xb5af1786 in get_charset_number () from /usr/lib/libmysqlclient.so.14
No symbol table info available.
#2  0xb5af1b5c in get_charset_by_csname () from /usr/lib/libmysqlclient.so.14
No symbol table info available.
#3  0xb5b0d9de in mysql_real_connect () from /usr/lib/libmysqlclient.so.14
No symbol table info available.
#4  0xb5bf88ed in QMYSQLDriver::open ()
   from /opt/qt/plugins/sqldrivers/libqsqlmysql.so
No symbol table info available.
[18 Feb 2005 11:01] Alexey Botchkov
bk commit - 4.1 tree (hf:1.2182) BUG#7344
[22 Feb 2005 21:06] Alexey Botchkov
Some variables wasn't restored to their initial state in mysql_server_end
It doesn't affect usual server, but made impossible new mysql_server_start in embedded one.

Pushed in 4.1.11
[22 Feb 2005 21:16] Paul DuBois
Noted in 4.1.11 changelog.
[21 Mar 2005 0:34] Boleslaw Ciesielski
Can someone who has access to bk post the actual patch that was applied to fix this bug? I downloaded the nightly snapshot and compared with 4.1.10a but I still couldn't figure out the actual fix. Thank you!
[21 Mar 2005 7:50] Sergei Golubchik
http://lists.mysql.com/search.php?q=7344&list=internals&m=o&begin=90
[21 Mar 2005 16:11] Boleslaw Ciesielski
Thank you. I applied the patch to 4.1.10a sources (no conflicts) and rebuilt, but the problem still persists when running MythTV 0.17. I get the same crash and stack trace as posted above. 

Has anyone verified the fix with MythTV?

Thanks
[21 Mar 2005 22:46] Boleslaw Ciesielski
So the checked-in fix does not work with MythTV but the following hack that Jim Perry mentions above does work (but the code has moved since then):

--- 1.39/mysys/my_init.c        2005-02-28 04:59:41 -05:00
+++ edited/mysys/my_init.c      2005-03-21 14:42:17 -05:00
@@ -140,6 +140,7 @@
       DBUG_PRINT("error",("%s",errbuff[0]));
     }
   }
+  free_charsets();
   my_once_free();
   if (infoflag & MY_GIVE_INFO || info_file != stderr)
   {
[1 Apr 2005 21:15] Boleslaw Ciesielski
Can this bug be reopened given that it's not really fixed?
Thanks
[18 Apr 2005 14:27] MySQL Verification Team
Looking your code descriptions:

int main()
{
   mysql_server_init( 0, NULL, NULL );
   mysql_server_end();
   mysql_server_init( 0, NULL, NULL );
   // all_charsets now contains pointers to unalllocated memory
   // do some malloc()s until we happen to reallocate and overwrite this memory
   mysql_real_connect( ...);  // this call will crash in get_charset_by_name
}

The embedded server is started/stopped and re-started in the same
process. Then my question is: do you have the InnoDB storage engine
enabled ?. 

Also the category of this bug report isn't embedded server library ?

Thanks in advance.
[18 Apr 2005 17:05] Jim Perry
Yes, I am using InnoDB.  I'm not using the embedded server -- this is a compile for a standard Linux library.  I am aware that calling init/done is pointless in this case, but (as I mentioned) a number of applications do so anyway.
[21 Apr 2005 6:09] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/24183
[21 Apr 2005 6:10] Alexey Botchkov
Additional fix sent
[25 Apr 2005 23:10] Paul DuBois
Additional fix noted in 4.1.12 changelog.