summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <aivanov@mysql.com>2006-04-21 01:07:37 +0400
committerunknown <aivanov@mysql.com>2006-04-21 01:07:37 +0400
commit7ee05d7c713c0958cd56248b7b7397d72fea3941 (patch)
tree31ecaf555285cc75ca6c78a278663dcc1fc1c253 /innobase
parent6b63f270c6c9d31c72bb2ca5131c490e367be515 (diff)
downloadmariadb-git-7ee05d7c713c0958cd56248b7b7397d72fea3941.tar.gz
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).
Diffstat (limited to 'innobase')
-rw-r--r--innobase/dict/dict0dict.c38
-rw-r--r--innobase/dict/dict0load.c17
-rw-r--r--innobase/dict/dict0mem.c18
-rw-r--r--innobase/ibuf/ibuf0ibuf.c6
-rw-r--r--innobase/include/dict0dict.h9
-rw-r--r--innobase/include/dict0mem.h7
-rw-r--r--innobase/include/univ.i3
-rw-r--r--innobase/log/log0recv.c6
-rw-r--r--innobase/row/row0mysql.c18
9 files changed, 106 insertions, 16 deletions
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 <stdio.h>
#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)) {