Skip to content

Missing size check in parseLiteralAndAssertType causes OOB crash when tuple element counts differ between rows #101727

@clickgapai

Description

@clickgapai

Found via ClickGap automated review. Please close or comment if this is incorrect or needs adjustment.

Describe what's wrong

INSERT INTO t (c0) VALUES ((1, 2)), ((1, 2, 3)) crashes with 'vector[] index out of bounds' in the Values format template parser

Root cause: ConstantExpressionTemplate.cpp:670-672: for loop uses nested_types.size() (parsed input) as bound but indexes into type_info.nested_types (template) without checking that sizes match. The PR fixed type mismatch (Array vs Tuple) but not size mismatch (2-tuple vs 3-tuple).

Why we believe this is a bug: parseLiteralAndAssertType (ConstantExpressionTemplate.cpp:670) iterates nested_types.size() (from parsed literal) but accesses type_info.nested_types[i] (from template built from first row). When second row's tuple has more elements than first row's, the loop goes out of bounds.

Affected locations:

  • src/Processors/Formats/Impl/ConstantExpressionTemplate.cpp:670 — loop over nested_types without size guard against type_info.nested_types

Impact: Server-side crash (abort from libc++ hardening) on valid SQL when inserting tuples of different sizes in the same VALUES clause into a String column. This is a P0 crash triggered by valid user input.

Does it reproduce on most recent release?

Yes — confirmed on current master (commit fc7ad06dc31f).

How to reproduce

DROP TABLE IF EXISTS t_tuple_oob;
CREATE TABLE t_tuple_oob (c0 String) ENGINE = Memory;
INSERT INTO TABLE t_tuple_oob (c0) VALUES ((1, 2)), ((1, 2, 3));
SELECT * FROM t_tuple_oob ORDER BY c0;
DROP TABLE IF EXISTS t_tuple_oob;

Try it on ClickHouse Fiddle

Expected behavior

(1,2)
(1,2,3)

Error message and/or stacktrace

Exit code 134
contrib/llvm-project/libcxx/include/__vector/vector.h:406: libc++ Hardening assertion __n < size() failed: vector[] index out of bounds
6. DB::ConstantExpressionTemplate::tryParseExpression @ 0x00000000180341d8
7. DB::ConstantExpressionTemplate::parseExpression @ 0x0000000018032c08
8. DB::ValuesBlockInputFormat::read @ 0x00000000180260ec

Additional context

Open risks:

  • Map type could have similar size mismatches in theory, though Map always has exactly 2 key-value types

Suggested fix: Add a size check before the loop: if (nested_types.size() != type_info.nested_types.size()) return false;

Analysis details: Confidence HIGH | Severity P0 | Testability: STATELESS_SQL

Found during automated review of PR #77071.


ClickGapAI · Confidence: HIGH · Severity: P0 · Finding: h_pr77071_001

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions