Skip to content

Commit

Permalink
*: fix the sysvar value may be corrupted after set by subquery (#41003)
Browse files Browse the repository at this point in the history
close #40979
  • Loading branch information
lcwangchao committed Feb 6, 2023
1 parent 76f1c52 commit e5477b8
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 1 deletion.
11 changes: 10 additions & 1 deletion executor/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,16 @@ func (e *SetExecutor) getVarValue(ctx context.Context, v *expression.VarAssignme
if err != nil || nativeVal.IsNull() {
return "", err
}
return nativeVal.ToString()

value, err = nativeVal.ToString()
if err != nil {
return "", err
}

// We need to clone the string because the value is constructed by `hack.String` in Datum which reuses the under layer `[]byte`
// instead of allocating some new spaces. The `[]byte` in Datum will be reused in `chunk.Chunk` by different statements in session.
// If we do not clone the value, the system variable will have a risk to be modified by other statements.
return strings.Clone(value), nil
}

func (e *SetExecutor) loadSnapshotInfoSchemaIfNeeded(name string, snapshotTS uint64) error {
Expand Down
37 changes: 37 additions & 0 deletions server/tidb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2950,3 +2950,40 @@ func TestSandBoxMode(t *testing.T) {
require.NoError(t, err)
}
}

// See: https://github.com/pingcap/tidb/issues/40979
// Reusing memory of `chunk.Chunk` may cause some systems variable's memory value to be modified unexpectedly.
func TestChunkReuseCorruptSysVarString(t *testing.T) {
ts := createTidbTestSuite(t)

db, err := sql.Open("mysql", ts.getDSN())
require.NoError(t, err)
defer func() {
require.NoError(t, db.Close())
}()

conn, err := db.Conn(context.Background())
require.NoError(t, err)
defer func() {
require.NoError(t, conn.Close())
}()

rs, err := conn.QueryContext(context.Background(), "show tables in test")
ts.Rows(t, rs)

_, err = conn.ExecContext(context.Background(), "set @@time_zone=(select 'Asia/Shanghai')")
require.NoError(t, err)

rs, err = conn.QueryContext(context.Background(), "select TIDB_TABLE_ID from information_schema.tables where TABLE_SCHEMA='aaaa'")
ts.Rows(t, rs)

rs, err = conn.QueryContext(context.Background(), "select @@time_zone")
require.NoError(t, err)
defer func() {
require.NoError(t, rs.Close())
}()

rows := ts.Rows(t, rs)
require.Equal(t, 1, len(rows))
require.Equal(t, "Asia/Shanghai", rows[0])
}

0 comments on commit e5477b8

Please sign in to comment.