From 994674c09b112745fd03355a0972fbf3f4b0295c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Apr 2005 15:27:42 +0200 Subject: Bug#8321 - myisampack bug in compression algorithm This is the second of three changesets. It contains the pure bug fix. It also contains the second after-review fixes. The problem was that with gcc on x86, shifts are done modulo word size. 'value' is 32 bits wide and shifting it by 32 bits is a no-op. This was triggered by an evil distribution of character incidences. A distribution of 2917027827 characters made of 202 distinct values led to 34 occurrences of 32-bit Huffman codes. This might have been the first time ever that write_bits() had to write 32-bit values. Since it can be expected that one day even 32 bits might be insufficient, the third changeset suggests to enlarge some variables to 64 bits. --- myisam/myisampack.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'myisam') diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 9f4e3bde65a..90689b08476 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -31,6 +31,7 @@ #define __GNU_LIBRARY__ /* Skip warnings in getopt.h */ #endif #include +#include #if INT_MAX > 32767 #define BITS_SAVED 32 @@ -1975,7 +1976,9 @@ static void write_bits (register ulong value, register uint bits) { reg3 uint byte_buff; bits= (uint) -file_buffer.bits; - byte_buff=file_buffer.byte | (uint) (value >> bits); + DBUG_ASSERT(bits <= 8 * sizeof(value)); + byte_buff= (file_buffer.byte | + ((bits != 8 * sizeof(value)) ? (uint) (value >> bits) : 0)); #if BITS_SAVED == 32 *file_buffer.pos++= (byte) (byte_buff >> 24) ; *file_buffer.pos++= (byte) (byte_buff >> 16) ; @@ -1983,7 +1986,9 @@ static void write_bits (register ulong value, register uint bits) *file_buffer.pos++= (byte) (byte_buff >> 8) ; *file_buffer.pos++= (byte) byte_buff; - value&=(1 << bits)-1; + DBUG_ASSERT(bits <= 8 * sizeof(ulong)); + if (bits != 8 * sizeof(value)) + value&= (((ulong) 1) << bits) - 1; #if BITS_SAVED == 16 if (bits >= sizeof(uint)) { -- cgit v1.2.1