diff options
author | Mikael Ronstrom <mikael@mysql.com> | 2009-10-28 01:11:17 +0100 |
---|---|---|
committer | Mikael Ronstrom <mikael@mysql.com> | 2009-10-28 01:11:17 +0100 |
commit | 10fed1aca0096acb135c2065233e84d61b00b9cf (patch) | |
tree | 32eac76c7c0b41298c58cd40bc85138e177d8a98 /sql | |
parent | cc43a2089cf6f45afb2cb5c15e2a077b075b80f8 (diff) | |
download | mariadb-git-10fed1aca0096acb135c2065233e84d61b00b9cf.tar.gz |
BUG#48165, needed to introduce length restrictions on partitioning fields to ensure that no stack overruns occur
Diffstat (limited to 'sql')
-rw-r--r-- | sql/opt_range.cc | 8 | ||||
-rw-r--r-- | sql/partition_info.cc | 30 | ||||
-rw-r--r-- | sql/partition_info.h | 3 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 2 | ||||
-rw-r--r-- | sql/sql_partition.cc | 21 | ||||
-rw-r--r-- | sql/sql_partition.h | 1 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 |
7 files changed, 55 insertions, 12 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 356cfe5e398..19aa06dcae9 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3600,12 +3600,8 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar) { key_part->key= 0; key_part->part= part; - key_part->store_length= key_part->length= (uint16) (*field)->key_length(); - if ((*field)->real_maybe_null()) - key_part->store_length+= HA_KEY_NULL_LENGTH; - if ((*field)->type() == MYSQL_TYPE_BLOB || - (*field)->real_type() == MYSQL_TYPE_VARCHAR) - key_part->store_length+= HA_KEY_BLOB_LENGTH; + key_part->length= (uint16)get_partition_field_store_length(*field); + key_part->store_length= key_part->length; DBUG_PRINT("info", ("part %u length %u store_length %u", part, key_part->length, key_part->store_length)); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 9d9aa5d4e95..52a4c4c0c7f 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -1344,6 +1344,36 @@ bool partition_info::set_part_expr(char *start_token, Item *item_ptr, /* + Check that partition fields and subpartition fields are not too long + + SYNOPSIS + check_partition_field_length() + + RETURN VALUES + TRUE Total length was too big + FALSE Length is ok +*/ + +bool partition_info::check_partition_field_length() +{ + uint store_length= 0; + uint i; + DBUG_ENTER("partition_info::check_partition_field_length"); + + for (i= 0; i < num_part_fields; i++) + store_length+= get_partition_field_store_length(part_field_array[i]); + if (store_length > MAX_KEY_LENGTH) + DBUG_RETURN(TRUE); + store_length= 0; + for (i= 0; i < num_subpart_fields; i++) + store_length+= get_partition_field_store_length(subpart_field_array[i]); + if (store_length > MAX_KEY_LENGTH) + DBUG_RETURN(TRUE); + DBUG_RETURN(FALSE); +} + + +/* Set up buffers and arrays for fields requiring preparation SYNOPSIS set_up_charset_field_preps() diff --git a/sql/partition_info.h b/sql/partition_info.h index 015e0c1d6d0..4d3cc2222a6 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -19,8 +19,6 @@ #include "partition_element.h" -#define MAX_STR_SIZE_PF 2048 - class partition_info; /* Some function typedefs */ @@ -298,6 +296,7 @@ public: char *end_token, bool is_subpart); static int compare_column_values(const void *a, const void *b); bool set_up_charset_field_preps(); + bool check_partition_field_length(); bool init_column_part(); bool add_column_list_value(THD *thd, Item *item); private: diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index d65945013b9..ec08885fda4 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6222,3 +6222,5 @@ ER_ROW_SINGLE_PARTITION_FIELD_ERROR eng "Row expressions in VALUES IN only allowed for multi-field column partitioning" ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD eng "Field '%-.192s' is of a not allowed type for this type of partitioning" +ER_PARTITION_FIELDS_TOO_LONG + eng "The total length of the partitioning fields is too large" diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 83d50ee222e..e21f7da6888 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1779,6 +1779,11 @@ bool fix_partition_func(THD *thd, TABLE *table, my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); goto end; } + if (unlikely(part_info->check_partition_field_length())) + { + my_error(ER_PARTITION_FIELDS_TOO_LONG, MYF(0)); + goto end; + } check_range_capable_PF(table); set_up_partition_key_maps(table, part_info); set_up_partition_func_pointers(part_info); @@ -2038,8 +2043,6 @@ static int check_part_field(Create_field *sql_field, case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: - if (sql_field->length > MAX_STR_SIZE_PF) - goto error; *need_cs_check= TRUE; return FALSE; break; @@ -2095,7 +2098,7 @@ static int add_column_list_values(File fptr, partition_info *part_info, err+= add_string(fptr, "NULL"); else { - char buffer[3 * MAX_STR_SIZE_PF + 10]; + char buffer[MAX_KEY_LENGTH]; String str(buffer, sizeof(buffer), &my_charset_bin); Item *item_expr= col_val->item_expression; if (item_expr->null_value) @@ -7730,5 +7733,17 @@ void create_subpartition_name(char *out, const char *in1, strxmov(out, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, "#REN#", NullS); } + +uint get_partition_field_store_length(Field *field) +{ + uint store_length; + + store_length= field->key_length(); + if (field->real_maybe_null()) + store_length+= HA_KEY_NULL_LENGTH; + if (field->real_type() == MYSQL_TYPE_VARCHAR) + store_length+= HA_KEY_BLOB_LENGTH; + return store_length; +} #endif diff --git a/sql/sql_partition.h b/sql/sql_partition.h index 0dac13a3fcc..724a63e1d76 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -71,6 +71,7 @@ bool partition_key_modified(TABLE *table, const MY_BITMAP *fields); void get_partition_set(const TABLE *table, uchar *buf, const uint index, const key_range *key_spec, part_id_range *part_spec); +uint get_partition_field_store_length(Field *field); void get_full_part_id_from_key(const TABLE *table, uchar *buf, KEY *key_info, const key_range *key_spec, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 46a91f7a905..77c7a3c27f3 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4846,7 +4846,7 @@ get_partition_column_description(partition_info *part_info, tmp_str.append("NULL"); else { - char buffer[3 * MAX_STR_SIZE_PF + 10]; + char buffer[MAX_KEY_LENGTH]; String str(buffer, sizeof(buffer), &my_charset_bin); Item *item= col_val->item_expression; |