From 7ad0e1c52795f1afb4c545f43dd1996d8ca41145 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Tue, 5 Nov 2013 10:02:57 +0100 Subject: [PATCH] Bug#12368495 CRASH AND/OR VALGRIND ERRORS WITH REVERSE FUNCTION AND CHARSET CONVERTS Item_func_trim::val_str: we were using the non-mb algorithm for skipping leading spaces in a multibyte-charset string. --- sql/item_strfunc.cc | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 363ca02fd7a..ae93f060956 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1005,6 +1005,7 @@ String *Item_func_reverse::val_str(String *str) if ((l= my_ismbchar(res->charset(),ptr,end))) { tmp-= l; + DBUG_ASSERT(tmp >= tmp_value.ptr()); memcpy(tmp,ptr,l); ptr+= l; } @@ -1751,18 +1752,35 @@ String *Item_func_trim::val_str(String *str) 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())) { + 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))) ptr+=l; - else ++ptr; + if ((l= my_ismbchar(res->charset(), ptr,end))) + ptr+= l; + else + ++ptr; } if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length)) { @@ -1775,6 +1793,8 @@ 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;