Bug #5731 key_buffer_size not properly restricted to 4GB
Submitted: 24 Sep 2004 12:10 Modified: 25 Oct 2007 18:18
Reporter: Dean Ellis Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: General Severity:S2 (Serious)
Version:4.0 4.1 5.0 OS:Any
Assigned to: Alexey Kopytov CPU Architecture:Any
Tags: bfsm_2007_02_01, bfsm_2007_04_05, bfsm_2007_05_31

[24 Sep 2004 12:10] Dean Ellis
Description:
OPT_KEY_BUFFER_SIZE is limited to 4GB via cast to long which is 64 bits on at least some 64 bit platforms (AMD64), allowing specification of values larger than 4GB for key_buffer_size.

How to repeat:
Set key_buffer_size to some value > 4GB on AMD64 machine.

Suggested fix:
Cast with (uint32) instead of (long).
[24 Sep 2004 12:18] Dean Ellis
Possible patch for 4.0:

===== sql/mysqld.cc 1.512 vs edited =====
--- 1.512/sql/mysqld.cc 2004-09-24 04:54:28 -05:00
+++ edited/sql/mysqld.cc        2004-09-24 07:16:10 -05:00
@@ -4144,7 +4144,7 @@
   {"key_buffer_size", OPT_KEY_BUFFER_SIZE,
    "The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
    (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULL,
-   REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
+   REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (uint32) ~0, MALLOC_OVERHEAD,
    IO_SIZE, 0},
   {"long_query_time", OPT_LONG_QUERY_TIME,
    "Log all queries that have taken more than long_query_time seconds to execute to file.",
[25 Sep 2004 11:18] Sergei Golubchik
Why do you consider it a bug ? Isn't it logical that one can specify key buffer larger than 4G on 64-bit box ?

(of course it if crashes elsewhere because of huge key buffer it's a bug to fix - but a different one)
[4 Oct 2004 23:26] Dean Ellis
The limit for key_buffer_size was supposed to be 4GB (per Monty); there are too many other areas of the server that do not have support for a larger buffer, so enforcing the limit correctly was the best short-term solution.
[17 Oct 2004 23:52] Dean Ellis
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html

Additional info:

Fixed in 4.0.22 (cset 1.2043).
[6 Feb 2007 21:50] Ingo Strüwing
Please note that the block buffer is allocated in init_key_cache() using my_large_malloc(), not my_malloc(). But despite its name it uses an uint for the size parameter. [my_large_malloc() tries a couple of efficient memory alloation methods and can fall back to my_malloc() though.]

Within the SQL layer the key_buffer_size is handled as ulonglong. In ha_init_key_cache() it is mapped to long. In init_key_cache() it is handled as ulong. So fixing my_large_malloc() and all functions that could be used by it internally should do the trick. However this might be too much for 5.0.

Regarding the limits I saw compilers on some of our pushbuild systems, which did not compile ~(ulong)0 to what one expects. So UINT_MAX32 is a proper 4G-1 limit. This should be used in 5.0 if we do not fix my_large_malloc() there. Otherwise, and in 5.1 it should be ULONG_MAX. So that it is limited to 4G-1 on 32-bit systems and higher otherwise.
[27 Feb 2007 17:22] Michael Widenius
Reviewed first version of patch. Can be pushed after the following changes are done:
- my_size_t -> size_t (in 5.1, remove my_size_t everywhere)
- llstr() for not DBUG printf's
- Fix calls to my_large_malloc/my_large_free to ensure right free is called
- Test with creating a key cache > 4G on a 64 bit system (and checking with
  mysqld --help --verbose and debugger that we really got a large cache)
[1 Mar 2007 10:55] 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/20888

ChangeSet@1.2404, 2007-03-01 13:55:11+03:00, kaa@polly.local +7 -0
  Fix for bug #5731 "key_buffer_size not properly restricted to 4GB".
  
  Problem: all memory allocation functions had an unsigned int argument specifying size of a block to allocate, which resulted in overflows when allocating buffers > 4GB on 64-bit systems.
  
  Solution: use size_t instead of uint to specify a memory block size. This is a minimal patch for 5.0 required to allow key_buffer_size > 4 GB on 64-bit systems. More cleanup work will be done in 5.1.
[5 Mar 2007 15:25] 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/21158

ChangeSet@1.2404, 2007-03-05 18:25:37+03:00, kaa@polly.local +7 -0
  Fix for bug #5731 "key_buffer_size not properly restricted to 4GB".
  
  Problem: all memory allocation functions had an unsigned int argument specifying size of a block to allocate, which resulted in overflows when allocating buffers > 4GB on 64-bit systems.
  
  Solution: use size_t instead of uint to specify a memory block size. This is a minimal patch for 5.0 required to allow key_buffer_size > 4 GB on 64-bit systems. More cleanup work will be done in 5.1.
[6 Mar 2007 17:06] 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/21248

ChangeSet@1.2434, 2007-03-06 20:06:23+03:00, kaa@polly.local +15 -0
  5.1 part of the fix for bug #5731 "key_buffer_size not properly restricted to 4GB".
  
  - Changed interfaces for my_large_malloc() and my_large_free() to ensure the proper free method is used.
  - Replaced my_size_t with platform-defined size_t.
[3 Apr 2007 15:49] 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/23692

ChangeSet@1.2434, 2007-04-03 19:48:29+04:00, kaa@polly.local +15 -0
  5.1 part of the fix for bug #5731 "key_buffer_size not properly restricted to 4GB".
  
  - Changed interfaces for my_large_malloc() and my_large_free() to ensure the proper free method is used.
  - Replaced my_size_t with platform-defined size_t, since it is correctly defined and safe to use on modern platforms.
[18 Jul 2007 10:47] 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/31075

ChangeSet@1.2404, 2007-07-18 14:45:44+04:00, kaa@polly.local +2 -0
  This patch is a part of work on bug #5731 "key_buffer_size not properly restricted to 4GB".
    
  The patch limits read_buffer_size and read_rnd_buffer_size by 2 GB on all platforms for the following reasons:
    
  - I/O code in mysys, code in mf_iocache.c and in some storage engines do not currently work with sizes > 2 GB for those buffers
  - even if the above had been fixed, Windows POSIX read() and write() calls are not 2GB-safe, so setting those buffer to sizes > 2GB would not work correctly on 64-bit Windows.
[18 Jul 2007 12:16] 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/31081

ChangeSet@1.2404, 2007-07-18 16:15:50+04:00, kaa@polly.local +1 -0
  Since it was decided to not fix bug #5731 and related ones in 5.0, we need to limit all buffer sizes to 4GB on all platforms. This patch will be null-merged to 5.1.
[23 Jul 2007 23:43] Michael Widenius
I changed this to be back in progress as we should not limit the key buffer size to 4G (not resonable restriction)

(The other buffers are ok to limit to 2G)

In 5.1 mysys and the string library are using size_t for all memory and string lengths. To fix the key buffer issue in 5.0, we could just backport the changes done to the following files in 5.1: my_malloc.c, safe_malloc.c my_largepage.c and my_lockmem.c.
(Basicly we should be able to just copy these files from 5.1 to 5.0 and fix the prototypes in my_sys.h)
This should fix the key_buffer_size in 5.0 for all system where 'ulong' is 64 bit (5.1 should work or be fixed to work with all systems)
[23 Jul 2007 23:53] Michael Widenius
I changed this to be back in progress as we should not limit the key buffer size to 4G (not resonable restriction)

(The other buffers are ok to limit to 2G)

In 5.1 mysys and the string library are using size_t for all memory and string lengths. To fix the key buffer issue in 5.0, we could just backport the changes done to the following files in 5.1: my_malloc.c, safe_malloc.c my_largepage.c and my_lockmem.c.
(Basicly we should be able to just copy these files from 5.1 to 5.0 and fix the prototypes in my_sys.h)
This should fix the key_buffer_size in 5.0 for all system where 'ulong' is 64 bit (5.1 should work or be fixed to work with all systems)
[2 Aug 2007 19:14] Bugs System
Pushed into 5.1.21-beta
[29 Aug 2007 15:21] 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/33343

ChangeSet@1.2512, 2007-08-29 19:20:18+04:00, kaa@polly.local +4 -0
  Backport of my_malloc() changes from 5.1 to make it 64-bit safe on Unix platforms.
  
  This is required to allow key_buffer_size > 4 GB (bug #5731).
[29 Aug 2007 16:35] 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/33358

ChangeSet@1.2512, 2007-08-29 20:33:44+04:00, kaa@polly.local +1 -0
  Limit join_buffer_size, sort_buffer_size and myisam_sort_buffer_size to 4GB on all platforms, since the related code in 5.0 is not 64-bit safe. This is patch is a part of work on bug #5731 and will be null-merged to 5.1.
[29 Aug 2007 16:46] 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/33363

ChangeSet@1.2512, 2007-08-29 20:45:04+04:00, kaa@polly.local +2 -0
  Backport of the keycache changes from http://lists.mysql.com/commits/31517 to make keycache 64-bit safe in 5.0. This is for bug #5731.
[3 Sep 2007 8:58] 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/33576

ChangeSet@1.2582, 2007-09-03 12:57:47+04:00, kaa@polly.(none) +2 -0
  Use SIZE_T_MAX instead of ulong as a limit for key_buffer_size to allow key_bufer_size > 4G on Windows in 5.1. This is for bug #5731.
[7 Sep 2007 8:00] 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/33888

ChangeSet@1.2404, 2007-09-07 11:58:04+04:00, kaa@polly.(none) +2 -0
  This patch is a part of work on bug #5731 "key_buffer_size not properly restricted to 4GB".
    
  The patch limits read_buffer_size and read_rnd_buffer_size by 2 GB on all platforms for the following reasons:
    
  - I/O code in mysys, code in mf_iocache.c and in some storage engines do not currently work with sizes > 2 GB for those buffers
  - even if the above had been fixed, Windows POSIX read() and write() calls are not 2GB-safe, so setting those buffer to sizes > 2GB would not work correctly on 64-bit Windows.
[9 Sep 2007 22:03] Dathan Pattishall
Has the > 4GB key_buffer_size been pushed into Community yet? If so what version? Tracking commits to branch-versions or bk tags is hard to track through the website. Is there a tool for this?
[10 Sep 2007 8:11] Alexey Kopytov
Dathan,

The patches are not in any publicly available tree yet, but I'm going to push them this week. Once the patches are merged into the main tree, there will be a comment in the bug saying in which versions of the main trees they will be available.
[18 Oct 2007 21:36] Bugs System
Pushed into 5.1.23-beta
[18 Oct 2007 21:37] Bugs System
Pushed into 5.0.52
[25 Oct 2007 18:18] Paul DuBois
Bug#5731, Bug#29419, Bug#29446 are related; this note appears in all three reports.

Noted in 5.0.52, 5.1.23 changelogs (and also 5.2.6 to note the changes explicitly because of discussion in these bug reports about work still to be done in 5.2).

Several buffer-size system variables were either being handled 
incorrectly for large values (for settings larger than 4GB, they were
truncated to values less than 4GB without a warning), or were limited
unnecessarily to 4GB even on 64-bit systems.

The following changes were made in 5.0.52: 

For key_buffer_size, values larger than 4GB are allowed on 64-bit 
platforms (except Windows, for which large values are truncated to
4GB with a warning). 

For join_buffer_size, sort_buffer_size, and myisam_sort_buffer_size,
values are limited to 4GB on all platforms. Larger values are
truncated to 4GB with a warning. 

The following changes were made in 5.1.23/5.2.6:

For key_buffer_size, values larger than 4GB are allowed on 64-bit 
platforms.  

For join_buffer_size, sort_buffer_size, and myisam_sort_buffer_size,
values larger than 4GB are allowed on 64-bit platforms (except
Windows, for which large values are truncated to 4GB with a warning). 

The following change was made in all versions:

Settings for read_buffer_size and read_rnd_buffer_size
are limited to 2GB on all platforms. Larger values are truncated to
2GB with a warning.
[29 Oct 2007 17:37] Paul DuBois
5.2.6 changes will appear in 6.0.3 instead.
[15 Jan 2008 15:51] MySQL Verification Team
Bug #33820 was marked as a duplicate of this