ClickHouse / ClickHouse/ClickHouse
`fuzzQuery` table function enters infinite loop when `max_query_length > 500`
- Dominant language
- C++
- Stars
- 49.9k
- Forks
- 9k
- Avg merge
- 21h 32m
- Merged PRs (30d)
- 515
Description
_Found via ClickGap automated review. Please close or comment if this is incorrect or needs adjustment._
_Retrospective finding from a historical scan of [PR #67655](https://github.com/ClickHouse/ClickHouse/pull/67655) (merged 2024-08-09). Confirmed on current codebase — close with a note if already fixed._
### Describe what's wrong
Calling `fuzzQuery('SELECT 1', 501, seed)` or any `max_query_length > 500` hangs indefinitely — the query never completes
**Root cause:** StorageFuzzQuery.cpp:48: `if (config.max_query_length > 500)` — this compares the wrong variable. The comment says 'AST is too long, will start from the original query' but the code checks if the configured max exceeds 500, not if the actual fuzzed text exceeds the configured max. When max_query_length > 500, this condition is ALWAYS true, causing the loop to reset `fuzz_base` and `continue` on every iteration without incrementing `row_num`, resulting in an infinite loop.
**Why we believe this is a bug:** StorageFuzzQuery.cpp:48 → `FuzzQuerySource::createColumn` — the condition `config.max_query_length > 500` compares the configuration parameter against 500 instead of comparing `fuzzed_text.size()` against `config.max_query_length`
**Affected locations:**
- `src/Storages/StorageFuzzQuery.cpp:48` — Length check in createColumn loop
**Impact:** Users setting max_query_length > 500 (to allow longer fuzzed queries) will experience hung queries that never return, requiring manual cancellation. Default value of 500 works correctly only by coincidence (500 > 500 is false).
### Does it reproduce on most recent release?
Yes — confirmed on current `master` (commit `b6844b26db6`).
### How to reproduce
```sql
-- Test shows infinite loop when max_query_length > 500
-- Run with timeout to demonstrate:
-- timeout 5 clickhouse-client -q "SELECT * FROM fuzzQuery('SELECT 1', 501, 8956) LIMIT 1" # HANGS
-- timeout 5 clickhouse-client -q "SELECT * FROM fuzzQuery('SELECT 1', 500, 8956) LIMIT 1" # WORKS
-- Working case (max_query_length <= 500):
SELECT length(query) > 0 FROM fuzzQuery('SELECT 1', 500, 8956) LIMIT 1;
-- Returns: 1 (success)
-- Bug case (max_query_length > 500):
-- SELECT * FROM fuzzQuery('SELECT 1', 501, 8956) LIMIT 1;
-- This query hangs indefinitely due to the bug
```
[Try it on ClickHouse Fiddle](https://fiddle.clickhouse.com/08c91eee-857f-4580-8923-bf6ef0d2341b)
### Expected behavior
```
Both queries should complete successfully, with max_query_length controlling the maximum length of generated fuzzed queries
```
### Error message and/or stacktrace
```
Query with max_query_length=500 returns: 'SELECT 1 PREWHERE NULL'
Query with max_query_length=501 times out after 5 seconds (infinite loop)
```
### Additional context
**Suggested fix:** Change `if (config.max_query_length > 500)` to `if (fuzzed_text.size() > config.max_query_length)` — compare the actual length of the fuzzed text against the configured maximum
**Analysis details:** Confidence HIGH | Severity P1 | Testability: `STATELESS_SQL`
Found during automated review of [PR #67655](https://github.com/ClickHouse/ClickHouse/pull/67655).
---
_ClickGapAI · Confidence: HIGH · Severity: P1 · Finding: `h_pr67655_001`_
Contributor guide
Assessment
This issue has not been assessed yet.