From: Date: June 20 2007 11:42am Subject: bk commit into 5.0 tree (gkodinov:1.2494) BUG#27383 List-Archive: http://lists.mysql.com/commits/29168 X-Bug: 27383 Message-Id: <200706200942.l5K9gNal011675@magare.gmz> Below is the list of changes that have just been committed into a local 5.0 repository of kgeorge. When kgeorge does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-06-20 12:42:21+03:00, gkodinov@stripped +1 -0 Bug #27383: Crash in test "mysql_client_test" The C optimizer may decide that data access operations through pointer of different type are not related to the original data (strict aliasing). This is what happens in fetch_long_with_conversion(), when called as part of mysql_stmt_fetch() : it tries to check for truncation errors by first storing float (and other types of data) into a char * buffer and then accesses them through a float pointer. This is done to prevent the effects of excess precision when using FPU registers. Fixed by making the intermediary variables volatile ( to not re-introduce the excess precision bug) and using the intermediary value instead of the char * buffer. Note that there can be loss of precision for both signed and unsigned 64 bit integers converted to double and back, so the check must stay there (even for compatibility reasons). Based on the excellent analysis in bug 28400. libmysql/libmysql.c@stripped, 2007-06-20 12:42:20+03:00, gkodinov@stripped +39 -26 Bug #27383: avoid pointer aliasing problems while not re-violating the Intel FPU gcc bug. # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: gkodinov # Host: magare.gmz # Root: /home/kgeorge/mysql/work/B28400-5.0-opt --- 1.256/libmysql/libmysql.c 2007-05-24 21:51:35 +03:00 +++ 1.257/libmysql/libmysql.c 2007-06-20 12:42:20 +03:00 @@ -3667,29 +3667,33 @@ static void fetch_long_with_conversion(M workaround Intel FPU executive precision feature. (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details) AFAIU it does not guarantee to work. + We need to keep the data buffer volatile : this will keep the + Intel FPU bug away and will also not cause the "Casting doesn't work + as expected when optimization is turned on" gcc non-bug + (see http://gcc.gnu.org/bugs.html#nonbugs_c). */ - float data; + volatile float data; if (is_unsigned) data= (float) ulonglong2double(value); else data= (float) value; floatstore(buffer, data); *param->error= is_unsigned ? - ((ulonglong) value) != ((ulonglong) (*(float*) buffer)) : - ((longlong) value) != ((longlong) (*(float*) buffer)); + ((ulonglong) value) != ((ulonglong) data) : + ((longlong) value) != ((longlong) data); break; } case MYSQL_TYPE_DOUBLE: { - double data; + volatile double data; if (is_unsigned) data= ulonglong2double(value); else data= (double)value; doublestore(buffer, data); *param->error= is_unsigned ? - ((ulonglong) value) != ((ulonglong) (*(double*) buffer)) : - ((longlong) value) != ((longlong) (*(double*) buffer)); + ((ulonglong) value) != ((ulonglong) data) : + ((longlong) value) != ((longlong) data); break; } case MYSQL_TYPE_TIME: @@ -3750,62 +3754,71 @@ static void fetch_float_with_conversion( workaround Intel FPU executive precision feature. (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details) Sic: AFAIU it does not guarantee to work. + We need to keep the data buffer volatile : this will keep the + Intel FPU bug away and will also not cause the "Casting doesn't work + as expected when optimization is turned on" gcc non-bug + (see http://gcc.gnu.org/bugs.html#nonbugs_c). */ if (param->is_unsigned) - *buffer= (uint8) value; + { + volatile uint8 data= (uint8) value; + *buffer= data; + *param->error= val64 != data; + } else - *buffer= (int8) value; - *param->error= val64 != (param->is_unsigned ? (double)((uint8) *buffer) : - (double)((int8) *buffer)); + { + volatile int8 data= (int8) value; + *buffer= data; + *param->error= val64 != data; + } break; case MYSQL_TYPE_SHORT: if (param->is_unsigned) { - ushort data= (ushort) value; + volatile ushort data= (ushort) value; shortstore(buffer, data); + *param->error= val64 != (double) data; } else { - short data= (short) value; + volatile short data= (short) value; shortstore(buffer, data); + *param->error= val64 != (double) data; } - *param->error= val64 != (param->is_unsigned ? (double) (*(ushort*) buffer): - (double) (*(short*) buffer)); break; case MYSQL_TYPE_LONG: if (param->is_unsigned) { - uint32 data= (uint32) value; + volatile uint32 data= (uint32) value; longstore(buffer, data); + *param->error= val64 != (double) data; } else { - int32 data= (int32) value; + volatile int32 data= (int32) value; longstore(buffer, data); + *param->error= val64 != (double) data; } - *param->error= val64 != (param->is_unsigned ? (double) (*(uint32*) buffer): - (double) (*(int32*) buffer)); - break; + break; case MYSQL_TYPE_LONGLONG: if (param->is_unsigned) { - ulonglong data= (ulonglong) value; + volatile ulonglong data= (ulonglong) value; longlongstore(buffer, data); + *param->error= val64 != ulonglong2double(data); } else { - longlong data= (longlong) value; + volatile longlong data= (longlong) value; longlongstore(buffer, data); + *param->error= val64 != (double) data; } - *param->error= val64 != (param->is_unsigned ? - ulonglong2double(*(ulonglong*) buffer) : - (double) (*(longlong*) buffer)); break; case MYSQL_TYPE_FLOAT: { - float data= (float) value; + volatile float data= (float) value; floatstore(buffer, data); - *param->error= (*(float*) buffer) != value; + *param->error= data != value; break; } case MYSQL_TYPE_DOUBLE: