From 9d41d7c57b4566b86ef2b623ed93ada50a359781 Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Tue, 4 Sep 2012 14:33:56 +0530 Subject: [PATCH] Bug #14500557 CRASH WHEN USING LONG INNODB INDEXES The ha_innobase table handler contained two search key buffers (srch_key_val1, srch_key_val2) of fixed size used to store the search key. The size of these buffers where fixed at REC_VERSION_56_MAX_INDEX_COL_LEN + 2. But this size is not sufficient to hold the search key. Hence the following assert in row_sel_convert_mysql_key_to_innobase() failed. 2438 /* Storing may use at most data_len bytes of buf */ 2439 2440 if (UNIV_LIKELY(!is_null)) { 2441 ut_a(buf + data_len <= original_buf + buf_len); 2442 row_mysql_store_col_in_innobase_format( 2443 dfield, buf, 2444 FALSE, /* MySQL key value format col */ 2445 key_ptr + data_offset, data_len, 2446 dict_table_is_comp(index->table)); 2447 buf += data_len; 2448 } The buffer size is now calculated with the formula MAX_KEY_LENGTH + MAX_REF_PARTS*2. This properly takes into account the extra bytes needed to store the length for each column. An index can contain a maximum of MAX_REF_PARTS columns in it, and for each column 2 bytes are needed to store length. rb://1238 approved by Marko and Vasil Dimov. --- storage/innobase/handler/ha_innodb.h | 9 +++++---- storage/innobase/row/row0sel.c | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index b32b23e418b..dfe58e2c309 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -80,12 +80,13 @@ class ha_innobase: public handler uchar* upd_buf; /*!< buffer used in updates */ ulint upd_buf_size; /*!< the size of upd_buf in bytes */ - uchar srch_key_val1[REC_VERSION_56_MAX_INDEX_COL_LEN + 2]; - uchar srch_key_val2[REC_VERSION_56_MAX_INDEX_COL_LEN + 2]; + uchar srch_key_val1[MAX_KEY_LENGTH + MAX_REF_PARTS*2]; + uchar srch_key_val2[MAX_KEY_LENGTH + MAX_REF_PARTS*2]; /*!< buffers used in converting search key values from MySQL format - to InnoDB format. "+ 2" for the two - bytes where the length is stored */ + to InnoDB format. For each column + 2 bytes are used to store length, + hence MAX_REF_PARTS*2. */ Table_flags int_table_flags; uint primary_key; ulong start_of_scan; /*!< this is set to 1 when we are diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 7bec0a26225..1e352d49670 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -2487,6 +2487,9 @@ row_sel_convert_mysql_key_to_innobase( dfield++; } + DBUG_EXECUTE_IF("innodb_srch_key_buffer_full", + ut_a(buf == (original_buf + buf_len));); + ut_a(buf <= original_buf + buf_len); /* We set the length of tuple to n_fields: we assume that the memory