Skip to content

Commit bf74dd8

Browse files
author
Tor Didriksen
committed
Bug #30114420 ASSERTION `CURRENT_THD->IS_ERROR()' FAILED|SQL/ITEM_STRFUNC.CC
Additional path, checking explicitly for binary arguments to functions REPLACE, SUBSTRING_INDEX and TRIM. Change-Id: I8686f5c48240c5aeff7db2c0834f1178ccc45d7f
1 parent 86eb374 commit bf74dd8

File tree

4 files changed

+91
-64
lines changed

4 files changed

+91
-64
lines changed

include/sql_string.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class String;
128128
struct CHARSET_INFO;
129129
struct IO_CACHE;
130130

131+
bool validate_string(const CHARSET_INFO *cs, const char *str, size_t length,
132+
size_t *valid_length, bool *length_error);
131133
int sortcmp(const String *a, const String *b, const CHARSET_INFO *cs);
132134
String *copy_if_not_alloced(String *to, String *from, size_t from_length);
133135
inline size_t copy_and_convert(char *to, size_t to_length,
@@ -475,6 +477,12 @@ class String {
475477
size_t offset;
476478
return needs_conversion(length(), charset(), cs_to, &offset);
477479
}
480+
bool is_valid_string(const CHARSET_INFO *cs_to) const {
481+
size_t valid_length;
482+
bool length_error;
483+
return !validate_string(cs_to, ptr(), length(), &valid_length,
484+
&length_error);
485+
}
478486
static bool needs_conversion_on_storage(size_t arg_length,
479487
const CHARSET_INFO *cs_from,
480488
const CHARSET_INFO *cs_to);
@@ -646,9 +654,6 @@ inline LEX_CSTRING to_lex_cstring(const char *s) {
646654
return cstr;
647655
}
648656

649-
bool validate_string(const CHARSET_INFO *cs, const char *str, size_t length,
650-
size_t *valid_length, bool *length_error);
651-
652657
bool append_escaped(String *to_str, const String *from_str);
653658

654659
#endif /* SQL_STRING_INCLUDED */

mysql-test/r/func_str.result

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5126,8 +5126,6 @@ HEX(LPAD('', 42, SUBSTRING_INDEX(COMPRESS(42),c1,1)))
51265126
02000000789C33310200009C006702000000789C33310200009C006702000000789C33310200009C0067
51275127
SELECT LPAD('', 42, REPLACE(RANDOM_BYTES(42),c1,'')) FROM t1;
51285128
SELECT LPAD('', 42, REPLACE(AES_ENCRYPT(c1, 'key'),c1,'')) FROM t1;
5129-
SELECT LPAD('', 42, TRIM(BOTH c1 FROM RANDOM_BYTES(1))) FROM t1;
5130-
SELECT LPAD('', 42, TRIM(BOTH RANDOM_BYTES(42) FROM c1)) FROM t1;
51315129
SELECT LPAD('', 42, REPLACE(MD5(c1),c1,'')) FROM t1;
51325130
LPAD('', 42, REPLACE(MD5(c1),c1,''))
51335131
e15997c74a71c5d9263df6f7a21bc191e15997c74a
@@ -5138,9 +5136,19 @@ SELECT HEX(LPAD('', 42, REPLACE(x'ffff',c1,''))) FROM t1;
51385136
HEX(LPAD('', 42, REPLACE(x'ffff',c1,'')))
51395137
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
51405138
SELECT HEX(LPAD('', 42, TRIM(x'ffff' FROM c1))) FROM t1;
5141-
HEX(LPAD('', 42, TRIM(x'ffff' FROM c1)))
5142-
416C61736B61416C61736B61416C61736B61416C61736B61416C61736B61416C61736B61416C61736B61
5139+
ERROR HY000: Cannot convert string '\xFF\xFF' from binary to utf8mb4
5140+
SELECT LPAD('', 42, REPLACE(c1, 'las', x'ff')) FROM t1;
5141+
ERROR HY000: Cannot convert string '\xFF' from binary to utf8mb4
5142+
SELECT LPAD('', 42, REPLACE(c1, x'ff', 'las')) FROM t1;
5143+
ERROR HY000: Cannot convert string '\xFF' from binary to utf8mb4
5144+
SELECT HEX(SUBSTRING_INDEX(_utf8mb4 x'41F09F8DA3F09F8DA3' , x'f0', 2)) FROM t1;
5145+
ERROR HY000: Cannot convert string '\xF0' from binary to utf8mb4
51435146
DROP TABLE t1;
5147+
SELECT TRIM(BOTH x'f0' FROM _utf8mb4 x'F09F8DA3F09F8DA3');
5148+
ERROR HY000: Cannot convert string '\xF0' from binary to utf8mb4
5149+
SELECT TRIM(BOTH x'F09F8DA3' FROM _utf8mb4 x'F09F8DA3F09F8DA3');
5150+
TRIM(BOTH x'F09F8DA3' FROM _utf8mb4 x'F09F8DA3F09F8DA3')
5151+
51445152
SELECT TRIM(_latin2 x'a3' from _latin1 "hello");
51455153
ERROR HY000: Cannot convert string '\xA3' from latin2 to latin1
51465154
SELECT REPLACE(_latin1 "hello", _latin2 x'a3', "hei");

mysql-test/t/func_str.test

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,18 +2031,30 @@ SELECT HEX(LPAD('', 42, SUBSTRING_INDEX(COMPRESS(42),c1,1))) FROM t1;
20312031
--disable_result_log
20322032
SELECT LPAD('', 42, REPLACE(RANDOM_BYTES(42),c1,'')) FROM t1;
20332033
SELECT LPAD('', 42, REPLACE(AES_ENCRYPT(c1, 'key'),c1,'')) FROM t1;
2034-
SELECT LPAD('', 42, TRIM(BOTH c1 FROM RANDOM_BYTES(1))) FROM t1;
2035-
SELECT LPAD('', 42, TRIM(BOTH RANDOM_BYTES(42) FROM c1)) FROM t1;
20362034
--enable_result_log
20372035

20382036
SELECT LPAD('', 42, REPLACE(MD5(c1),c1,'')) FROM t1;
20392037
SELECT HEX(LPAD('', 42, TRIM(BOTH c1 FROM x'ff'))) FROM t1;
20402038

20412039
SELECT HEX(LPAD('', 42, REPLACE(x'ffff',c1,''))) FROM t1;
2040+
--error ER_CANNOT_CONVERT_STRING
20422041
SELECT HEX(LPAD('', 42, TRIM(x'ffff' FROM c1))) FROM t1;
20432042

2043+
--error ER_CANNOT_CONVERT_STRING
2044+
SELECT LPAD('', 42, REPLACE(c1, 'las', x'ff')) FROM t1;
2045+
--error ER_CANNOT_CONVERT_STRING
2046+
SELECT LPAD('', 42, REPLACE(c1, x'ff', 'las')) FROM t1;
2047+
2048+
--error ER_CANNOT_CONVERT_STRING
2049+
SELECT HEX(SUBSTRING_INDEX(_utf8mb4 x'41F09F8DA3F09F8DA3' , x'f0', 2)) FROM t1;
2050+
20442051
DROP TABLE t1;
20452052

2053+
--error ER_CANNOT_CONVERT_STRING
2054+
SELECT TRIM(BOTH x'f0' FROM _utf8mb4 x'F09F8DA3F09F8DA3');
2055+
2056+
SELECT TRIM(BOTH x'F09F8DA3' FROM _utf8mb4 x'F09F8DA3F09F8DA3');
2057+
20462058
--error ER_CANNOT_CONVERT_STRING
20472059
SELECT TRIM(_latin2 x'a3' from _latin1 "hello");
20482060
--error ER_CANNOT_CONVERT_STRING

sql/item_strfunc.cc

Lines changed: 57 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,47 @@ static void report_conversion_error(const CHARSET_INFO *to_cs, const char *from,
120120
to_name);
121121
}
122122

123+
/**
124+
Convert and/or validate input_string according to charset 'to_cs'.
125+
126+
If input_string needs conversion to 'to_cs' then do the conversion,
127+
and verify the result.
128+
Otherwise, if input_string has charset my_charset_bin, then verify
129+
that it contains a valid string according to 'to_cs'.
130+
131+
Will call my_error() in case conversion/validation fails.
132+
133+
@param input_string string to be converted/validated.
134+
@param to_cs result character set
135+
@param output_string [out] output result variable
136+
137+
@return nullptr in case of error, otherwise pointer to result.
138+
*/
139+
static String *convert_or_validate_string(String *input_string,
140+
const CHARSET_INFO *to_cs,
141+
String *output_string) {
142+
String *retval = input_string;
143+
if (input_string->needs_conversion(to_cs)) {
144+
uint errors = 0;
145+
output_string->copy(input_string->ptr(), input_string->length(),
146+
input_string->charset(), to_cs, &errors);
147+
if (errors) {
148+
report_conversion_error(to_cs, input_string->ptr(),
149+
input_string->length(), input_string->charset());
150+
return nullptr;
151+
}
152+
retval = output_string;
153+
} else if (to_cs != &my_charset_bin &&
154+
input_string->charset() == &my_charset_bin) {
155+
if (!input_string->is_valid_string(to_cs)) {
156+
report_conversion_error(to_cs, input_string->ptr(),
157+
input_string->length(), input_string->charset());
158+
return nullptr;
159+
}
160+
}
161+
return retval;
162+
}
163+
123164
/*
124165
For the Items which have only val_str_ascii() method
125166
and don't have their own "native" val_str(),
@@ -1127,33 +1168,14 @@ String *Item_func_replace::val_str(String *str) {
11271168
tmp_value_res.set_charset(collation.collation);
11281169
String *result = &tmp_value_res;
11291170

1130-
char res2_buff[STRING_BUFFER_USUAL_SIZE];
1131-
String res2_converted(res2_buff, sizeof(res2_buff), nullptr);
1132-
char res3_buff[STRING_BUFFER_USUAL_SIZE];
1133-
String res3_converted(res3_buff, sizeof(res3_buff), nullptr);
1134-
uint errors = 0;
1171+
StringBuffer<STRING_BUFFER_USUAL_SIZE> res2_converted(nullptr);
1172+
StringBuffer<STRING_BUFFER_USUAL_SIZE> res3_converted(nullptr);
11351173

1136-
if (res2->needs_conversion(collation.collation)) {
1137-
res2_converted.copy(res2->ptr(), res2->length(), res2->charset(),
1138-
collation.collation, &errors);
1139-
if (errors) {
1140-
report_conversion_error(collation.collation, res2->ptr(), res2->length(),
1141-
res2->charset());
1142-
return error_str();
1143-
}
1144-
res2 = &res2_converted;
1145-
}
1174+
res2 = convert_or_validate_string(res2, collation.collation, &res2_converted);
1175+
if (res2 == nullptr) return error_str();
11461176

1147-
if (res3->needs_conversion(collation.collation)) {
1148-
res3_converted.copy(res3->ptr(), res3->length(), res3->charset(),
1149-
collation.collation, &errors);
1150-
if (errors) {
1151-
report_conversion_error(collation.collation, res3->ptr(), res3->length(),
1152-
res3->charset());
1153-
return error_str();
1154-
}
1155-
res3 = &res3_converted;
1156-
}
1177+
res3 = convert_or_validate_string(res3, collation.collation, &res3_converted);
1178+
if (res3 == nullptr) return error_str();
11571179

11581180
THD *thd = current_thd;
11591181
const unsigned long max_size = thd->variables.max_allowed_packet;
@@ -1520,21 +1542,11 @@ String *Item_func_substr_index::val_str(String *str) {
15201542

15211543
res->set_charset(collation.collation);
15221544

1523-
char delimiter_buff[STRING_BUFFER_USUAL_SIZE];
1524-
String delimiter_converted(delimiter_buff, sizeof(delimiter_buff), nullptr);
1525-
uint errors = 0;
1526-
if (delimiter->needs_conversion(collation.collation)) {
1527-
delimiter_converted.copy(delimiter->ptr(), delimiter->length(),
1528-
delimiter->charset(), collation.collation,
1529-
&errors);
1530-
if (errors) {
1531-
report_conversion_error(collation.collation, delimiter->ptr(),
1532-
delimiter->length(), delimiter->charset());
1533-
return error_str();
1534-
}
1535-
delimiter = &delimiter_converted;
1536-
delimiter_length = delimiter->length();
1537-
}
1545+
StringBuffer<STRING_BUFFER_USUAL_SIZE> delimiter_converted(nullptr);
1546+
delimiter = convert_or_validate_string(delimiter, collation.collation,
1547+
&delimiter_converted);
1548+
if (delimiter == nullptr) return error_str();
1549+
delimiter_length = delimiter->length();
15381550

15391551
Integer_value count_val(count, args[2]->unsigned_flag);
15401552

@@ -1636,26 +1648,16 @@ String *Item_func_trim::val_str(String *str) {
16361648

16371649
char buff[MAX_FIELD_WIDTH];
16381650
String tmp(buff, sizeof(buff), system_charset_info);
1639-
const String *remove_str = &remove; // Default value.
1651+
String *remove_str = &remove; // Default value.
16401652

1641-
char remove_buff[STRING_BUFFER_USUAL_SIZE];
1642-
String remove_converted(remove_buff, sizeof(remove_buff), nullptr);
1643-
uint errors = 0;
1653+
StringBuffer<STRING_BUFFER_USUAL_SIZE> remove_converted(nullptr);
16441654

16451655
if (arg_count == 2) {
16461656
remove_str = args[1]->val_str(&tmp);
16471657
if ((null_value = args[1]->null_value)) return NULL;
1648-
if (remove_str->needs_conversion(collation.collation)) {
1649-
remove_converted.copy(remove_str->ptr(), remove_str->length(),
1650-
remove_str->charset(), collation.collation,
1651-
&errors);
1652-
if (errors) {
1653-
report_conversion_error(collation.collation, remove_str->ptr(),
1654-
remove_str->length(), remove_str->charset());
1655-
return error_str();
1656-
}
1657-
remove_str = &remove_converted;
1658-
}
1658+
remove_str = convert_or_validate_string(remove_str, collation.collation,
1659+
&remove_converted);
1660+
if (remove_str == nullptr) return error_str();
16591661
}
16601662

16611663
const size_t remove_length = remove_str->length();

0 commit comments

Comments
 (0)