From 7ee05d7c713c0958cd56248b7b7397d72fea3941 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 21 Apr 2006 01:07:37 +0400 Subject: Applied innodb-5.0-ss476 snapshot. Fix BUG#18934: "InnoDB crashes when table uses column like DB_ROW_ID". Also, fix memory leaks in row_create_table_for_mysql() in rare corner cases. innobase/dict/dict0dict.c: Applied innodb-5.0-ss476 snapshot. Refuse tables that use reserved column names (Bug#18934). innobase/dict/dict0load.c: Applied innodb-5.0-ss476 snapshot. dict_load_table(): Refuse to load tables with other TYPE than DICT_TABLE_ORDINARY. innobase/dict/dict0mem.c: Applied innodb-5.0-ss476 snapshot. Add dict_mem_table_free(), use it instead of duplicating the code everywhere. innobase/ibuf/ibuf0ibuf.c: Applied innodb-5.0-ss476 snapshot. innobase/include/dict0dict.h: Applied innodb-5.0-ss476 snapshot. Refuse tables that use reserved column name (Bug#18934). innobase/include/dict0mem.h: Applied innodb-5.0-ss476 snapshot. Add dict_mem_table_free(), use it instead of duplicating the code everywhere. innobase/include/univ.i: Applied innodb-5.0-ss476 snapshot. innobase/log/log0recv.c: Applied innodb-5.0-ss476 snapshot. innobase/row/row0mysql.c: Applied innodb-5.0-ss476 snapshot. Refuse tables that use reserved column names (Bug#18934). mysql-test/r/innodb.result: Applied innodb-5.0-ss476 snapshot. Fix result for test case for Bug#18934. (Other changes are to be restored by the next cset). mysql-test/t/innodb.test: Applied innodb-5.0-ss476 snapshot. Fix result for test case for Bug#18934. (Removed test case for Bug#14360 is to be restored by the next cset). --- innobase/dict/dict0dict.c | 38 ++++++++++++++++++++++++++++++++++---- innobase/dict/dict0load.c | 17 +++++++++++------ innobase/dict/dict0mem.c | 18 ++++++++++++++++++ innobase/ibuf/ibuf0ibuf.c | 6 +++--- innobase/include/dict0dict.h | 9 +++++++++ innobase/include/dict0mem.h | 7 +++++++ innobase/include/univ.i | 3 +++ innobase/log/log0recv.c | 6 +++--- innobase/row/row0mysql.c | 18 ++++++++++++++++++ 9 files changed, 106 insertions(+), 16 deletions(-) (limited to 'innobase') diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 653addd9ede..bad8886d0be 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -1249,15 +1249,13 @@ dict_table_remove_from_cache( /* Remove table from LRU list of tables */ UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table); - mutex_free(&(table->autoinc_mutex)); - size = mem_heap_get_size(table->heap); ut_ad(dict_sys->size >= size); dict_sys->size -= size; - mem_heap_free(table->heap); + dict_mem_table_free(table); } /************************************************************************** @@ -1378,6 +1376,38 @@ dict_col_reposition_in_cache( HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col); } +/******************************************************************** +If the given column name is reserved for InnoDB system columns, return +TRUE. */ + +ibool +dict_col_name_is_reserved( +/*======================*/ + /* out: TRUE if name is reserved */ + const char* name) /* in: column name */ +{ + /* This check reminds that if a new system column is added to + the program, it should be dealt with here. */ +#if DATA_N_SYS_COLS != 4 +#error "DATA_N_SYS_COLS != 4" +#endif + + static const char* reserved_names[] = { + "DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR", "DB_MIX_ID" + }; + + ulint i; + + for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) { + if (strcmp(name, reserved_names[i]) == 0) { + + return(TRUE); + } + } + + return(FALSE); +} + /************************************************************************** Adds an index to the dictionary cache. */ @@ -1551,7 +1581,7 @@ dict_index_remove_from_cache( dict_sys->size -= size; - mem_heap_free(index->heap); + dict_mem_index_free(index); } /*********************************************************************** diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 6415cc56b61..bd93a719f6c 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -767,7 +767,7 @@ dict_load_table( if (!btr_pcur_is_on_user_rec(&pcur, &mtr) || rec_get_deleted_flag(rec, sys_tables->comp)) { /* Not found */ - + err_exit: btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); @@ -779,11 +779,8 @@ dict_load_table( /* Check if the table name in record is the searched one */ if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) { - btr_pcur_close(&pcur); - mtr_commit(&mtr); - mem_heap_free(heap); - - return(NULL); + + goto err_exit; } ut_a(0 == ut_strcmp("SPACE", @@ -844,6 +841,14 @@ dict_load_table( field = rec_get_nth_field_old(rec, 5, &len); table->type = mach_read_from_4(field); + if (UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: table %s: unknown table type %lu\n", + name, (ulong) table->type); + goto err_exit; + } + if (table->type == DICT_TABLE_CLUSTER_MEMBER) { ut_error; #if 0 /* clustered tables have not been implemented yet */ diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c index eec35310039..98ef44a4969 100644 --- a/innobase/dict/dict0mem.c +++ b/innobase/dict/dict0mem.c @@ -97,6 +97,21 @@ dict_mem_table_create( return(table); } +/******************************************************************** +Free a table memory object. */ + +void +dict_mem_table_free( +/*================*/ + dict_table_t* table) /* in: table */ +{ + ut_ad(table); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + mutex_free(&(table->autoinc_mutex)); + mem_heap_free(table->heap); +} + /************************************************************************** Creates a cluster memory object. */ @@ -290,5 +305,8 @@ dict_mem_index_free( /*================*/ dict_index_t* index) /* in: index */ { + ut_ad(index); + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + mem_heap_free(index->heap); } diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index d7fa48b6e66..e4694ed52ae 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -1160,9 +1160,9 @@ ibuf_dummy_index_free( dict_index_t* index) /* in: dummy index */ { dict_table_t* table = index->table; - mem_heap_free(index->heap); - mutex_free(&(table->autoinc_mutex)); - mem_heap_free(table->heap); + + dict_mem_index_free(index); + dict_mem_table_free(table); } /************************************************************************* diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index 4396611e529..642037494b5 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -98,6 +98,15 @@ ulint dict_col_get_clust_pos( /*===================*/ dict_col_t* col); +/******************************************************************** +If the given column name is reserved for InnoDB system columns, return +TRUE. */ + +ibool +dict_col_name_is_reserved( +/*======================*/ + /* out: TRUE if name is reserved */ + const char* name); /* in: column name */ /************************************************************************ Initializes the autoinc counter. It is not an error to initialize an already initialized counter. */ diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h index 7eec86d0bcb..3c10e82342b 100644 --- a/innobase/include/dict0mem.h +++ b/innobase/include/dict0mem.h @@ -56,6 +56,13 @@ dict_mem_table_create( a member of a cluster */ ulint n_cols, /* in: number of columns */ ibool comp); /* in: TRUE=compact page format */ +/******************************************************************** +Free a table memory object. */ + +void +dict_mem_table_free( +/*================*/ + dict_table_t* table); /* in: table */ /************************************************************************** Creates a cluster memory object. */ diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 04b254a8221..bc3bd031f0c 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -261,6 +261,9 @@ it is read or written. */ /* Tell the compiler that cond is unlikely to hold */ #define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE) +/* Compile-time constant of the given array's size. */ +#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0])) + #include #include "ut0dbg.h" #include "ut0ut.h" diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 42e854398ba..7c56fe35d48 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -890,9 +890,9 @@ recv_parse_or_apply_log_rec_body( ut_ad(!page || ptr); if (index) { dict_table_t* table = index->table; - mem_heap_free(index->heap); - mutex_free(&(table->autoinc_mutex)); - mem_heap_free(table->heap); + + dict_mem_index_free(index); + dict_mem_table_free(table); } return(ptr); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 937056c300e..89b82882d93 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1673,7 +1673,9 @@ row_mysql_recover_tmp_table( if (!ptr) { /* table name does not begin with "/rsql" */ + dict_mem_table_free(table); trx_commit_for_mysql(trx); + return(DB_ERROR); } else { @@ -1785,6 +1787,7 @@ row_create_table_for_mysql( const char* table_name; ulint table_name_len; ulint err; + ulint i; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); #ifdef UNIV_SYNC_DEBUG @@ -1802,6 +1805,7 @@ row_create_table_for_mysql( "InnoDB: with raw, and innodb_force_... is removed.\n", stderr); + dict_mem_table_free(table); trx_commit_for_mysql(trx); return(DB_ERROR); @@ -1816,11 +1820,25 @@ row_create_table_for_mysql( "InnoDB: MySQL system tables must be of the MyISAM type!\n", table->name); + dict_mem_table_free(table); trx_commit_for_mysql(trx); return(DB_ERROR); } + /* Check that no reserved column names are used. */ + for (i = 0; i < dict_table_get_n_user_cols(table); i++) { + dict_col_t* col = dict_table_get_nth_col(table, i); + + if (dict_col_name_is_reserved(col->name)) { + + dict_mem_table_free(table); + trx_commit_for_mysql(trx); + + return(DB_ERROR); + } + } + trx_start_if_not_started(trx); if (row_mysql_is_recovered_tmp_table(table->name)) { -- cgit v1.2.1