From f70de1451ba24e0459edcdbe2e67e3df5f348050 Mon Sep 17 00:00:00 2001
From: Weijun Huang <huangweijun1001@gmail.com>
Date: Sat, 11 Mar 2023 11:06:03 +0100
Subject: [PATCH] MDEV-30351 crash in Item_func_left::val_str

When using LEFT() function with a string that is without a charset,
the function crashes. This is because the function assumes that
the string has a charset, and tries to use it to calculate the
length of the string.

Two functions, UNHEX and WEIGHT_STRING, returned a string without
the charset being set to a not null value.

The fix is to set charset when calling val_str on these two functions.

Reviewed-by: Alexander Barkov <bar@mariadb.com>
Reviewed-by: Daniel Black <daniel@mariadb.org>
---
 mysql-test/main/func_str.result |  9 +++++++++
 mysql-test/main/func_str.test   | 10 ++++++++--
 sql/item_strfunc.cc             |  2 ++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result
index 2f692f9135e..4e36acd25ca 100644
--- a/mysql-test/main/func_str.result
+++ b/mysql-test/main/func_str.result
@@ -5240,6 +5240,15 @@ DROP TABLE crash_test_2;
 # Start of 10.4 tests
 #
 #
+# MDEV-30351 crash in Item_func_left::val_str
+#
+SELECT WEIGHT_STRING('aa') IN (LEFT(WEIGHT_STRING('aaa'),4),'bbb') as expect_1;
+expect_1
+1
+SELECT UNHEX('0032') in (LEFT(UNHEX('003200'), 2),'dog') as expect_1;
+expect_1
+1
+#
 # MDEV-21841 CONV() function truncates the result type to 21 symbol.
 #
 CREATE TABLE t1(i BIGINT);
diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test
index 910214901e5..da3483dd08a 100644
--- a/mysql-test/main/func_str.test
+++ b/mysql-test/main/func_str.test
@@ -2256,16 +2256,22 @@ CREATE TABLE crash_test_2 (
 DROP TABLE t1;
 DROP TABLE crash_test_2;
 
-
 --echo #
 --echo # End of 10.3 tests
 --echo #
 
-
 --echo #
 --echo # Start of 10.4 tests
 --echo #
 
+--echo #
+--echo # MDEV-30351 crash in Item_func_left::val_str
+--echo #
+
+SELECT WEIGHT_STRING('aa') IN (LEFT(WEIGHT_STRING('aaa'),4),'bbb') as expect_1;
+
+SELECT UNHEX('0032') in (LEFT(UNHEX('003200'), 2),'dog') as expect_1;
+
 --echo #
 --echo # MDEV-21841 CONV() function truncates the result type to 21 symbol.
 --echo #
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index a57fbd7bebc..f95f4795820 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -3729,6 +3729,7 @@ String *Item_func_weight_string::val_str(String *str)
                                  flags);
   DBUG_ASSERT(frm_length <= tmp_length);
 
+  str->set_charset(&my_charset_bin);
   str->length(frm_length);
   null_value= 0;
   return str;
@@ -3808,6 +3809,7 @@ String *Item_func_unhex::val_str(String *str)
 
   from= res->ptr();
   null_value= 0;
+  str->set_charset(&my_charset_bin);
   str->length(length);
   to= (char*) str->ptr();
   if (res->length() % 2)