From e5f893c666cda3c4adebfdf36fe1ac0b500a5de4 Mon Sep 17 00:00:00 2001 From: Olernov Date: Thu, 18 May 2017 18:42:05 +0300 Subject: [PATCH] Bug #85588: When using rlike operator to detect characters with hex values between 80 and FF, it does not work when converting a binary string that starts with hexadecimal '00' using unhex function. --- client/mysqltest.cc | 4 ++-- mysql-test/r/func_regexp.result | 3 +++ mysql-test/t/func_regexp.test | 10 ++++++++++ rapid/plugin/x/src/xpl_regex.cc | 2 +- regex/engine.c | 5 +++-- regex/engine.ih | 2 +- regex/main.c | 4 ++-- regex/my_regex.h | 2 +- regex/regexec.c | 7 ++++--- sql/item_cmpfunc.cc | 2 +- 10 files changed, 28 insertions(+), 13 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index f472b0fc320..1a1ff96b7e4 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -8805,7 +8805,7 @@ int match_re(my_regex_t *re, char *str) str= comm_end + 2; } - int err= my_regexec(re, str, (size_t)0, NULL, 0); + int err= my_regexec(re, str, strlen(str), (size_t)0, NULL, 0); if (err == 0) return 1; @@ -10332,7 +10332,7 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, while (!err_code) { /* find the match */ - err_code= my_regexec(&r,str_p, r.re_nsub+1, subs, + err_code= my_regexec(&r,str_p, strlen(str_p), r.re_nsub+1, subs, (str_p != string) ? MY_REG_NOTBOL : 0); /* if regular expression error (eg. bad syntax, or out of memory) */ diff --git a/mysql-test/r/func_regexp.result b/mysql-test/r/func_regexp.result index 091f5025b01..177597db0ce 100644 --- a/mysql-test/r/func_regexp.result +++ b/mysql-test/r/func_regexp.result @@ -158,3 +158,6 @@ SELECT ' ' REGEXP '[[:space:]]'; SELECT '\t' REGEXP '[[:space:]]'; '\t' REGEXP '[[:space:]]' 1 +SELECT (CONVERT(UNHEX('00149D5554') USING BINARY) RLIKE CONCAT('[', UNHEX('80'), '-', UNHEX('FF'), ']')); +(CONVERT(UNHEX('00149D5554') USING BINARY) RLIKE CONCAT('[', UNHEX('80'), '-', UNHEX('FF'), ']')) +1 diff --git a/mysql-test/t/func_regexp.test b/mysql-test/t/func_regexp.test index 42462859e49..1a94e4bbd63 100644 --- a/mysql-test/t/func_regexp.test +++ b/mysql-test/t/func_regexp.test @@ -111,3 +111,13 @@ SELECT '\t' REGEXP '[[:blank:]]'; SELECT ' ' REGEXP '[[:space:]]'; SELECT '\t' REGEXP '[[:space:]]'; + +# +# Bug #85588: When using rlike operator to detect characters with hex values +# between 80 and FF, it does not work when converting a binary string that +# starts with hexadecimal '00' using unhex function. +# This test verifies that binary string having hexadecimal 00 byte is +# processed correctly. + +SELECT (CONVERT(UNHEX('00149D5554') USING BINARY) RLIKE CONCAT('[', UNHEX('80'), '-', UNHEX('FF'), ']')); + diff --git a/rapid/plugin/x/src/xpl_regex.cc b/rapid/plugin/x/src/xpl_regex.cc index 3cad8fb8bdc..600528ed94b 100644 --- a/rapid/plugin/x/src/xpl_regex.cc +++ b/rapid/plugin/x/src/xpl_regex.cc @@ -57,6 +57,6 @@ xpl::Regex::~Regex() bool xpl::Regex::match(const char *value) const { - return my_regexec(&m_re, value, (size_t)0, NULL, 0) == 0; + return my_regexec(&m_re, value, strlen(value), (size_t)0, NULL, 0) == 0; } diff --git a/regex/engine.c b/regex/engine.c index 47c71940110..bb7820b457a 100644 --- a/regex/engine.c +++ b/regex/engine.c @@ -63,10 +63,11 @@ struct match { == size_t nmatch, regmatch_t pmatch[], int eflags); */ static int /* 0 success, MY_REG_NOMATCH failure */ -matcher(charset,g, str, nmatch, pmatch, eflags) +matcher(charset,g, str, strlength, nmatch, pmatch, eflags) const CHARSET_INFO *charset; struct re_guts *g; char *str; +size_t strlength; size_t nmatch; my_regmatch_t pmatch[]; int eflags; @@ -89,7 +90,7 @@ int eflags; stop = str + pmatch[0].rm_eo; } else { start = str; - stop = start + strlen(start); + stop = start + strlength; } if (stop < start) return(MY_REG_INVARG); diff --git a/regex/engine.ih b/regex/engine.ih index 6d17c1f0927..336f0e63a2c 100644 --- a/regex/engine.ih +++ b/regex/engine.ih @@ -5,7 +5,7 @@ extern "C" { /* === engine.c === */ static int matcher(const CHARSET_INFO *charset,struct re_guts *g, - char *string, size_t nmatch, my_regmatch_t pmatch[], + char *string, size_t strlength, size_t nmatch, my_regmatch_t pmatch[], int eflags); static char *dissect(const CHARSET_INFO *charset, struct match *m, char *start, char *stop, sopno startst, sopno stopst); diff --git a/regex/main.c b/regex/main.c index a39d70e0c73..ba62b1f7a3a 100644 --- a/regex/main.c +++ b/regex/main.c @@ -153,7 +153,7 @@ char *argv[]; subs[0].rm_so = startoff; subs[0].rm_eo = strlen(argv[optind]) - endoff; } - err = my_regexec(&re, argv[optind], (size_t)NS, subs, eopts); + err = my_regexec(&re, argv[optind], strlen(argv[optind]), (size_t)NS, subs, eopts); if (err) { len = my_regerror(err, &re, erbuf, sizeof(erbuf)); fprintf(stderr, "error %s, %d/%d `%s'\n", @@ -333,7 +333,7 @@ int opts; /* may not match f1 */ subs[0].rm_so = strchr(f2, '(') - f2 + 1; subs[0].rm_eo = strchr(f2, ')') - f2; } - err = my_regexec(&re, f2copy, NSUBS, subs, options('e', f1)); + err = my_regexec(&re, f2copy, strlen(f2copy), NSUBS, subs, options('e', f1)); if (err != 0 && (f3 != NULL || err != MY_REG_NOMATCH)) { /* unexpected error or wrong error */ diff --git a/regex/my_regex.h b/regex/my_regex.h index c0282844cf2..c0bb52513e5 100644 --- a/regex/my_regex.h +++ b/regex/my_regex.h @@ -66,7 +66,7 @@ extern size_t my_regerror(int, const my_regex_t *, char *, size_t); /* === regexec.c === */ -extern int my_regexec(const my_regex_t *, const char *, size_t, my_regmatch_t [], int); +extern int my_regexec(const my_regex_t *, const char *, size_t, size_t, my_regmatch_t [], int); #define MY_REG_NOTBOL 00001 #define MY_REG_NOTEOL 00002 #define MY_REG_STARTEND 00004 diff --git a/regex/regexec.c b/regex/regexec.c index 92bfd5e1ec6..5ff6e07370f 100644 --- a/regex/regexec.c +++ b/regex/regexec.c @@ -138,9 +138,10 @@ @return 0 success, MY_REG_NOMATCH failure */ int -my_regexec(preg, str, nmatch, pmatch, eflags) +my_regexec(preg, str, strlength, nmatch, pmatch, eflags) const my_regex_t *preg; const char *str; +size_t strlength; size_t nmatch; my_regmatch_t pmatch[]; int eflags; @@ -162,7 +163,7 @@ int eflags; if ((size_t) g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&MY_REG_LARGE)) - return(smatcher(preg->charset, g, pstr, nmatch, pmatch, eflags)); + return(smatcher(preg->charset, g, pstr, strlength, nmatch, pmatch, eflags)); else - return(lmatcher(preg->charset, g, pstr, nmatch, pmatch, eflags)); + return(lmatcher(preg->charset, g, pstr, strlength, nmatch, pmatch, eflags)); } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 0b90d3e676d..d5a6875adb2 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -6751,7 +6751,7 @@ longlong Item_func_regex::val_int() } res= &conv; } - return my_regexec(&preg,res->c_ptr_safe(),0,(my_regmatch_t*) 0,0) ? 0 : 1; + return my_regexec(&preg, res->c_ptr_safe(), res->length(), 0, (my_regmatch_t*) 0, 0) ? 0 : 1; }