summaryrefslogtreecommitdiff
path: root/myisam
diff options
context:
space:
mode:
authorunknown <istruewing@chilla.local>2006-11-10 14:40:56 +0100
committerunknown <istruewing@chilla.local>2006-11-10 14:40:56 +0100
commit6982fc4d2be46335e09b08662a0760a7ac4a4716 (patch)
tree2e3d2e75bc5f271b2582d454208cc00fddb3f56c /myisam
parent71c646f34dd84140497c7e309070a0ae19b056cb (diff)
parent0e3c030558c2e81f684460d21b941c88aeae5525 (diff)
downloadmariadb-git-6982fc4d2be46335e09b08662a0760a7ac4a4716.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into chilla.local:/home/mydev/mysql-5.0-axmrg configure.in: Auto merged sql/sql_insert.cc: Auto merged
Diffstat (limited to 'myisam')
-rw-r--r--myisam/mi_check.c90
-rw-r--r--myisam/mi_dynrec.c8
2 files changed, 78 insertions, 20 deletions
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 06fdd3bff4c..1297338436f 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -251,11 +251,12 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
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); /* purecov: tested */
next_link=info->s->state.key_del[nr];
records= (ha_rows) (info->state->key_file_length / block_size);
@@ -265,14 +266,46 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
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)
+ {
+ /* purecov: begin tested */
+ 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);
+ /* purecov: end */
+ }
+
+ /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
+ if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1))
+ {
+ /* purecov: begin tested */
+ 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);
+ /* purecov: end */
+ }
+
+ /*
+ Read the key block with MI_MIN_KEY_BLOCK_LENGTH to find next link.
+ If the key cache block size is smaller than block_size, we can so
+ avoid unecessary eviction of cache block.
+ */
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)))
+ {
+ /* purecov: begin tested */
+ mi_check_print_error(param, "key cache read error for block: %s",
+ llstr(next_link,llbuff));
DBUG_RETURN(1);
+ /* purecov: end */
+ }
next_link=mi_sizekorr(buff);
records--;
param->key_file_blocks+=block_size;
@@ -556,17 +589,37 @@ static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
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));
-
- if (page+info->s->blocksize > max_length)
+ DBUG_ENTER("chk_index_down");
+
+ /* Key blocks must lay within the key file length entirely. */
+ if (page + keyinfo->block_length > info->state->key_file_length)
+ {
+ /* purecov: begin tested */
+ /* 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));
+ /* purecov: end */
+ }
+
+ /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
+ if (page & (MI_MIN_KEY_BLOCK_LENGTH - 1))
+ {
+ /* purecov: begin tested */
+ 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;
+ /* purecov: end */
}
+
if (!_mi_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0))
{
mi_check_print_error(param,"Can't read key from filepos: %s",
@@ -577,9 +630,12 @@ static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (chk_index(param,info,keyinfo,page,buff,keys,key_checksum,level))
goto err;
- return 0;
+ DBUG_RETURN(0);
+
+ /* purecov: begin tested */
err:
- return 1;
+ DBUG_RETURN(1);
+ /* purecov: end */
}
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index ef5ab73f1a9..149f9cea59e 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -1029,9 +1029,11 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
{
uint size_length=rec_length- mi_portable_sizeof_char_ptr;
ulong blob_length=_mi_calc_blob_length(size_length,from);
- if ((ulong) (from_end-from) - size_length < blob_length ||
- min_pack_length > (uint) (from_end -(from+size_length+blob_length)))
- goto err;
+ ulong from_left= (ulong) (from_end - from);
+ if (from_left < size_length ||
+ from_left - size_length < blob_length ||
+ from_left - size_length - blob_length < min_pack_length)
+ goto err;
memcpy((byte*) to,(byte*) from,(size_t) size_length);
from+=size_length;
memcpy_fixed((byte*) to+size_length,(byte*) &from,sizeof(char*));