Repository: pingcap/tidb (Go)

Issue:
runtime error: index out of range [18446744073709551615] with length 2
## Bug Report

### 1. Minimal reproduce step (Required)
```sql
drop table if exists t1;
set sql_mode='';
CREATE TABLE t1 (a enum('Yes', 'No') NOT NULL);
insert t1 values (0);
delete from alias using t1, t1 alias where t1.a = alias.a;
```

### 2. What did you expect to see? (Required)
No panic.

### 3. What did you see instead (Required)
Client output:
```
ERROR 1105 (HY000): runtime error: index out of range [18446744073709551615] with length 2
```
TiDB log:
```
[2021/03/01 19:43:20.401 +08:00] [ERROR] [misc.go:90] ["panic in the recoverable goroutine"] [r={}] ["stack trace"="github.com/pingcap/tidb/util.WithRecovery.func1
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/util/misc.go:92
runtime.gopanic
	/usr/local/go/src/runtime/panic.go:679
runtime.goPanicIndexU
	/usr/local/go/src/runtime/panic.go:79
github.com/pingcap/tidb/util/codec.HashChunkSelected
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/util/codec/codec.go:574
github.com/pingcap/tidb/executor.(*hashRowContainer).PutChunkSelected
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/hash_table.go:181
github.com/pingcap/tidb/executor.(*hashRowContainer).PutChunk
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/hash_table.go:160
github.com/pingcap/tidb/executor.(*HashJoinExec).buildHashTableForList
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/join.go:763
github.com/pingcap/tidb/executor.(*HashJoinExec).fetchAndBuildHashTable
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/join.go:713
github.com/pingcap/tidb/executor.(*HashJoinExec).Next.func1
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/join.go:658
github.com/pingcap/tidb/util.WithRecovery
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/util/misc.go:95"]
[2021/03/01 19:43:20.401 +08:00] [INFO] [conn.go:809] ["command dispatched failed"] [conn=3] [connInfo="id:3, addr:127.0.0.1:37894 status:10, collation:utf8_general_ci, user:root"] [command=Query] [status="inTxn:0, autocommit:1"] [sql="DELETE FROM alias USING t1, t1 alias WHERE t1.a = alias.a"] [txn_mode=PESSIMISTIC] [err="runtime error: index out of range [18446744073709551615] with length 2
github.com/pingcap/tidb/executor.(*HashJoinExec).handleFetchAndBuildHashTablePanic
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/join.go:683
github.com/pingcap/tidb/util.WithRecovery.func1
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/util/misc.go:87
runtime.gopanic
	/usr/local/go/src/runtime/panic.go:679
runtime.goPanicIndexU
	/usr/local/go/src/runtime/panic.go:79
github.com/pingcap/tidb/util/codec.HashChunkSelected
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/util/codec/codec.go:574
github.com/pingcap/tidb/executor.(*hashRowContainer).PutChunkSelected
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/hash_table.go:181
github.com/pingcap/tidb/executor.(*hashRowContainer).PutChunk
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/hash_table.go:160
github.com/pingcap/tidb/executor.(*HashJoinExec).buildHashTableForList
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/join.go:763
github.com/pingcap/tidb/executor.(*HashJoinExec).fetchAndBuildHashTable
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/join.go:713
github.com/pingcap/tidb/executor.(*HashJoinExec).Next.func1
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/executor/join.go:658
github.com/pingcap/tidb/util.WithRecovery
	/home/jenkins/agent/workspace/tidb_master/go/src/github.com/pingcap/tidb/util/misc.go:95
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:1357"]
```

### 4. What is your TiDB version? (Required)
```yaml
Release Version: v4.0.0-beta.2-2209-gfebac515b
Edition: Community
Git Commit Hash: febac515b1369643216e1efc971a262615dc4794
Git Branch: master
UTC Build Time: 2021-03-01 03:47:27
GoVersion: go1.13
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false
```




Discussion:
/cc guo-shaoge
/cc @guo-shaoge 
/assign @guo-shaoge 
@XuHuaiyu: GitHub didn't allow me to assign the following users: guo-shaoge.

Note that only [pingcap members](https://github.com/orgs/pingcap/people), repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time.
For more information please see [the contributor guide](https://git.k8s.io/community/contributors/guide/first-contribution.md#issue-assignment-in-github)

<details>

In response to [this](https://github.com/pingcap/tidb/issues/23060#issuecomment-791090249):

>/assign @guo-shaoge 


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
/assign @guo-shaoge 
/assign @guo-shaoge 
Guess caused by this fix: https://github.com/pingcap/tidb/pull/18855/files . Trying to figure out how to fix it.
## Please edit this comment or add a new comment to complete the following information

### Not a bug

1. Remove the 'type/bug' label
2. Add notes to indicate why it is not a bug

### Duplicate bug

1. Add the 'type/duplicate' label
2. Add the link to the original bug

### Bug

Note: Make Sure that 'component', and 'severity' labels are added
Example for how to fill out the template: https://github.com/pingcap/tidb/issues/20100

#### 1. Root Cause Analysis (RCA) (optional) 
<!-- Write down the reason why this bug occurs -->

#### 2. Symptom (optional)

<!-- What will the user see when this bug occurs. The error message may be in the terminal, log or monitoring -->

#### 3. All Trigger Conditions (optional)

<!-- All the user scenarios that may trigger this bug -->

#### 4. Workaround (optional)

#### 5. Affected versions
[v4.0.5:v4.0.11],[v5.0.0-rc]
<!--
In the format of [start_version:end_version], multiple version ranges are
accepted. If the bug only affects the unreleased version, please input:
"unreleased". For example:

Notes:
  1. Do not use any white spaces in '[]'.
  2. The range in '[]' is a closed interval
  3. The version format is `v$Major.$Minor.$Patch`, the $Majoy and $Minor
     number in a version range should be the same. [v3.0.1:v3.1.2] is
     invalid because the $Minor number of the version range is different.

Example 1: [v3.0.1:v3.0.5], [v4.0.1:v4.0.5]
Example 2: unreleased
-->

#### 6. Fixed versions
master
<!--
The first released version that contains this fix in each minor version. If the bug's affected version has been released, the fixed version should be a detailed version number; If the bug doesn't affect any released version, the fixed version can be "master";  

Example 1: v3.0.13, v4.0.5
Example 2: master
-->



Patch:
diff --git a/util/codec/codec.go b/util/codec/codec.go
index 38dcc0385e419..9b5e6b82a808d 100644
--- a/util/codec/codec.go
+++ b/util/codec/codec.go
@@ -359,7 +359,11 @@ func encodeHashChunkRowIdx(sc *stmtctx.StatementContext, row chunk.Row, tp *type
 	case mysql.TypeEnum:
 		flag = compactBytesFlag
 		v := uint64(row.GetEnum(idx).ToNumber())
-		str := tp.Elems[v-1]
+		str := ""
+		if enum, err := types.ParseEnumValue(tp.Elems, v); err == nil {
+			// str will be empty string if v out of definition of enum.
+			str = enum.Name
+		}
 		b = ConvertByCollation(hack.Slice(str), tp)
 	case mysql.TypeSet:
 		flag = compactBytesFlag
@@ -571,7 +575,11 @@ func HashChunkSelected(sc *stmtctx.StatementContext, h []hash.Hash64, chk *chunk
 			} else {
 				buf[0] = compactBytesFlag
 				v := uint64(column.GetEnum(i).ToNumber())
-				str := tp.Elems[v-1]
+				str := ""
+				if enum, err := types.ParseEnumValue(tp.Elems, v); err == nil {
+					// str will be empty string if v out of definition of enum.
+					str = enum.Name
+				}
 				b = ConvertByCollation(hack.Slice(str), tp)
 			}
 


Test patch:
diff --git a/executor/join_test.go b/executor/join_test.go
index daa93ef680c7b..1edac17004362 100644
--- a/executor/join_test.go
+++ b/executor/join_test.go
@@ -2277,6 +2277,21 @@ func (s *testSuiteJoin1) TestIssue18564(c *C) {
 	tk.MustQuery("select /*+ INL_JOIN(t1) */ * from t1 FORCE INDEX (idx) join t2 on t1.b=t2.b and t1.a = t2.a").Check(testkit.Rows("1 1 1 1"))
 }
 
+// test hash join when enum column got invalid value
+func (s *testSuiteJoin1) TestInvalidEnumVal(c *C) {
+	tk := testkit.NewTestKit(c, s.store)
+	tk.MustExec("use test;")
+	tk.MustExec("set sql_mode = '';")
+	tk.MustExec("drop table if exists t1;")
+	tk.MustExec("create table t1(c1 enum('a', 'b'));")
+	tk.MustExec("insert into t1 values('a');")
+	tk.MustExec("insert into t1 values(0);")
+	tk.MustExec("insert into t1 values(100);")
+	rows := tk.MustQuery("select /*+ hash_join(t_alias1, t_alias2)*/ * from t1 t_alias1 inner join t1 t_alias2 on t_alias1.c1 = t_alias2.c1;")
+	// use empty string if got invalid enum int val.
+	rows.Check(testkit.Rows("a a", " ", " ", " ", " "))
+}
+
 func (s *testSuite9) TestIssue18572_1(c *C) {
 	tk := testkit.NewTestKitWithInit(c, s.store)
 	tk.MustExec("drop table if exists t1")