summaryrefslogtreecommitdiff
path: root/sql/item_strfunc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r--sql/item_strfunc.cc252
1 files changed, 137 insertions, 115 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index fa6ba706718..9a3c7589db2 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -179,16 +179,27 @@ String *Item_func_md5::val_str_ascii(String *str)
}
+/*
+ The MD5()/SHA() functions treat their parameter as being a case sensitive.
+ Thus we set binary collation on it so different instances of MD5() will be
+ compared properly.
+*/
+static CHARSET_INFO *get_checksum_charset(const char *csname)
+{
+ CHARSET_INFO *cs= get_charset_by_csname(csname, MY_CS_BINSORT, MYF(0));
+ if (!cs)
+ {
+ // Charset has no binary collation: use my_charset_bin.
+ cs= &my_charset_bin;
+ }
+ return cs;
+}
+
+
void Item_func_md5::fix_length_and_dec()
{
- /*
- The MD5() function treats its parameter as being a case sensitive. Thus
- we set binary collation on it so different instances of MD5() will be
- compared properly.
- */
- args[0]->collation.set(
- get_charset_by_csname(args[0]->collation.collation->csname,
- MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
+ CHARSET_INFO *cs= get_checksum_charset(args[0]->collation.collation->csname);
+ args[0]->collation.set(cs, DERIVATION_COERCIBLE);
fix_length_and_charset(32, default_charset());
}
@@ -218,14 +229,8 @@ String *Item_func_sha::val_str_ascii(String *str)
void Item_func_sha::fix_length_and_dec()
{
- /*
- The SHA() function treats its parameter as being a case sensitive. Thus
- we set binary collation on it so different instances of MD5() will be
- compared properly.
- */
- args[0]->collation.set(
- get_charset_by_csname(args[0]->collation.collation->csname,
- MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
+ CHARSET_INFO *cs= get_checksum_charset(args[0]->collation.collation->csname);
+ args[0]->collation.set(cs, DERIVATION_COERCIBLE);
// size of hex representation of hash
fix_length_and_charset(SHA1_HASH_SIZE * 2, default_charset());
}
@@ -348,18 +353,9 @@ void Item_func_sha2::fix_length_and_dec()
ER(ER_WRONG_PARAMETERS_TO_NATIVE_FCT), "sha2");
}
- /*
- The SHA2() function treats its parameter as being a case sensitive.
- Thus we set binary collation on it so different instances of SHA2()
- will be compared properly.
- */
+ CHARSET_INFO *cs= get_checksum_charset(args[0]->collation.collation->csname);
+ args[0]->collation.set(cs, DERIVATION_COERCIBLE);
- args[0]->collation.set(
- get_charset_by_csname(
- args[0]->collation.collation->csname,
- MY_CS_BINSORT,
- MYF(0)),
- DERIVATION_COERCIBLE);
#else
push_warning_printf(current_thd,
Sql_condition::WARN_LEVEL_WARN,
@@ -513,39 +509,42 @@ void Item_func_from_base64::fix_length_and_dec()
String *Item_func_from_base64::val_str(String *str)
{
String *res= args[0]->val_str_ascii(str);
- bool too_long= false;
int length;
const char *end_ptr;
- if (!res ||
- res->length() > (uint) base64_decode_max_arg_length() ||
- (too_long=
- ((uint) (length= base64_needed_decoded_length((int) res->length())) >
- current_thd->variables.max_allowed_packet)) ||
- tmp_value.alloc((uint) length) ||
- (length= base64_decode(res->ptr(), (int) res->length(),
+ if (!res)
+ goto err;
+
+ if (res->length() > (uint) base64_decode_max_arg_length() ||
+ ((uint) (length= base64_needed_decoded_length((int) res->length())) >
+ current_thd->variables.max_allowed_packet))
+ {
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
+ current_thd->variables.max_allowed_packet);
+ goto err;
+ }
+
+ if (tmp_value.alloc((uint) length))
+ goto err;
+
+ if ((length= base64_decode(res->ptr(), (int) res->length(),
(char *) tmp_value.ptr(), &end_ptr, 0)) < 0 ||
end_ptr < res->ptr() + res->length())
{
- null_value= 1; // NULL input, too long input, OOM, or badly formed input
- if (too_long)
- {
- push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
- ER_WARN_ALLOWED_PACKET_OVERFLOWED,
- ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
- current_thd->variables.max_allowed_packet);
- }
- else if (res && length < 0)
- {
- push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
- ER_BAD_BASE64_DATA, ER(ER_BAD_BASE64_DATA),
- end_ptr - res->ptr());
- }
- return 0;
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_BAD_BASE64_DATA, ER(ER_BAD_BASE64_DATA),
+ end_ptr - res->ptr());
+ goto err;
}
+
tmp_value.length((uint) length);
null_value= 0;
return &tmp_value;
+err:
+ null_value= 1; // NULL input, too long input, OOM, or badly formed input
+ return 0;
}
///////////////////////////////////////////////////////////////////////////////
@@ -598,7 +597,7 @@ String *Item_func_decode_histogram::val_str(String *str)
val= p[i] / ((double)((1 << 8) - 1));
break;
case DOUBLE_PREC_HB:
- val= ((uint16 *)(p + i))[0] / ((double)((1 << 16) - 1));
+ val= uint2korr(p + i) / ((double)((1 << 16) - 1));
i++;
break;
default:
@@ -1962,7 +1961,7 @@ String *Item_func_ltrim::val_str(String *str)
if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length())
- return res;
+ return non_trimmed_value(res);
ptr= (char*) res->ptr();
end= ptr+res->length();
@@ -1981,9 +1980,8 @@ String *Item_func_ltrim::val_str(String *str)
end+=remove_length;
}
if (ptr == res->ptr())
- return res;
- tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr));
- return &tmp_value;
+ return non_trimmed_value(res);
+ return trimmed_value(res, (uint32) (ptr - res->ptr()), (uint32) (end - ptr));
}
@@ -2009,7 +2007,7 @@ String *Item_func_rtrim::val_str(String *str)
if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length())
- return res;
+ return non_trimmed_value(res);
ptr= (char*) res->ptr();
end= ptr+res->length();
@@ -2021,11 +2019,11 @@ String *Item_func_rtrim::val_str(String *str)
{
char chr=(*remove_str)[0];
#ifdef USE_MB
- if (use_mb(res->charset()))
+ if (use_mb(collation.collation))
{
while (ptr < end)
{
- if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l,p=ptr;
+ if ((l= my_ismbchar(collation.collation, ptr, end))) ptr+= l, p=ptr;
else ++ptr;
}
ptr=p;
@@ -2038,12 +2036,12 @@ String *Item_func_rtrim::val_str(String *str)
{
const char *r_ptr=remove_str->ptr();
#ifdef USE_MB
- if (use_mb(res->charset()))
+ if (use_mb(collation.collation))
{
loop:
while (ptr + remove_length < end)
{
- if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
+ if ((l= my_ismbchar(collation.collation, ptr, end))) ptr+= l;
else ++ptr;
}
if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
@@ -2062,9 +2060,8 @@ String *Item_func_rtrim::val_str(String *str)
}
}
if (end == res->ptr()+res->length())
- return res;
- tmp_value.set(*res,0,(uint) (end-res->ptr()));
- return &tmp_value;
+ return non_trimmed_value(res);
+ return trimmed_value(res, 0, (uint32) (end - res->ptr()));
}
@@ -2091,37 +2088,22 @@ String *Item_func_trim::val_str(String *str)
if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length())
- return res;
+ return non_trimmed_value(res);
ptr= (char*) res->ptr();
end= ptr+res->length();
r_ptr= remove_str->ptr();
+ while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
+ ptr+=remove_length;
#ifdef USE_MB
- if (use_mb(res->charset()))
+ if (use_mb(collation.collation))
{
- while (ptr + remove_length <= end)
- {
- uint num_bytes= 0;
- while (num_bytes < remove_length)
- {
- uint len;
- if ((len= my_ismbchar(res->charset(), ptr + num_bytes, end)))
- num_bytes+= len;
- else
- ++num_bytes;
- }
- if (num_bytes != remove_length)
- break;
- if (memcmp(ptr, r_ptr, remove_length))
- break;
- ptr+= remove_length;
- }
char *p=ptr;
register uint32 l;
loop:
while (ptr + remove_length < end)
{
- if ((l= my_ismbchar(res->charset(), ptr,end)))
+ if ((l= my_ismbchar(collation.collation, ptr, end)))
ptr+= l;
else
++ptr;
@@ -2137,16 +2119,13 @@ String *Item_func_trim::val_str(String *str)
else
#endif /* USE_MB */
{
- while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
- ptr+=remove_length;
while (ptr + remove_length <= end &&
!memcmp(end-remove_length,r_ptr,remove_length))
end-=remove_length;
}
if (ptr == res->ptr() && end == ptr+res->length())
- return res;
- tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr));
- return &tmp_value;
+ return non_trimmed_value(res);
+ return trimmed_value(res, (uint32) (ptr - res->ptr()), (uint32) (end - ptr));
}
void Item_func_trim::fix_length_and_dec()
@@ -2348,32 +2327,6 @@ void Item_func_decode::crypto_transform(String *res)
}
-Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs)
-{
- Item_string *conv;
- uint conv_errors;
- String tmp, cstr, *ostr= val_str(&tmp);
- if (null_value)
- {
- Item *null_item= new Item_null((char *) fully_qualified_func_name());
- null_item->collation.set (tocs);
- return null_item;
- }
- cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
- if (conv_errors ||
- !(conv= new Item_static_string_func(fully_qualified_func_name(),
- cstr.ptr(), cstr.length(),
- cstr.charset(),
- collation.derivation)))
- {
- return NULL;
- }
- conv->str_value.copy();
- conv->str_value.mark_as_const();
- return conv;
-}
-
-
String *Item_func_database::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -3045,6 +2998,75 @@ err:
}
+void Item_func_space::fix_length_and_dec()
+{
+ collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
+ if (args[0]->const_item())
+ {
+ /* must be longlong to avoid truncation */
+ longlong count= args[0]->val_int();
+ if (args[0]->null_value)
+ goto end;
+ /*
+ Assumes that the maximum length of a String is < INT_MAX32.
+ Set here so that rest of code sees out-of-bound value as such.
+ */
+ if (count > INT_MAX32)
+ count= INT_MAX32;
+ fix_char_length_ulonglong(count);
+ return;
+ }
+
+end:
+ max_length= MAX_BLOB_WIDTH;
+ maybe_null= 1;
+}
+
+
+String *Item_func_space::val_str(String *str)
+{
+ uint tot_length;
+ longlong count= args[0]->val_int();
+ const CHARSET_INFO *cs= collation.collation;
+
+ if (args[0]->null_value)
+ goto err; // string and/or delim are null
+ null_value= 0;
+
+ if (count <= 0 && (count == 0 || !args[0]->unsigned_flag))
+ return make_empty_result();
+ /*
+ Assumes that the maximum length of a String is < INT_MAX32.
+ Bounds check on count: If this is triggered, we will error.
+ */
+ if ((ulonglong) count > INT_MAX32)
+ count= INT_MAX32;
+
+ // Safe length check
+ tot_length= (uint) count * cs->mbminlen;
+ if (tot_length > current_thd->variables.max_allowed_packet)
+ {
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
+ func_name(),
+ current_thd->variables.max_allowed_packet);
+ goto err;
+ }
+
+ if (str->alloc(tot_length))
+ goto err;
+ str->length(tot_length);
+ str->set_charset(cs);
+ cs->cset->fill(cs, (char*) str->ptr(), tot_length, ' ');
+ return str;
+
+err:
+ null_value= 1;
+ return 0;
+}
+
+
void Item_func_binlog_gtid_pos::fix_length_and_dec()
{
collation.set(system_charset_info);
@@ -3443,7 +3465,7 @@ void Item_func_set_collation::print(String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN(" collate "));
DBUG_ASSERT(args[1]->basic_const_item() &&
args[1]->type() == Item::STRING_ITEM);
- args[1]->str_value.print(str);
+ ((Item_string *)args[1])->print_value(str);
str->append(')');
}