Skip to content

Commit e52921d

Browse files
author
Sreeharsha Ramanavarapu
committed
Bug #27973409:GCOL: INCORRECT BEHAVIOR WITH STRING FUNCTION
Issue: ------ 1) Create table with a string function to populate an integer virtual generated column with an index on it. 2) INSERT IGNORE INTO t1(c1) VALUES (''); The string function returns empty string because length (last input parameter) is zero. It does this by manipulating a length of the constant string input parameter and setting it to zero. It is important to remember that for generated columns, Item_func_xxxx (the generated column's function) object is created on the table's memroot and thus has a lifetime beyond this statement (i.e. until the table is flushed). So effectively this statement has corrupted the constant string parameter and its length is now set to zero. And will return incorrect results for subsequent statements. This problem isn't restricted to generated columns and can be seen in simple calls to the string functions also. Solution: --------- String functions shouldn't manipulate the lengths of input parameters to return results. Create a new string, copy to that location and manipulate the length there.
1 parent 00985f4 commit e52921d

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

sql/item_strfunc.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3708,6 +3708,7 @@ String *Item_func_rpad::val_str(String *str)
37083708
char *to;
37093709
/* must be longlong to avoid truncation */
37103710
longlong count= args[1]->val_int();
3711+
/* Avoid modifying this string as it may affect args[0] */
37113712
String *res= args[0]->val_str(str);
37123713
String *rpad= args[2]->val_str(&rpad_str);
37133714

@@ -3751,10 +3752,15 @@ String *Item_func_rpad::val_str(String *str)
37513752

37523753
const size_t res_char_length= res->numchars();
37533754

3755+
// String to pad is big enough
37543756
if (count <= static_cast<longlong>(res_char_length))
3755-
{ // String to pad is big enough
3756-
res->length(res->charpos((int) count)); // Shorten result if longer
3757-
return (res);
3757+
{
3758+
int res_charpos= res->charpos((int)count);
3759+
if (tmp_value.alloc(res_charpos))
3760+
return NULL;
3761+
(void)tmp_value.copy(*res);
3762+
tmp_value.length(res_charpos); // Shorten result if longer
3763+
return &tmp_value;
37583764
}
37593765
const size_t pad_char_length= rpad->numchars();
37603766

@@ -3776,6 +3782,10 @@ String *Item_func_rpad::val_str(String *str)
37763782
}
37773783
/* Must be done before alloc_buffer */
37783784
const size_t res_byte_length= res->length();
3785+
/*
3786+
alloc_buffer() doesn't modify 'res' because 'res' is guaranteed too short
3787+
at this stage.
3788+
*/
37793789
if (!(res= alloc_buffer(res, str, &tmp_value,
37803790
static_cast<size_t>(byte_count))))
37813791
{
@@ -3836,6 +3846,7 @@ String *Item_func_lpad::val_str(String *str)
38363846
/* must be longlong to avoid truncation */
38373847
longlong count= args[1]->val_int();
38383848
size_t byte_count;
3849+
/* Avoid modifying this string as it may affect args[0] */
38393850
String *res= args[0]->val_str(&tmp_value);
38403851
String *pad= args[2]->val_str(&lpad_str);
38413852

@@ -3876,8 +3887,12 @@ String *Item_func_lpad::val_str(String *str)
38763887

38773888
if (count <= static_cast<longlong>(res_char_length))
38783889
{
3879-
res->length(res->charpos((int) count));
3880-
return res;
3890+
int res_charpos= res->charpos((int)count);
3891+
if (tmp_value.alloc(res_charpos))
3892+
return NULL;
3893+
(void)tmp_value.copy(*res);
3894+
tmp_value.length(res_charpos); // Shorten result if longer
3895+
return &tmp_value;
38813896
}
38823897

38833898
pad_char_length= pad->numchars();

0 commit comments

Comments
 (0)