MDEV-28686 Assertion `0' in Type_handler_string_result::make_sort_key or unexpected result

The code in the can_eval_in_optimize() branch in
Item_func_pad::fix_length_and_dec() did not take into account
that the constant can be negative. So the function will return NULL.

This later crashed on DBUG_ASSERT() because a NOT NULL function returned NULL.

Adding set_maybe_null() into this branch if the constant is negative.
This commit is contained in:
Alexander Barkov 2024-11-06 15:45:59 +04:00
parent 4ded2cbe13
commit b9f9d804f2
3 changed files with 55 additions and 5 deletions

View file

@ -5355,5 +5355,27 @@ HEX(INSERT(_utf8 0xD18FD18E, 2, 1, 0x20))
D120D18E
DROP VIEW v1;
#
# MDEV-28686 Assertion `0' in Type_handler_string_result::make_sort_key or unexpected result
#
CREATE TABLE t (s DATE, e DATE, PERIOD FOR p(s,e));
INSERT INTO t (s,e) VALUES ('1970-01-01','1970-01-02'),('1980-01-01','1980-01-02');
SET sql_mode='';
SELECT e, GROUP_CONCAT(s) FROM t GROUP BY CONVERT((LPAD(e, -1) AND e) USING utf8);
e GROUP_CONCAT(s)
1970-01-02 1970-01-01,1980-01-01
DROP TABLE t;
CREATE TABLE t (s DATE, e DATE, PERIOD FOR p(s,e));
INSERT INTO t (s,e) VALUES ('1970-01-01','1970-01-02'),('1980-01-01','1980-01-02');
SET sql_mode='';
SELECT DISTINCT CONVERT((LPAD(e, -1) AND e) USING utf8) FROM t;
CONVERT((LPAD(e, -1) AND e) USING utf8)
NULL
SET sql_mode=STRICT_TRANS_TABLES;
SELECT DISTINCT CONVERT((LPAD(e, -1) AND e) USING utf8) FROM t;
CONVERT((LPAD(e, -1) AND e) USING utf8)
NULL
DROP TABLE t;
SET sql_mode=DEFAULT;
#
# End of 10.6 tests
#

View file

@ -2402,6 +2402,24 @@ CREATE VIEW v1 AS SELECT HEX(INSERT(_utf8 0xD18FD18E, 2, 1, 0x20));
SELECT * FROM v1;
DROP VIEW v1;
--echo #
--echo # MDEV-28686 Assertion `0' in Type_handler_string_result::make_sort_key or unexpected result
--echo #
CREATE TABLE t (s DATE, e DATE, PERIOD FOR p(s,e));
INSERT INTO t (s,e) VALUES ('1970-01-01','1970-01-02'),('1980-01-01','1980-01-02');
SET sql_mode='';
SELECT e, GROUP_CONCAT(s) FROM t GROUP BY CONVERT((LPAD(e, -1) AND e) USING utf8);
DROP TABLE t;
CREATE TABLE t (s DATE, e DATE, PERIOD FOR p(s,e));
INSERT INTO t (s,e) VALUES ('1970-01-01','1970-01-02'),('1980-01-01','1980-01-02');
SET sql_mode='';
SELECT DISTINCT CONVERT((LPAD(e, -1) AND e) USING utf8) FROM t;
SET sql_mode=STRICT_TRANS_TABLES;
SELECT DISTINCT CONVERT((LPAD(e, -1) AND e) USING utf8) FROM t;
DROP TABLE t;
SET sql_mode=DEFAULT;
--echo #
--echo # End of 10.6 tests

View file

@ -61,13 +61,17 @@ size_t username_char_length= USERNAME_CHAR_LENGTH;
Calculate max length of string from length argument to LEFT and RIGHT
*/
static uint32 max_length_for_string(Item *item)
static uint32 max_length_for_string(Item *item, bool *neg)
{
*neg= false;
ulonglong length= item->val_int();
if (item->null_value)
return 0;
if (length > (ulonglong) LONGLONG_MAX && !item->unsigned_flag)
{
*neg= true;
return 0; // Negative
}
if (length > (ulonglong) INT_MAX32)
{
/* Limit string length to maxium string length in MariaDB (2G) */
@ -1664,7 +1668,8 @@ void Item_str_func::left_right_max_length()
uint32 char_length= args[0]->max_char_length();
if (args[1]->can_eval_in_optimize())
{
uint32 length= max_length_for_string(args[1]);
bool neg;
uint32 length= max_length_for_string(args[1], &neg);
set_if_smaller(char_length, length);
}
fix_char_length(char_length);
@ -3078,7 +3083,8 @@ bool Item_func_repeat::fix_length_and_dec()
DBUG_ASSERT(collation.collation != NULL);
if (args[1]->can_eval_in_optimize())
{
uint32 length= max_length_for_string(args[1]);
bool neg;
uint32 length= max_length_for_string(args[1], &neg);
ulonglong char_length= (ulonglong) args[0]->max_char_length() * length;
fix_char_length_ulonglong(char_length);
return false;
@ -3152,7 +3158,8 @@ bool Item_func_space::fix_length_and_dec()
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
if (args[0]->can_eval_in_optimize())
{
fix_char_length_ulonglong(max_length_for_string(args[0]));
bool neg;
fix_char_length_ulonglong(max_length_for_string(args[0], &neg));
return false;
}
max_length= MAX_BLOB_WIDTH;
@ -3278,7 +3285,10 @@ bool Item_func_pad::fix_length_and_dec()
DBUG_ASSERT(collation.collation->mbmaxlen > 0);
if (args[1]->can_eval_in_optimize())
{
fix_char_length_ulonglong(max_length_for_string(args[1]));
bool neg;
fix_char_length_ulonglong(max_length_for_string(args[1], &neg));
if (neg)
set_maybe_null();
return false;
}
max_length= MAX_BLOB_WIDTH;