From 14bedf3ee5a29d14b1041f2f93dad24ca58c551f Mon Sep 17 00:00:00 2001 From: Hangjie Mo Date: Mon, 21 Feb 2022 17:35:43 +0800 Subject: [PATCH] expression: fix panic in upper() and lower() func. (#32505) close pingcap/tidb#32488 --- expression/builtin_string_vec.go | 34 ++++++++++++++++++++++++++------ expression/integration_test.go | 16 +++++++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/expression/builtin_string_vec.go b/expression/builtin_string_vec.go index 5484d46f953e5..8232fa36754b1 100644 --- a/expression/builtin_string_vec.go +++ b/expression/builtin_string_vec.go @@ -43,12 +43,23 @@ func (b *builtinLowerSig) vectorized() bool { } func (b *builtinLowerUTF8Sig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { - if err := b.args[0].VecEvalString(b.ctx, input, result); err != nil { + n := input.NumRows() + buf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(buf) + if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil { return err } + result.ReserveString(n) enc := charset.FindEncoding(b.args[0].GetType().Charset) - for i := 0; i < input.NumRows(); i++ { - result.SetRaw(i, []byte(enc.ToLower(result.GetString(i)))) + for i := 0; i < n; i++ { + if buf.IsNull(i) { + result.AppendNull() + } else { + result.AppendString(enc.ToLower(buf.GetString(i))) + } } return nil } @@ -144,12 +155,23 @@ func (b *builtinStringIsNullSig) vectorized() bool { } func (b *builtinUpperUTF8Sig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { - if err := b.args[0].VecEvalString(b.ctx, input, result); err != nil { + n := input.NumRows() + buf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(buf) + if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil { return err } + result.ReserveString(n) enc := charset.FindEncoding(b.args[0].GetType().Charset) - for i := 0; i < input.NumRows(); i++ { - result.SetRaw(i, []byte(enc.ToUpper(result.GetString(i)))) + for i := 0; i < n; i++ { + if buf.IsNull(i) { + result.AppendNull() + } else { + result.AppendString(enc.ToUpper(buf.GetString(i))) + } } return nil } diff --git a/expression/integration_test.go b/expression/integration_test.go index f3f4ee44e32a7..7091f50818c4f 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -7043,3 +7043,19 @@ func TestIssue22206(t *testing.T) { unixTime = time.Unix(5000000000, 0).In(tz).String()[:19] result.Check(testkit.Rows(unixTime)) } + +func TestIssue32488(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a varchar(32)) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;") + tk.MustExec("insert into t values('ʞ'), ('İ');") + tk.MustExec("set @@tidb_enable_vectorized_expression = false;") + tk.MustQuery("select binary upper(a), lower(a) from t order by upper(a);").Check([][]interface{}{{"İ i"}, {"Ʞ ʞ"}}) + tk.MustQuery("select distinct upper(a), lower(a) from t order by upper(a);").Check([][]interface{}{{"İ i"}, {"Ʞ ʞ"}}) + tk.MustExec("set @@tidb_enable_vectorized_expression = true;") + tk.MustQuery("select binary upper(a), lower(a) from t order by upper(a);").Check([][]interface{}{{"İ i"}, {"Ʞ ʞ"}}) + tk.MustQuery("select distinct upper(a), lower(a) from t order by upper(a);").Check([][]interface{}{{"İ i"}, {"Ʞ ʞ"}}) +}