mirror of
https://github.com/MariaDB/server.git
synced 2025-08-27 13:04:36 +03:00
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.
This commit is contained in:
@@ -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, ¬_used, ¬_used2, ¬_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, ¬_used, ¬_used2, ¬_found);
|
||||
}
|
||||
else /* not NULL */
|
||||
{
|
||||
(void) find_set(interval, def->ptr(), def->length(),
|
||||
cs, ¬_used, ¬_used2, ¬_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);
|
||||
|
Reference in New Issue
Block a user