| Bug #36320 | server crashes on "select 1e37" and on "select -1e15" etc. | ||
|---|---|---|---|
| Submitted: | 24 Apr 2008 15:16 | Modified: | 29 May 2008 3:43 | 
| Reporter: | Daniel Fischer | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Data Types | Severity: | S1 (Critical) | 
| Version: | 6.0.5 | OS: | Other (Solaris Sparc64, HP-UX ia64/hppa64) | 
| Assigned to: | Alexey Kopytov | CPU Architecture: | Any | 
   [27 Apr 2008 8:01]
   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/46068 ChangeSet@1.2626, 2008-04-27 12:00:14+04:00, kaa@mbp.local +1 -0 Fix for bug #36320: server crashes on "select 1e37" and on "select -1e15" etc. The bug is a regression introduced by the patch for WL #2934. On 64-bit architectures with strict alignment rules converting some floating point numbers to/from strings could crash the server due to improper alignment of internal data structures. Fixed allocation routines in dtoa.c to ensure allocated objects to be aligned by the pointer size. No test case is required because the necessary coverage is provided by existing tests.
   [28 Apr 2008 9:30]
   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/46102 ChangeSet@1.2625, 2008-04-28 11:29:17+02:00, jperkin@mysql.com +1 -0 dtoa.c: Pull in patch from bug#36320 to fix 64bit architectures with strict alignment rules.
   [28 May 2008 10:01]
   Bugs System        
  Pushed into 6.0.6-alpha
   [29 May 2008 3:43]
   Paul DuBois        
  Noted in 6.0.6 changelog. The server crashed while parsing large floating-point numbers such as 1e37 or -1e15.
   [23 Jul 2008 13:08]
   Bugs System        
  Pushed into 6.0.7-alpha (revid:serg@mysql.com-20080722121106-wy84j0yvceyu72zr) (pib:2)
   [14 Sep 2008 0:27]
   Bugs System        
  Pushed into 6.0.7-alpha (revid:sp1r-jperkin/mysqldev@mysql.com/production.mysql.com-20080428092917-15381) (version source revid:vvaintroub@mysql.com-20080804094710-jb2qpqxpf2ir2gf3) (pib:3)


Description: MySQL 6.0.5 crashes reproducibly with SIGBUS on specific platforms when attempting to parse large floating-point numbers. These are actually many different bugs that are caused by similar mistakes in strings/dtoa.c. The code in dtoa.c assumes in many places that aligning pointers to 32 bit boundaries is always sufficient. This is incorrect specifically on Sparc in 64 bit mode, on ia64, and on hppa in 64 bit mode. Examples of statement that crash the server in different places in the source code: select 1e37; (dtoa.c:Balloc) select 1e-15; (dtoa.c:dtoa_alloc, after fixing Balloc) select 1e-48; (dtoa.c:cmp, after fixing dtoa_alloc) This also manifests itself in many test case failures. MySQL 6.0.5 is the lowest version that is affected. How to repeat: Build 6.0.5 on Solaris 10 Sparc in 64-bit mode (cc-5.0 -xarch=v9 etc.). Run your choice of the above queries. Suggested fix: < jperkin> import gdtoa from netbsd and have done with it Fixes for the first two examples: ===== dtoa.c 1.8 vs edited ===== --- 1.8/strings/dtoa.c 2008-01-08 08:33:02 +01:00 +++ edited/dtoa.c 2008-04-24 17:14:42 +02:00 @@ -664,6 +664,10 @@ int x, len; x= 1 << k; +#if SIZEOF_LONG == 8 + /* Align len to 8-byte boundary */ + x+= x&1; +#endif len= sizeof(Bigint) + x * sizeof(ULong); if (alloc->free + len <= alloc->end) @@ -709,13 +713,15 @@ /* This is to place return value of dtoa in: tries to use stack as well, but passes by free lists management and just aligns len by - sizeof(ULong). + sizeof(long). + Aligning len by sizeof(ULong) is not sufficient because of alignment + restrictions on 64-bit values on some 64 bit architectures. */ static char *dtoa_alloc(int i, Stack_alloc *alloc) { char *rv; - int aligned_size= (i + sizeof(ULong) - 1) / sizeof(ULong) * sizeof(ULong); + int aligned_size= (i + sizeof(long) - 1) / sizeof(long) * sizeof(long); if (alloc->free + aligned_size <= alloc->end) { rv= alloc->free;