summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMikael Ronstrom <mikael@mysql.com>2009-10-28 01:11:17 +0100
committerMikael Ronstrom <mikael@mysql.com>2009-10-28 01:11:17 +0100
commit10fed1aca0096acb135c2065233e84d61b00b9cf (patch)
tree32eac76c7c0b41298c58cd40bc85138e177d8a98 /sql
parentcc43a2089cf6f45afb2cb5c15e2a077b075b80f8 (diff)
downloadmariadb-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.cc8
-rw-r--r--sql/partition_info.cc30
-rw-r--r--sql/partition_info.h3
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sql_partition.cc21
-rw-r--r--sql/sql_partition.h1
-rw-r--r--sql/sql_show.cc2
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;