mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01:00
Bug#27079 Crash while grouping empty ucs2 strings
Problem: GROUP BY on empty ucs2 strings crashed server. Reason: sometimes mi_unique_hash() is executed with ptr=null and length=0, which means "empty string". The branch of code handling UCS2 character set was not safe against ptr=null and fell into and endless loop even if length=0 because of poiter arithmetic overflow. Fix: adding special check for length=0 to avoid pointer arithmetic overflow.
This commit is contained in:
parent
f0a95a4e20
commit
1b426d3c6d
3 changed files with 46 additions and 7 deletions
|
@ -2654,3 +2654,12 @@ ii 2 ii 2 İİ 4
|
|||
İİ 4 ii 2 İİ 4
|
||||
II 2 ıı 4 II 2
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
c1 text character set ucs2 collate ucs2_polish_ci NOT NULL
|
||||
) ENGINE=MyISAM;
|
||||
insert into t1 values (''),('a');
|
||||
SELECT COUNT(*), c1 FROM t1 GROUP BY c1;
|
||||
COUNT(*) c1
|
||||
1
|
||||
1 a
|
||||
DROP TABLE IF EXISTS t1;
|
||||
|
|
|
@ -475,3 +475,13 @@ ALTER TABLE t1 MODIFY a VARCHAR(30) character set utf8 collate utf8_turkish_ci;
|
|||
SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
|
||||
FROM t1 ORDER BY id;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug #27079 Crash while grouping empty ucs2 strings
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
c1 text character set ucs2 collate ucs2_polish_ci NOT NULL
|
||||
) ENGINE=MyISAM;
|
||||
insert into t1 values (''),('a');
|
||||
SELECT COUNT(*), c1 FROM t1 GROUP BY c1;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
|
|
|
@ -6744,7 +6744,7 @@ typedef struct my_uca_scanner_handler_st
|
|||
int (*next)(my_uca_scanner *scanner);
|
||||
} my_uca_scanner_handler;
|
||||
|
||||
static uint16 nochar[]= {0};
|
||||
static uint16 nochar[]= {0,0};
|
||||
|
||||
|
||||
#ifdef HAVE_CHARSET_ucs2
|
||||
|
@ -6769,13 +6769,33 @@ static void my_uca_scanner_init_ucs2(my_uca_scanner *scanner,
|
|||
CHARSET_INFO *cs __attribute__((unused)),
|
||||
const uchar *str, uint length)
|
||||
{
|
||||
/* Note, no needs to initialize scanner->wbeg */
|
||||
scanner->sbeg= str;
|
||||
scanner->send= str + length - 2;
|
||||
scanner->wbeg= nochar;
|
||||
scanner->uca_length= cs->sort_order;
|
||||
scanner->uca_weight= cs->sort_order_big;
|
||||
scanner->contractions= cs->contractions;
|
||||
if (length)
|
||||
{
|
||||
scanner->sbeg= str;
|
||||
scanner->send= str + length - 2;
|
||||
scanner->uca_length= cs->sort_order;
|
||||
scanner->uca_weight= cs->sort_order_big;
|
||||
scanner->contractions= cs->contractions;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Sometimes this function is called with
|
||||
str=NULL and length=0, which should be
|
||||
considered as an empty string.
|
||||
|
||||
The above initialization is unsafe for such cases,
|
||||
because scanner->send is initialized to (NULL-2), which is 0xFFFFFFFE.
|
||||
Then we fall into an endless loop in my_uca_scanner_next_ucs2().
|
||||
|
||||
Do special initialization for the case when length=0.
|
||||
Initialize scanner->sbeg to an address greater than scanner->send.
|
||||
Next call of my_uca_scanner_next_ucs2() will correctly return with -1.
|
||||
*/
|
||||
scanner->sbeg= (uchar*) &nochar[1];
|
||||
scanner->send= (uchar*) &nochar[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue