Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

index out of range [4] with length 1 in executor.(*LimitExec).Next->chunk.(*Chunk).TruncateTo #55885

Closed
ycybfhb opened this issue Sep 5, 2024 · 1 comment · Fixed by #57274

Comments

@ycybfhb
Copy link

ycybfhb commented Sep 5, 2024

Bug Report

Please answer these questions before submitting your issue. Thanks!

1. Minimal reproduce step (Required)

SQL to init database
create table t_jg8o ( 
c_otj13 int unique ,
c_foveoe text ,
c_jbb text ,
c_s int not null unique ,
c_ovz0 double ,
c_m0qqv_cl4x text ,
c_cz text not null ,
c__qy double ,
c_z int not null ,
c_a90ol text not null ,
primary key(c_z) CLUSTERED) pre_split_regions=2;

alter table t_jg8o add column c_tazb9 int;

create table t__9r63 ( 
c_g7eofzlxn int ,
c_r58lkh double ,
c_x2erxo10w int ,
c_wsr tinyint ,
c_hd2v4v0 double ,
c_tb3u text ,
c_onfeptr2q tinyint unique ,
primary key(c_g7eofzlxn, c_x2erxo10w) CLUSTERED) pre_split_regions=7;

alter table t__9r63 add column c_o8tsf double;

alter table t_jg8o add column c_mgjb text;

insert into t__9r63 (c_g7eofzlxn, c_r58lkh, c_x2erxo10w, c_wsr, c_hd2v4v0, c_tb3u, c_onfeptr2q, c_o8tsf) values 
  (1275540443, 9223372036854775806.5, -1407328577, (NOT NOT(cast((-945767894 <= -8247562720541611887) as unsigned))), 35.15, 'l7ngfavtf2', (NOT NOT(cast((cast(cast(null as signed) as signed) > cast(-1581230237 as signed)) as unsigned))), 22.55), 
  (0, 6.4, -23, (-4 is not NULL), -256.4, 'nrqgupym', (NOT NOT(cast((cast(null as char) < cast(null as char)) as unsigned))), 49.2), 
  (-2005512947, 14.81, 1215057043, ((NOT NOT(cast((cast(-4255 as signed) <=> cast(-9223372036854775807.2 as double)) as unsigned)))) 
    or ((1928377790 is NULL)), 93.95, 'ycra', (NOT NOT(cast((-4902061839617880638 < cast(null as signed)) as unsigned))), 53.76), 
  (-865548105, 27.38, -932309610, 1=1, 65.29, cast(null as char), (NOT NOT(cast((cast(cast(null as char) as char) != cast(cast(null as char) as char)) as unsigned))), 2.71);

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (-1125135259, cast(null as char), 'yv0lmxlfk', -975033779, 37.68, 'bza6', 'cfvnwio', 85.65, -355481284, 'gnip', 1483367478, 'qb60'), 
  (1880243065, cast(null as char), 'i2qqh305', -2018599732, 32767.3, 'oro', 'it5a4_xpb', 85.86, 1617093413, 'm', -322122295, 'sfvnji04t3'), 
  (-4, 'yuv', 'aqx', -960107027, -2147483646.5, 'o8fnlpv', 'm2pb', 4.6, -2042358076, 'y1q', -2127191042, 'p'), 
  (-1974234281, 'lsw', 'mkdf7_y', -3, 31.13, 'gk45', 'i830ous8', 38.1, -1528586343, 'ex_2', cast(cast(null as signed) as signed), 'm7z');

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (-277118542, 'k', 'ghm1uf2f2', 69386953, cast(null as double), 'u9n4y2', 'qt', 32768.0, -62220810, 'tfkxjj5c', -627116719, 'dmgjz'), 
  (1565474881, 'min0', 'ml_ba1n', 587181689, 33.58, 'jz9rotuhlh', 'uo8lf', -9223372036854775806.3, -1666156943, 'queemvgj', 1778222362, 'fg3c8gyszj'), 
  (-589629632, 'pxcx', 'kkscy', -218561796, 71.80, 'chknth', 'nl2', 85.2, -670390288, 'nf990nol', -1306461501, 'f'), 
  (127, 'g5of_oy', 'uoxa', 858419954, 7.39, 'q', 'z0paksyd_8', 2147483646.0, -1649362344, 'won_9', -1363570695, 'mf196l7n');

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (1241131098, 'ohukstr8z6', 'o8lc2gnw', -1120115215, 25.45, 'i5', 'jl6gpk', 22.100, 1509989939, 'w', cast(cast(null as signed) as signed), 'u5cmakw59'), 
  (32767, 'cluk1', 'vwf0c', -1388119356, 43.38, 'd', 'k2k', 94.32, -1694148464, 'gu4i4knyhm', 2133825849, 'tk'), 
  (-1649650590, 'srv', 'sw', -1016230734, cast(null as double), 'epf0', 'zgntl', -4294967295.8, 1430313391, 's', cast(null as signed), 'c63s91'), 
  (625818595, 'b598_', 'k09g474', -1861825796, -128.8, 'fma', 'vpwh7bhpeg', 36.52, -1457928755, 'j', -1081926301, 'fi');

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (cast(null as signed), 'q4z87vft', 'y_1oiurq', 1963621165, 32769.7, 'sx17rkl7ru', 't45zvd_', 88.87, 18928603, 'gxbsloff', -2034290070, 'xb'), 
  (-972441022, 'oe', cast(null as char), 1492879828, 39.59, 'r', 'hyj_2', cast(null as double), 759883041, 'zwue', 1697880045, 'e'), 
  (cast(cast(null as signed) as signed), 'l4_3', 'i4h7dg', -1607192175, cast(null as double), 'z8voqwznkh', 'l_mk', 12.36, 1669523024, 'qt5zch71a', 1249617332, 'i1'), 
  (-846888054, 'm1jbwdl', 'rrrum4j6', 1534068569, 27.67, 'il', 'j_hlg0_3rp', 46.79, -392085130, 'bc', 16, 'w3lw6');

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (cast(cast(null as signed) as signed), cast(null as char), 'g', 155707446, 256.3, 'mx1qj0', 'j3', 9223372036854775809.4, 1727199557, 'qyghenu9t6', 744205327, 'z1_che8qi'), 
  (39, 'fnm2krnb', 'wxqm_zq3a', -1524976778, 31.59, 'gdv27x', 'n69m7fymt1', 75.99, 335492222, 'sdgde0z', cast(cast(null as signed) as signed), 'ykr5erlg5'), 
  (1355656665, '__eyi', 'mfr5', 175403335, 87.17, 'jj', 'oz', cast(null as double), -69711503, 'ja', 14424161, cast(null as char)), 
  (218845689, 'u2u8egda6', 'o8', -272715456, -9223372036854775807.1, 'szwj7begac', 'm', 48.62, 753928713, 'ur', cast(cast(null as signed) as signed), 'o_hzkvf2h');

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (325010661, 'gv15a', cast(null as char), -2035825967, 9223372036854775807.3, 'bd', 'c3kvy', 257.3, -1598426762, 'lmqmn', 814499588, 'gwqmly7q'), 
  (-233415102, 'hs2xue1', 'efbj7o4p', -1178957955, 58.9, 'y04g', 'qi68fwpdwo', 2147483648.100000, 1432554380, 'dqpb210', 2, 'a'), 
  (-2, 'brrhd', 's6mk', -2056628646, cast(null as double), 'gi', '_v7eaafvx', 254.5, -1476177588, 'k41ajpt7x', -599714096, 'paeld1s_gk'), 
  (cast(cast(null as signed) as signed), 'o23', 'bqdf52', -914210874, 1.75, 'd041c76', 'd6', 126.7, -421919910, 'x57ud7oy1', -537365618, 'srrn');

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (145245111, 'v66uhowf9g', 'ai4', -88586773, 43.77, 'byh', 'hazwego', 1.2, 1568247510, 'drmxi8', -1707580186, 'te3'), 
  (100663045, 'blfgrhpmo', 'pswozf1q2', -834563269, 86.9, 'gpwkf932fe', 'pnomakvyp', -4294967296.7, 1163133933, 'wp', -964848632, 'lfrx2gtt'), 
  (1498701970, cast(null as char), 'i89en7s8z', -84490060, 74.53, 'bx', 'xs6344kmb0', 54.13, -630289437, '_3_twecg5h', -2054873600, 'eu62_'), 
  (-522428484, 'euwmtnx1f', 'a_', 267700893, 63.46, 'n2s', 'mx8wzrf3z', 54.75, 370343042, 'n72', -1749867774, 'zmz8efxh');

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (-905893719, 'm7d8j', 'ml', 552106333, 15.76, 'a', 'pyq1x9ums', 32766.2, 2365745, 's7tt', 38, 'bat'), 
  (1231160405, 'h_pkv', cast(null as char), 643440707, cast(null as double), 'mxk3co7', 'v60l0it', 65536.8, -850412592, 'wmluxa9a', -3, cast(null as char)), 
  (1986094882, 'tn2lly', 't2wczw', 1709853766, 256.6, 'nowm1x', 's07dvcbf', -4294967296.5, -21041749, 'obqj0uu5v', 1779379786, 'pgi'), 
  (-1821883740, 'j37djo2lth', 'fv', -7, 9223372036854775807.7, 'cde8k', 'jylbt', 80.88, 528792379, 'n5qr9m26i', 434269354, 'l');

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (-961030073, cast(null as char), 'hzacfknf', -456431629, 95.4, 'j', 'l', 28.43, 1958788149, 'b', 30, 'svw3'), 
  (1650387673, 'rw8fqp6v', 'pvrb_y8', -28841240, 16.59, 'jmp5', 'f7jcx7', 11.86, -1089765168, 'pqg', 1336711866, 'i'), 
  (593387683, 'rtavaa', 'hu95fi27', -807839288, 15.55, 'o', 'dniac62ej', 25.89, 504535500, 'cs3tkhs', -355956957, 'e2u_e'), 
  (1925910886, 'yc6f2b8sx', cast(null as char), -52910064, -18446744073709551616.6, 'p55j0qfh', 'k7p587ii', 85.16, 354032882, '_ffjo67yxe', cast(null as signed), cast(null as char));

insert into t_jg8o (c_otj13, c_foveoe, c_jbb, c_s, c_ovz0, c_m0qqv_cl4x, c_cz, c__qy, c_z, c_a90ol, c_tazb9, c_mgjb) values 
  (-324790424, 'l7tkij97', 'jpsz1afty', 1919869830, 47.51, 'cjep', 'ysinvie', 81.81, -272247558, 'aj', -1364386190, 'b9pv_pswu'), 
  (-1176143795, 'mhx', cast(null as char), 165434725, 22.67, 'y', 'wg_ccu', -2147483648.0, 11, 'xxnsf5', -33, 'n9a'), 
  (43882083, cast(null as char), 'sb8q1qk93', 3, 58.12, '_nq5o3o4h', 'p', -2147483648.7, 1616632952, 'g7t8tqyi', 1149176707, cast(null as char)), 
  (683197795, 'xv38gos', 'he', 1851859144, -2147483647.6, 'f', 'sqbww', 70.73, -1105664209, 'qjfhjr', 1736785989, 'm');


SQL that causes error
WITH
cte_0 AS (
SELECT
  subq_0.c3 as c1
FROM
  (select  
          ref_0.c_a90ol as c0, 
          ref_0.c_mgjb as c1, 
          (select c_g7eofzlxn from t__9r63 order by c_g7eofzlxn limit 1 offset 5)
             as c2, 
          ref_0.c_a90ol as c3, 
          ref_0.c_a90ol as c4, 
          
            var_pop(
              cast(ref_0.c__qy as double)) over (partition by ref_0.c_a90ol, ref_0.c_s order by ref_0.c_z) as c5, 
          1867837693 as c6, 
          -1397297856 as c7
        from 
          t_jg8o as ref_0
        where (substring(
            cast(ref_0.c_m0qqv_cl4x as char), 
            cast((select c_wsr from t__9r63 order by c_wsr limit 1 offset 1)
               as signed), 
            cast(-21766 as signed)) is not NULL)
        limit 65) as subq_0
LIMIT 37
)
SELECT
  ref_29.c1 as c96
FROM
  cte_0 as ref_29
LIMIT 142;

2. What did you expect to see? (Required)

Expect no crashes

3. What did you see instead (Required)

runtime error: index out of range [4] with length 1
github.com/pingcap/errors.AddStack
	/root/go/pkg/mod/github.com/pingcap/errors@v0.11.5-0.20240318064555-6bd07397691f/errors.go:178
github.com/pingcap/errors.Trace
	/root/go/pkg/mod/github.com/pingcap/errors@v0.11.5-0.20240318064555-6bd07397691f/juju_adaptor.go:15
github.com/pingcap/tidb/pkg/util.GetRecoverError
	/workspace/source/tidb/pkg/util/util.go:288
github.com/pingcap/tidb/pkg/executor/internal/exec.Next.func1
	/workspace/source/tidb/pkg/executor/internal/exec/executor.go:435
runtime.gopanic
	/usr/local/go/src/runtime/panic.go:914
runtime.goPanicIndex
	/usr/local/go/src/runtime/panic.go:114
github.com/pingcap/tidb/pkg/util/chunk.(*Chunk).TruncateTo
	/workspace/source/tidb/pkg/util/chunk/chunk.go:517
github.com/pingcap/tidb/pkg/executor.(*LimitExec).Next
	/workspace/source/tidb/pkg/executor/executor.go:1377
github.com/pingcap/tidb/pkg/executor/internal/exec.Next
	/workspace/source/tidb/pkg/executor/internal/exec/executor.go:451
github.com/pingcap/tidb/pkg/executor.(*LimitExec).Next
	/workspace/source/tidb/pkg/executor/executor.go:1367
github.com/pingcap/tidb/pkg/executor/internal/exec.Next
	/workspace/source/tidb/pkg/executor/internal/exec/executor.go:451
github.com/pingcap/tidb/pkg/executor.(*ProjectionExec).unParallelExecute
	/workspace/source/tidb/pkg/executor/projection.go:218
github.com/pingcap/tidb/pkg/executor.(*ProjectionExec).Next
	/workspace/source/tidb/pkg/executor/projection.go:205
github.com/pingcap/tidb/pkg/executor/internal/exec.Next
	/workspace/source/tidb/pkg/executor/internal/exec/executor.go:451
github.com/pingcap/tidb/pkg/executor.(*ExecStmt).next
	/workspace/source/tidb/pkg/executor/adapter.go:1254
github.com/pingcap/tidb/pkg/executor.(*recordSet).Next
	/workspace/source/tidb/pkg/executor/adapter.go:171
github.com/pingcap/tidb/pkg/server/internal/resultset.(*tidbResultSet).Next
	/workspace/source/tidb/pkg/server/internal/resultset/resultset.go:72
github.com/pingcap/tidb/pkg/server.(*clientConn).writeChunks
	/workspace/source/tidb/pkg/server/conn.go:2361
github.com/pingcap/tidb/pkg/server.(*clientConn).writeResultSet
	/workspace/source/tidb/pkg/server/conn.go:2304
github.com/pingcap/tidb/pkg/server.(*clientConn).handleStmt
	/workspace/source/tidb/pkg/server/conn.go:2097
github.com/pingcap/tidb/pkg/server.(*clientConn).handleQuery
	/workspace/source/tidb/pkg/server/conn.go:1811
github.com/pingcap/tidb/pkg/server.(*clientConn).dispatch
	/workspace/source/tidb/pkg/server/conn.go:1385
github.com/pingcap/tidb/pkg/server.(*clientConn).Run
	/workspace/source/tidb/pkg/server/conn.go:1147
github.com/pingcap/tidb/pkg/server.(*Server).onConn
	/workspace/source/tidb/pkg/server/server.go:741
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:1650

4. What is your TiDB version? (Required)

Release Version: v8.4.0-alpha-66-g1167e0c
Edition: Community
Git Commit Hash: 1167e0c06fc8e2dd066bd974315284bc0e884acc
Git Branch: HEAD
UTC Build Time: 2024-09-03 01:15:19
GoVersion: go1.21.13
Race Enabled: false
Check Table Before Drop: false
Store: tikv

We are the BASS team from the School of Cyber Science and Technology at Beihang University. Our main focus is on system software security, operating systems, and program analysis research, as well as the development of automated program testing frameworks for detecting software defects. Using our self-developed database vulnerability testing tool, we have identified the above-mentioned vulnerabilities in TiDB that may lead to database crashes.

@windtalker
Copy link
Contributor

simplest reproduce sql

SELECT
subq_0.c3 as c1
FROM
(
select
        ref_0.c_a90ol as c3,
        ref_0.c_a90ol as c4,
        var_pop(cast(ref_0.c__qy as double)) over (partition by ref_0.c_a90ol, ref_0.c_s order by ref_0.c_z) as c5
        from
          t_jg8o as ref_0
        limit 65
) as subq_0
LIMIT 37

The root cause of this issue is

  1. the sql will generate a plan that contains projection the same column multiple times
mysql> source /tmp/test.sql
+----------------------------------------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id                                     | estRows | task      | access object | operator info                                                                                                                                                             |
+----------------------------------------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Projection_14                          | 37.00   | root      |               | issuedb.t_jg8o.c_a90ol                                                                                                                                                    |
| └─Limit_17                             | 37.00   | root      |               | offset:0, count:37                                                                                                                                                        |
|   └─Limit_20                           | 40.00   | root      |               | offset:0, count:65                                                                                                                                                        |
|     └─Shuffle_27                       | 40.00   | root      |               | execution info: concurrency:5, data sources:[Projection_23]                                                                                                               |
|       └─Window_21                      | 40.00   | root      |               | var_pop(Column#15)->Column#16 over(partition by issuedb.t_jg8o.c_a90ol, issuedb.t_jg8o.c_s order by issuedb.t_jg8o.c_z range between unbounded preceding and current row) |
|         └─Sort_26                      | 40.00   | root      |               | issuedb.t_jg8o.c_a90ol, issuedb.t_jg8o.c_s, issuedb.t_jg8o.c_z                                                                                                            |
|           └─ShuffleReceiver_28         | 40.00   | root      |               |                                                                                                                                                                           |
|             └─Projection_23            | 40.00   | root      |               | issuedb.t_jg8o.c_a90ol, issuedb.t_jg8o.c_a90ol, issuedb.t_jg8o.c_s, issuedb.t_jg8o.c_z, cast(issuedb.t_jg8o.c__qy, double BINARY)->Column#15                              |
|               └─TableReader_25         | 40.00   | root      |               | data:TableFullScan_24                                                                                                                                                     |
|                 └─TableFullScan_24     | 40.00   | cop[tikv] | table:ref_0   | keep order:false, stats:pseudo                                                                                                                                            |
+----------------------------------------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Note that Projection_23 project column issuedb.t_jg8o.c_a90ol twice
2. In projection exec, if projection project the same column multiple times, in the result chunk, the column will be reused

type columnEvaluator struct {
inputIdxToOutputIdxes map[int][]int
// mergedInputIdxToOutputIdxes is only determined in runtime when saw the input chunk.
mergedInputIdxToOutputIdxes atomic.Pointer[map[int][]int]
}
// run evaluates "Column" expressions.
// NOTE: It should be called after all the other expressions are evaluated
//
// since it will change the content of the input Chunk.
func (e *columnEvaluator) run(ctx EvalContext, input, output *chunk.Chunk) error {
// mergedInputIdxToOutputIdxes only can be determined in runtime when we saw the input chunk structure.
if e.mergedInputIdxToOutputIdxes.Load() == nil {
e.mergeInputIdxToOutputIdxes(input, e.inputIdxToOutputIdxes)
}
for inputIdx, outputIdxes := range *e.mergedInputIdxToOutputIdxes.Load() {
if err := output.SwapColumn(outputIdxes[0], input, inputIdx); err != nil {
return err
}
for i, length := 1, len(outputIdxes); i < length; i++ {
output.MakeRef(outputIdxes[0], outputIdxes[i])
}
}
return nil
}

So the chunk output by Projection_23 will be something like
col1, col1, col3, col4, ...
3. In LimitExec, it may contain inlined projection by setting the output column in columnIdxsUsedByChild

tidb/pkg/executor/executor.go

Lines 1363 to 1364 in 1dc3851

// columnIdxsUsedByChild keep column indexes of child executor used for inline projection
columnIdxsUsedByChild []int

5. In LimitExec.Next, it use SwapColumn to do the inline projection, which will got wrong result if the inline projection index actually pointing to the same column in chunk

tidb/pkg/executor/executor.go

Lines 1426 to 1430 in 1dc3851

for i, childIdx := range e.columnIdxsUsedByChild {
if err = req.SwapColumn(i, e.childResult, childIdx); err != nil {
return err
}
}

For example, if columnIdxsUsedByChild is [0, 1], and the input chunk is col1, col1, col3, col4, ...
After swap column 0, the result chunk is col1, nil and the input chunk is nil, nil, col3, col4, ...
After swap column 1, the result chunk is col1, nil and the input chunk is nil, nil, col3, col4, ...
So the final result chunk is col1, nil, and the expected result chunk is col1, col1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants