Bug #58497 mysql client crashes due to unitialized string buffer in term.c
Submitted: 25 Nov 2010 15:38 Modified: 21 Mar 2012 19:06
Reporter: Werner Ott Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Server: Compiling Severity:S1 (Critical)
Version:5.1.53 OS:Linux
Assigned to: CPU Architecture:Any
Tags: segfault

[25 Nov 2010 15:38] Werner Ott
Description:
When compiling from source, the resulting mysql client binary successfuly connects to any mysql server but then segfaults (crashes) after supplying the credentials (as also described in Bug #45562)

How to repeat:
Environment:
------------
openSUSE Linux 11.0/11.1 on x86_64
Linux 2.6.27.7-9-default
gcc 4.3.2 with glibc 2.9
libncurses 5.6

How to repeat:
--------------
Extract 5.1.51 tar.gz sources to build directory and cd into this directory.

Then:
 $ CPPFLAGS="-m64" \
 LDFLAGS="-L/lib64 -L/usr/lib64 -L/usr/lib -m64"  \
 CFLAGS="-O3 -m64" \
 CXX=gcc \
 CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti -m64" \
 --enable-local-infile \
 --enable-shared \
 --enable-static \
 --enable-thread-safe-client \
 --exec-prefix=/usr \
 --infodir=/usr/share/info \
 --libdir=/usr/lib64 \
 --localstatedir=/home/mysql \
 --mandir=/usr/share/man \
 --prefix=/usr \
 --sysconfdir=/etc \
 --with-comment="built 25 NOV 2010 on Linux 2.6.27.7-9-default; gcc 4.3.2; libncurses 5.6" \
 --with-extra-charsets=complex \
 --with-mysqld-user=mysql \
 --with-named-curses-libs=/lib64/libncurses.so.5.6 \
 --with-tcp-port=3306

 $ make
 $ make install

Start the server (without any problem), then try to access server with the client:
 $ mysql -uroot -pMYPASS

leads to:

 Welcome to the MySQL monitor.  Commands end with ; or \g.
 Your MySQL connection id is 8
 Server version: 5.1.51 built 25 NOV 2010 on Linux 2.6.27.7-9-default; gcc 4.3.2; libncurses 5.6

 Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
 This software comes with ABSOLUTELY NO WARRANTY. This is free software,
 and you are welcome to modify and redistribute it under the GPL v2 license

 Segmentation fault

Debugging with gdb:
-------------------
 $ gdb /usr/bin/mysql
 Starting program: /usr/bin/mysql
 [Thread debugging using libthread_db enabled]
 (gdb) run -uroot -pMYPASS
 Starting program: /usr/bin/mysql -uroot -pMYPASS

 [Thread debugging using libthread_db enabled]
 Welcome to the MySQL monitor.  Commands end with ; or \g.
 Your MySQL connection id is 7
 Server version: 5.1.51 built 25 NOV 2010 on Linux 2.6.27.7-9-default; gcc 4.3.2; libncurses 5.6

 Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
 This software comes with ABSOLUTELY NO WARRANTY. This is free software,
 and you are welcome to modify and redistribute it under the GPL v2 license

 Program received signal SIGSEGV, Segmentation fault.
 0x000000000041fdc2 in term_alloc ()
 Current language:  auto; currently asm

The backtrace then shows:
-------------------------
 #0  0x000000000041fdc2 in term_alloc ()
 #1  0x0000000000421325 in term_set ()
 #2  0x0000000000421600 in term_init ()
 #3  0x0000000000426bae in el_init ()
 #4  0x0000000000419671 in rl_initialize ()
 #5  0x000000000041a2bd in read_history ()
 #6  0x0000000000413dd8 in main ()

Suggested fix:
Running a mysql client on the exact same machine but compiled with gcc 4.2.x on another machine (also openSUSE, but older distro) does NOT segfault. This strongly points into the direction of a GCC compiler issue.

Regardless of which configure settings were used, a gcc 4.3.x compiled client binary always crashes while the same build with a gcc 4.2.x is not crashing.

Suggested fix: make sources compatible with gcc 4.3 or supply configure parameter to be used with gcc 4.3
[27 Nov 2010 13:23] Sveta Smirnova
Thank you for the report.

I can not repeat described behavior. Please try with current version 5.1.53 and if problem still exists try with newer version of gcc and inform us about results.
[7 Dec 2010 9:31] Werner Ott
Retried on openSUSE 11.0 and 11.1 x86_64 using

(*) gcc 4.4.5 
(*) mysql 5.1.53

still showed the same result.

mysql client program crashes (segfault) as soon as it connects to any MySQL 5.0 or 5.1 server.
[7 Dec 2010 10:19] Werner Ott
Introduction:
-------------
Already filed for 5.1.35, this bug still is in 5.1.53!

This error, as opposed to what I've written earlier, has NOTHING to do with the compiler version used. It is an 

How to reproduce:
-----------------
This segfault is caused by the use of an unitialized buffer in ./cmd-line-utils/libedit/term.c

The content of this buffer is arbitrary (as it isn't initialized) and may thus be non-reproducable in other environments.

"Stack trace" in term.c:
------------------------
904:  buf = array[2048];
914:  area = pointer to buf; // buf still uninitalized!
959:  term_alloc(..., area);
400:  clen = strlen(cap);    // unpredictable!
407:  strcpy unitialized buffer to other buffer  // segfaults!

How to fix:
-----------
(Credits go to Bart Kedryna, see Bug 45562)

Since function term_set() allocates a char buffer which it doesn't do
anything with, it contains possibly junk. This potentially junk containing buffer is passed to function term_alloc(). Function term_alloc() then tries to read the contents of this pointer and is segfaulting.

Since this buffer is not even initialized, it doesn't contain anything useful, and since it's passed to term_alloc() as const, it can't be written to by term_alloc(). 

The fix is to completely comment it out (line 904) and set the area pointer to NULL instead of buf (in line 914):

904://      char buf[TC_BUFSIZE];
914:        area = NULL;
[14 Dec 2010 19:15] Sveta Smirnova
Thank you for the feedback.

Please send output of command \s of mysql command line client.
[15 Jan 2011 0:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[19 Mar 2012 2:13] Eric Batchelor
Just wanted to comment I ran across this in version 5.1.61, and a fix that worked for me. As best I can tell it's the same problem.

I'm using Ubuntu 10.04.4 LTS, 64 bit version.
GCC 4.4.3

I ran ./configure, it balked about a terminal library.
I installed the package libncursesw5-dev, thinking I might want wide-char support, and compilation succeeded, but the resultant mysql bin segfaulted. I think it's simply a package problem where the proper curses header files were not being included and this was not detected by the configure script.

The following compile warnings hint at the cause of the segfault:

terminal.c: In function ‘terminal_set’:
terminal.c:925: warning: passing argument 3 of ‘terminal_alloc’ makes pointer from integer without a cast
terminal.c:327: note: expected ‘const char *’ but argument is of type ‘int’

The relevant code:
terminal_alloc(el, t,  tgetstr(strchr(t->name, *t->name), &area)  );
(This code is valid, btw, notice that &area is being passed to tgetstr, not terminal_alloc. It's fine if area=buf points to an unitinalized area.)

tgetstr is supposed to return a char*, NOT an int, so clearly something is wrong, like a missing header file. Using a 32 bit int as a 64 bit address of course is completely bogus and generates an invalid address which causes a segfault. The generated assembler code is movslq %eax,%rdx which sign extends the top bit of 32 bit eax register to 64 bit rdx, which is not at all what we want.

What fixed it for me:

I uninstalled libncursesw5-dev and installed libncurses5-dev (non-wide char), ./configure, make, and the resultant mysql binary executes fine.
No warnings were generated for the same section of code, and stepping through with a debugger confirmed that the return value of tgetstr was being interpreted as a 64 bit address, not a 32 bit int.
[19 Mar 2012 21:47] Sveta Smirnova
Eric,

thank you for the feedback.

I can not repeat described behavior with libncursesw as well. Please send full configuration line you use. Do you link with static or dynamic curses library?
[21 Mar 2012 5:51] Eric Batchelor
My configure line was simply ./configure with no additional arguments.
I believe it is dynamically linked.
ldd shows for curses:
libncursesw.so.5 => /lib/libncursesw.so.5 (0x00007fa824e82000)
[21 Mar 2012 19:06] Sveta Smirnova
Thank you for the feedback.

I still can not repeat described behavior. So closing report as "Can't repeat". As problem seems to be ncurses library workaround can be use different version of the library.
[27 Aug 2012 21:55] Xun Tang
I have experienced the same crash. When I run the cmake command like below, The HAVE_CURSES_H is not defined and curses.h is not included in terminal.c. Then the built bin/mysql will crash. I have to explicitly define HAVE_CURSES_H. I can't find where the configure is broken.

cmake . -DCURSES_LIBRARY=/usr/lib64/libcurses.so.1 -DCURSES_INCLUDE_PATH=/usr/include/curses/
[3 Sep 2012 17:35] Sveta Smirnova
Xun Tang,

thank you for the feedback. I still can not repeat this issue with ncurses 5.7 Looks like version matters.