List:Commits« Previous MessageNext Message »
From:ingo Date:October 17 2006 5:41pm
Subject:bk commit into 5.1 tree (istruewing:1.2345) BUG#22119
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of istruewing. When istruewing 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, 2006-10-17 17:40:33+02:00, istruewing@stripped +3 -0
  Bug#22119 - Changing MI_KEY_BLOCK_LENGTH makes a wrong myisamchk
  
  When compiling with a default key block size greater than the
  smallest key block size used in a table, checking that table
  failed with bogus errors. The table was marked corrupt. This
  affected myisamchk and the server.
  
  The problem was that the default key block size was used at
  some places where sizes less or equal to the block size of the
  index in check was required.
  
  We do now use the key block size of the particular index
  when checking.

  mysql-test/r/myisam.result@stripped, 2006-10-17 17:40:19+02:00, istruewing@stripped +45
-0
    Bug#22119 - Changing MI_KEY_BLOCK_LENGTH makes a wrong myisamchk
    Added test result.

  mysql-test/t/myisam.test@stripped, 2006-10-17 17:40:20+02:00, istruewing@stripped +43 -0
    Bug#22119 - Changing MI_KEY_BLOCK_LENGTH makes a wrong myisamchk
    Added test case.

  storage/myisam/mi_check.c@stripped, 2006-10-17 17:40:20+02:00, istruewing@stripped +70
-16
    Bug#22119 - Changing MI_KEY_BLOCK_LENGTH makes a wrong myisamchk
    Changed check_k_link() and chk_index_down() to use the block
    size of the index in check or MI_MIN_KEY_BLOCK_LENGTH where
    required. Formerly myisam_block_size or MYISAM_SHARE::blocksize
    was used wrongly.

# 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:	istruewing
# Host:	chilla.local
# Root:	/home/mydev/mysql-5.1-bug22119

--- 1.152/storage/myisam/mi_check.c	2006-10-17 17:41:11 +02:00
+++ 1.153/storage/myisam/mi_check.c	2006-10-17 17:41:11 +02:00
@@ -227,13 +227,21 @@ static int check_k_link(MI_CHECK *param,
   my_off_t next_link;
   uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
   ha_rows records;
-  char llbuff[21],*buff;
+  char llbuff[21], llbuff2[21], *buff;
   DBUG_ENTER("check_k_link");
+  DBUG_PRINT("enter", ("block_size: %u", block_size));
 
   if (param->testflag & T_VERBOSE)
-    printf("block_size %4d:",block_size);
+    printf("block_size %4u:", block_size);
 
   next_link=info->s->state.key_del[nr];
+  /* Inject an alignment error. */
+  DBUG_EXECUTE_IF("inject_check_k_link_align",
+                  next_link--;);
+  /* Inject a violation of the key file length. */
+  DBUG_EXECUTE_IF("inject_check_k_link_length",
+                  next_link= info->state->key_file_length;);
+
   records= (ha_rows) (info->state->key_file_length / block_size);
   while (next_link != HA_OFFSET_ERROR && records > 0)
   {
@@ -241,14 +249,33 @@ static int check_k_link(MI_CHECK *param,
       DBUG_RETURN(1);
     if (param->testflag & T_VERBOSE)
       printf("%16s",llstr(next_link,llbuff));
-    if (next_link > info->state->key_file_length ||
-	next_link & (info->s->blocksize-1))
+    /* Key blocks must lay within the key file length entirely. */
+    if (next_link + block_size > info->state->key_file_length)
+    {
+      mi_check_print_error(param, "Invalid key block position: %s  "
+                           "key block size: %u  file_length: %s",
+                           llstr(next_link, llbuff), block_size,
+                           llstr(info->state->key_file_length, llbuff2));
       DBUG_RETURN(1);
+    }
+    /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
+    if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1))
+    {
+      mi_check_print_error(param, "Mis-aligned key block: %s  "
+                           "minimum key block length: %u",
+                           llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
+      DBUG_RETURN(1);
+    }
+    /* Read the key block with MI_MIN_KEY_BLOCK_LENGTH to find next link. */
     if (!(buff=key_cache_read(info->s->key_cache,
                               info->s->kfile, next_link, DFLT_INIT_HITS,
-                              (byte*) info->buff,
-			      myisam_block_size, block_size, 1)))
+                              (byte*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
+                              MI_MIN_KEY_BLOCK_LENGTH, 1)))
+    {
+      mi_check_print_error(param, "key cache read error for block: %s",
+			   llstr(next_link,llbuff));
       DBUG_RETURN(1);
+    }
     next_link=mi_sizekorr(buff);
     records--;
     param->key_file_blocks+=block_size;
@@ -532,16 +559,43 @@ static int chk_index_down(MI_CHECK *para
                      ha_checksum *key_checksum, uint level)
 {
   char llbuff[22],llbuff2[22];
-  if (page > info->state->key_file_length || (page &
(info->s->blocksize -1)))
-  {
-    my_off_t max_length=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
-    mi_check_print_error(param,"Wrong pagepointer: %s at page: %s",
-                llstr(page,llbuff),llstr(page,llbuff2));
+  DBUG_ENTER("chk_index_down");
 
-    if (page+info->s->blocksize > max_length)
+  /* Inject an alignment error. */
+  DBUG_EXECUTE_IF("inject_chk_index_down_align",
+                  page--;);
+  /* Inject a violation of the real key file length. */
+  DBUG_EXECUTE_IF("inject_chk_index_down_length",
+                  page= info->state->key_file_length=
+                  my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(0)););
+  /* Inject a violation of the remembered but not the real key file length. */
+  DBUG_EXECUTE_IF("inject_chk_index_down_seek",
+                  page= (info->state->key_file_length=
+                         my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(0)) -
+                         keyinfo->block_length););
+
+  /* Key blocks must lay within the key file length entirely. */
+  if (page + keyinfo->block_length > info->state->key_file_length)
+  {
+    /* Give it a chance to fit in the real file size. */
+    my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(0));
+    mi_check_print_error(param, "Invalid key block position: %s  "
+                         "key block size: %u  file_length: %s",
+                         llstr(page, llbuff), keyinfo->block_length,
+                         llstr(info->state->key_file_length, llbuff2));
+    if (page + keyinfo->block_length > max_length)
       goto err;
-    info->state->key_file_length=(max_length &
-                                  ~ (my_off_t) (info->s->blocksize-1));
+    /* Fix the remebered key file length. */
+    info->state->key_file_length= (max_length &
+                                   ~ (my_off_t) (keyinfo->block_length - 1));
+  }
+  /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
+  if (page & (MI_MIN_KEY_BLOCK_LENGTH - 1))
+  {
+    mi_check_print_error(param, "Mis-aligned key block: %s  "
+                         "minimum key block length: %u",
+                         llstr(page, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
+    goto err;
   }
   if (!_mi_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0))
   {
@@ -553,9 +607,9 @@ static int chk_index_down(MI_CHECK *para
   if (chk_index(param,info,keyinfo,page,buff,keys,key_checksum,level))
     goto err;
 
-  return 0;
+  DBUG_RETURN(0);
 err:
-  return 1;
+  DBUG_RETURN(1);
 }
 
 

--- 1.95/mysql-test/r/myisam.result	2006-10-17 17:41:11 +02:00
+++ 1.96/mysql-test/r/myisam.result	2006-10-17 17:41:11 +02:00
@@ -1631,4 +1631,49 @@ create table t1 (a int not null, key key
 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near '=1024 (a))' at line 1
 create table t1 (a int not null, key `a` key_block_size=1024 (a));
 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near 'key_block_size=1024 (a))' at
line 1
+CREATE TABLE t1 (
+c1 INT,
+c2 VARCHAR(300),
+KEY (c1) KEY_BLOCK_SIZE 1024,
+KEY (c2) KEY_BLOCK_SIZE 8192
+);
+INSERT INTO t1 VALUES (10, REPEAT('a', CEIL(RAND(10) * 300))),
+(11, REPEAT('b', CEIL(RAND() * 300))),
+(12, REPEAT('c', CEIL(RAND() * 300))),
+(13, REPEAT('d', CEIL(RAND() * 300))),
+(14, REPEAT('e', CEIL(RAND() * 300))),
+(15, REPEAT('f', CEIL(RAND() * 300))),
+(16, REPEAT('g', CEIL(RAND() * 300))),
+(17, REPEAT('h', CEIL(RAND() * 300))),
+(18, REPEAT('i', CEIL(RAND() * 300))),
+(19, REPEAT('j', CEIL(RAND() * 300))),
+(20, REPEAT('k', CEIL(RAND() * 300))),
+(21, REPEAT('l', CEIL(RAND() * 300))),
+(22, REPEAT('m', CEIL(RAND() * 300))),
+(23, REPEAT('n', CEIL(RAND() * 300))),
+(24, REPEAT('o', CEIL(RAND() * 300))),
+(25, REPEAT('p', CEIL(RAND() * 300))),
+(26, REPEAT('q', CEIL(RAND() * 300))),
+(27, REPEAT('r', CEIL(RAND() * 300))),
+(28, REPEAT('s', CEIL(RAND() * 300))),
+(29, REPEAT('t', CEIL(RAND() * 300))),
+(30, REPEAT('u', CEIL(RAND() * 300))),
+(31, REPEAT('v', CEIL(RAND() * 300))),
+(32, REPEAT('w', CEIL(RAND() * 300))),
+(33, REPEAT('x', CEIL(RAND() * 300))),
+(34, REPEAT('y', CEIL(RAND() * 300))),
+(35, REPEAT('z', CEIL(RAND() * 300)));
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+REPAIR TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	status	OK
+DELETE FROM t1 WHERE c1 >= 10;
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+DROP TABLE t1;
 End of 5.1 tests

--- 1.70/mysql-test/t/myisam.test	2006-10-17 17:41:12 +02:00
+++ 1.71/mysql-test/t/myisam.test	2006-10-17 17:41:12 +02:00
@@ -963,4 +963,47 @@ create table t1 (a int not null, key key
 --error 1064
 create table t1 (a int not null, key `a` key_block_size=1024 (a));
 
+#
+# Bug#22119 - Changing MI_KEY_BLOCK_LENGTH makes a wrong myisamchk
+#
+CREATE TABLE t1 (
+  c1 INT,
+  c2 VARCHAR(300),
+  KEY (c1) KEY_BLOCK_SIZE 1024,
+  KEY (c2) KEY_BLOCK_SIZE 8192
+  );
+INSERT INTO t1 VALUES (10, REPEAT('a', CEIL(RAND(10) * 300))),
+  (11, REPEAT('b', CEIL(RAND() * 300))),
+  (12, REPEAT('c', CEIL(RAND() * 300))),
+  (13, REPEAT('d', CEIL(RAND() * 300))),
+  (14, REPEAT('e', CEIL(RAND() * 300))),
+  (15, REPEAT('f', CEIL(RAND() * 300))),
+  (16, REPEAT('g', CEIL(RAND() * 300))),
+  (17, REPEAT('h', CEIL(RAND() * 300))),
+  (18, REPEAT('i', CEIL(RAND() * 300))),
+  (19, REPEAT('j', CEIL(RAND() * 300))),
+  (20, REPEAT('k', CEIL(RAND() * 300))),
+  (21, REPEAT('l', CEIL(RAND() * 300))),
+  (22, REPEAT('m', CEIL(RAND() * 300))),
+  (23, REPEAT('n', CEIL(RAND() * 300))),
+  (24, REPEAT('o', CEIL(RAND() * 300))),
+  (25, REPEAT('p', CEIL(RAND() * 300))),
+  (26, REPEAT('q', CEIL(RAND() * 300))),
+  (27, REPEAT('r', CEIL(RAND() * 300))),
+  (28, REPEAT('s', CEIL(RAND() * 300))),
+  (29, REPEAT('t', CEIL(RAND() * 300))),
+  (30, REPEAT('u', CEIL(RAND() * 300))),
+  (31, REPEAT('v', CEIL(RAND() * 300))),
+  (32, REPEAT('w', CEIL(RAND() * 300))),
+  (33, REPEAT('x', CEIL(RAND() * 300))),
+  (34, REPEAT('y', CEIL(RAND() * 300))),
+  (35, REPEAT('z', CEIL(RAND() * 300)));
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+CHECK TABLE t1;
+REPAIR TABLE t1;
+DELETE FROM t1 WHERE c1 >= 10;
+CHECK TABLE t1;
+DROP TABLE t1;
+
 --echo End of 5.1 tests
Thread
bk commit into 5.1 tree (istruewing:1.2345) BUG#22119ingo17 Oct