Bug #48284 C99 aliasing violation, results in failures in the client library
Submitted: 25 Oct 7:57 Modified: 23 Nov 23:02
Reporter: Davin McCall
Status: Patch pending
Category:C API Severity:S2 (Serious)
Version:5.1.40 OS:Linux
Assigned to: Jim Winstead Target Version:5.1+
Triage: Triaged: D2 (Serious)

[25 Oct 7:57] Davin McCall
Description:
There is a C99 aliasing violation in the source of Mysql 5.1.40 which causes client
errors (specifically with MythTV but probably also with others) when Mysql is compiled
with -O3 optimization (GCC 4.4.2).

The problem is in in libmysql/libmysql.c, in the cli_stmt_execute() function. Line 2553
looks like:

    for (param= stmt->params; param < param_end; param++)
        store_param_type((char**) &net->write_pos, param);

And store_param_type is declared as:

    static void store_param_type(char **pos, MYSQL_BIND *param)
    {
        uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
        int2store(*pos, typecode);
        *pos+= 2;
    }

However, the real type of net->write_pos is "uchar *" not "char *" and it is referenced
as such elsewhere in the cli_stmt_execute function. The types are incompatible and it is
not legal to access the net->write_pos value as if it were both a "uchar *" and "char *"
(note that if the "char **" cast is removed GCC gives a warning that the types are
incompatible).

The eventual result is that GCC thinks "*pos+=2" can be moved outside the loop and
collapsed to a single store. A bit silly, but that's what happens when you break the
aliasing rules :)

How to repeat:
Compile with GCC 4.4.2, using the Mysql-recommended CFLAGS/CXXFLAGS (I added only
-march=i686).

CXX=gcc CFLAGS="-O3 -march=i686" \
CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti -march=i686" \
  ./configure --prefix=/usr --localstatedir=/var/mysql --sysconfdir=/etc \
              --mandir=/usr/share/man \
              --enable-thread-safe-client --enable-assembler --with-gnu-ld \
              --with-mysqld-user=mysql --with-ssl
make
make install

Then run "mythfrontend"...

Suggested fix:
The fix is fairly trivial, two things should be changed:
1) change the declared type of the "pos" parameter in store_param_type from "char **" to
"uchar **"
2) remove the "char **" cast from line 2554 in cli_stmt_execute. (Not strictly necessary,
but GCC gives a warning if you don't).

For a workaround with current version, it's easy just to add "-fno-strict-aliasing" to
CFLAGS.
[17 Nov 11:33] Tonci Grgin
Hi Davin.

Verified just as described by looking into latest 5.1 sources.
[23 Nov 23:02] 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/commits/91356

3218 Jim Winstead	2009-11-23
      Fix C99 aliasing violation due to mismatched types that were papered over
      with a cast. (Bug #48284)