summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <elliot@mysql.com>2006-04-28 12:15:29 -0400
committerunknown <elliot@mysql.com>2006-04-28 12:15:29 -0400
commitdd68976a249cf73d6bf67faa37108438b26e800c (patch)
treea1a6f77b937a2fd005b4ab4083ce3d0757c2f12e
parente92e1dace7529271a401273bdf265adf863b6c77 (diff)
downloadmariadb-git-dd68976a249cf73d6bf67faa37108438b26e800c.tar.gz
BUG#19145: mysqld crashes if you set the default value of an enum field to NULL
Now test for NULLness the pointers returned from objects created from the default value. Pushing patch on behalf of cmiller. mysql-test/r/null.result: Add test case mysql-test/t/null.test: Add test case sql/sql_table.cc: No longer blindly dereference pointer of the string representation of the values, where "NULL" is NUL. Raise INVALID DEFAULT error messages where appropriate. Note that the -O1 optimization flag made debugging this extremely tricky, with misleading results, and that removing it from the Makefile during debugging can be invaluable.
-rw-r--r--mysql-test/r/null.result42
-rw-r--r--mysql-test/t/null.test41
-rw-r--r--sql/sql_table.cc49
3 files changed, 122 insertions, 10 deletions
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 3e233eb512a..4d90aac0e68 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -269,3 +269,45 @@ field('str1', null, 'STR1') as c05,
c01 c02 c03 c04 c05 c08 c09
str str 0 1 2 1 1
set names latin1;
+create table bug19145a (e enum('a','b','c') default 'b' , s set('x', 'y', 'z') default 'y' ) engine=MyISAM;
+create table bug19145b (e enum('a','b','c') default null, s set('x', 'y', 'z') default null) engine=MyISAM;
+create table bug19145c (e enum('a','b','c') not null default 'b' , s set('x', 'y', 'z') not null default 'y' ) engine=MyISAM;
+create table bug19145setnotnulldefaultnull (e enum('a','b','c') default null, s set('x', 'y', 'z') not null default null) engine=MyISAM;
+ERROR 42000: Invalid default value for 's'
+create table bug19145enumnotnulldefaultnull (e enum('a','b','c') not null default null, s set('x', 'y', 'z') default null) engine=MyISAM;
+ERROR 42000: Invalid default value for 'e'
+alter table bug19145a alter column e set default null;
+alter table bug19145a alter column s set default null;
+alter table bug19145a add column (i int);
+alter table bug19145b alter column e set default null;
+alter table bug19145b alter column s set default null;
+alter table bug19145b add column (i int);
+alter table bug19145c alter column e set default null;
+ERROR 42000: Invalid default value for 'e'
+alter table bug19145c alter column s set default null;
+ERROR 42000: Invalid default value for 's'
+alter table bug19145c add column (i int);
+show create table bug19145a;
+Table Create Table
+bug19145a CREATE TABLE `bug19145a` (
+ `e` enum('a','b','c') default NULL,
+ `s` set('x','y','z') default NULL,
+ `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table bug19145b;
+Table Create Table
+bug19145b CREATE TABLE `bug19145b` (
+ `e` enum('a','b','c') default NULL,
+ `s` set('x','y','z') default NULL,
+ `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table bug19145c;
+Table Create Table
+bug19145c CREATE TABLE `bug19145c` (
+ `e` enum('a','b','c') NOT NULL default 'b',
+ `s` set('x','y','z') NOT NULL default 'y',
+ `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table bug19145a;
+drop table bug19145b;
+drop table bug19145c;
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index 731f0a4cb34..b405b8fb852 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -187,4 +187,45 @@ select
# Restore charset to the default value.
set names latin1;
+#
+# Bug#19145: mysqld crashes if you set the default value of an enum field to NULL
+#
+create table bug19145a (e enum('a','b','c') default 'b' , s set('x', 'y', 'z') default 'y' ) engine=MyISAM;
+create table bug19145b (e enum('a','b','c') default null, s set('x', 'y', 'z') default null) engine=MyISAM;
+
+create table bug19145c (e enum('a','b','c') not null default 'b' , s set('x', 'y', 'z') not null default 'y' ) engine=MyISAM;
+
+# Invalid default value for 's'
+--error 1067
+create table bug19145setnotnulldefaultnull (e enum('a','b','c') default null, s set('x', 'y', 'z') not null default null) engine=MyISAM;
+
+# Invalid default value for 'e'
+--error 1067
+create table bug19145enumnotnulldefaultnull (e enum('a','b','c') not null default null, s set('x', 'y', 'z') default null) engine=MyISAM;
+
+alter table bug19145a alter column e set default null;
+alter table bug19145a alter column s set default null;
+alter table bug19145a add column (i int);
+
+alter table bug19145b alter column e set default null;
+alter table bug19145b alter column s set default null;
+alter table bug19145b add column (i int);
+
+# Invalid default value for 'e'
+--error 1067
+alter table bug19145c alter column e set default null;
+
+# Invalid default value for 's'
+--error 1067
+alter table bug19145c alter column s set default null;
+alter table bug19145c add column (i int);
+
+show create table bug19145a;
+show create table bug19145b;
+show create table bug19145c;
+
+drop table bug19145a;
+drop table bug19145b;
+drop table bug19145c;
+
# End of 4.1 tests
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c9513ec71ab..0454cadc774 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -601,7 +601,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (need_to_change_arena)
thd->restore_backup_item_arena(thd->current_arena, &backup_arena);
- if (! sql_field->def)
+ if (sql_field->def == NULL)
{
/* Could not convert */
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
@@ -611,15 +611,30 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (sql_field->sql_type == FIELD_TYPE_SET)
{
- if (sql_field->def)
+ if (sql_field->def != NULL)
{
char *not_used;
uint not_used2;
bool not_found= 0;
String str, *def= sql_field->def->val_str(&str);
- def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
- (void) find_set(interval, def->ptr(), def->length(),
- cs, &not_used, &not_used2, &not_found);
+ if (def == NULL) /* SQL "NULL" maps to NULL */
+ {
+ if ((sql_field->flags & NOT_NULL_FLAG) != 0)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+
+ /* else, NULL is an allowed value */
+ (void) find_set(interval, NULL, 0,
+ cs, &not_used, &not_used2, &not_found);
+ }
+ else /* not NULL */
+ {
+ (void) find_set(interval, def->ptr(), def->length(),
+ cs, &not_used, &not_used2, &not_found);
+ }
+
if (not_found)
{
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
@@ -631,14 +646,28 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
else /* FIELD_TYPE_ENUM */
{
- if (sql_field->def)
+ DBUG_ASSERT(sql_field->sql_type == FIELD_TYPE_ENUM);
+ if (sql_field->def != NULL)
{
String str, *def= sql_field->def->val_str(&str);
- def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
- if (!find_type2(interval, def->ptr(), def->length(), cs))
+ if (def == NULL) /* SQL "NULL" maps to NULL */
{
- my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
- DBUG_RETURN(-1);
+ if ((sql_field->flags & NOT_NULL_FLAG) != 0)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+
+ /* else, the defaults yield the correct length for NULLs. */
+ }
+ else /* not NULL */
+ {
+ def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
+ if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
}
}
calculate_interval_lengths(cs, interval, &sql_field->length, &dummy);