Bug #6413 Purify ABR on mysql_real_connect
Submitted: 3 Nov 2004 20:23 Modified: 20 Oct 2005 1:02
Reporter: Stephen Dodson Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:4.1.7, 4.1.13 OS:Solaris (Solaris 9)
Assigned to: Jim Winstead CPU Architecture:Any

[3 Nov 2004 20:23] Stephen Dodson
Description:
#include <mysql.h>

int
main(void)
{
    MYSQL   mysql;

    mysql_init(&mysql);

    if(!mysql_real_connect(&mysql, NULL, NULL, NULL, NULL, 0UL, NULL, 0UL))
    {
        ...
    }

    return 0;
}

Linked against libmysqlclient_r.

This code when compiled (g++ 3.3.2) and run under purify (Version 2003a.06.13 FixPack 
0155 040722 Solaris 2) results in an array bounds read (ABR).

The stack trace is as follows:

   Finished  a.out                (   1 error, 8592 leaked bytes)
      Purify instrumented a.out (pid 23766 at Wed Nov  3 19:55:49 2004)
      Command-line: ./a.out 
      ABR: Array bounds read
      This is occurring while in:
            memcmp         [rtlib.o]
            _memcmp        [rtlib.o]
            bcmp           [libc.so.1]
            my_xml_scan    [xml.c:84]
            my_xml_parse   [xml.c:287]
            my_parse_charset_xml [ctype.c:314]
            my_read_charset_file [charset.c:303]
            init_available_charsets [charset.c:393]
            get_charset_by_csname [charset.c:538]
            mysql_real_connect [client.c:1852]
            main           [main.cc:10]
            _start         [crt1.o]
      Reading 4 bytes from 0xb1698 in the heap (1 byte at 0xb169b illegal).
      Address 0xb1698 is 17144 bytes into a malloc'd block at 0xad3a0 of 17147 bytes.
      This block was allocated from:
            malloc         [rtlib.o]
            my_malloc      [my_malloc.c:35]
            my_read_charset_file [charset.c:290]
            init_available_charsets [charset.c:393]
            get_charset_by_csname [charset.c:538]
            mysql_real_connect [client.c:1852]
            main           [main.cc:10]
            _start         [crt1.o]
      Current file descriptors in use: 6
      Memory leaked: 8592 bytes (22.2%); potentially leaked: 0 bytes (0%)
      Thread Summary : 1 threads in existence
      Program exited with status code 0.

From gdb the stack frame (xml.c:84) is

#4  0xff2c30e4 in my_xml_scan (p=0xffbfe460, a=0xffbfdc78) at xml.c:84
84        if (!bcmp(p->cur,"<!--",4))
(gdb) print p->cur
$1 = 0xb1698 ">\n\n"

This is a 3 character byte string and is not 4 bytes long, hence the ABR. 

(gdb) print *p
$3 = {errstr = '\0' <repeats 127 times>, 
  attr = "\000harsets\000charset\000collation\000flag", '\0' <repeats 96 times>, attrend = 
0xffbfe4e0 "", 
  beg = 0xad3a0 "<?xml version='1.0' encoding=\"utf-8\"?>\n\n<charsets max-
id=\"94\">\n\n<copyright>\n Copyright (C) 2003 MySQL AB\n\n  This program is free software; 
you can redistribute it and/or modify\n  it under the terms of"..., 
  cur = 0xb1698 ">\n\n", end = 0xb169b "", user_data = 0xffbfdcf0, 
  enter = 0xff2ba0a8 <cs_enter>, value = 0xff2ba1d0 <cs_value>, 
  leave_xml = 0xff2ba14c <cs_leave>}

Going up the stack the xml file read is:

#8  0xff2ab54c in init_available_charsets (myflags=0) at charset.c:393
393         error= my_read_charset_file(fname,myflags);
(gdb) print fname
$4 = "/usr/local/share/mysql/charsets/Index.xml\0.....

To demonstate this, if an extra \n is added to this file the error goes away as the last p->cur 
happens to be 4 bytes. However, a proper fix is required.

How to repeat:
See Description

Suggested fix:
Changing xml.c:83 to guard with

if ((p->end-p->cur) >= 4 && !bcmp(p->cur,"<!--",4))
{

Will fix the problem but I have not followed the logic completely through.
[16 Sep 2005 14:23] Valeriy Kravchuk
Thank you for your bug report,

I was able to repeat just the same behaviour as you described when running simple client program purified on our sunfire280 server:

****  Purify instrumented /export/home/mysqldev/valeriy/6413 (pid 66683)  ****
ABR: Array bounds read:
  * This is occurring while in:
        memcmp         [rtlib.o]
        _memcmp        [rtlib.o]
        bcmp           [libc.so.1]
        my_xml_scan    [libmysqlclient.so.14]
        my_xml_parse   [libmysqlclient.so.14]
        my_parse_charset_xml [libmysqlclient.so.14]
  * Reading 4 bytes from 0xcde9d in the heap (1 byte at 0xcdea0 illegal).
  * Address 0xcde9d is 17797 bytes into a malloc'd block at 0xc9918 of 17800 byt
es.
  * This block was allocated from:
        malloc         [rtlib.o]
        my_malloc      [libmysqlclient.so.14]
        init_available_charsets [libmysqlclient.so.14]
        get_charset_by_csname [libmysqlclient.so.14]
        mysql_real_connect [libmysqlclient.so.14]
        main           [cc4Lnayt.o]

Moreover, line 84 in xml.c is still the same in the newer BK 4.1.15 code, so, I think, this should be checked once more carefully by developers.
[11 Oct 2005 22:22] 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/30939
[13 Oct 2005 15:13] Jim Winstead
Fixed in 4.1.16 and 5.0.15.
[20 Oct 2005 1:02] Paul DuBois
Noted in 4.1.16, 5.0.15 changelogs.