Fix STID 1941-1bfa: reject query parameter substitution as function name by groeneai · Pull Request #105839 · ClickHouse/ClickHouse · GitHub
Skip to content

Fix STID 1941-1bfa: reject query parameter substitution as function name#105839

Closed
groeneai wants to merge 1 commit into
ClickHouse:masterfrom
groeneai:groeneai/fix-stid-1941-1bfa-empty-name-function-param-subst
Closed

Fix STID 1941-1bfa: reject query parameter substitution as function name#105839
groeneai wants to merge 1 commit into
ClickHouse:masterfrom
groeneai:groeneai/fix-stid-1941-1bfa-empty-name-function-param-subst

Conversation

@groeneai

Copy link
Copy Markdown
Contributor

The AST fuzzer keeps rediscovering the Inconsistent AST formatting: the original AST: (STID: 1941-1bfa) round-trip failure across unrelated PRs (see #104605). One subvariant: a query parameter substitution placed in a function-name position, e.g.

SELECT {FUNC:Identifier}(-1)

with --param_FUNC=abs aborts the server in debug builds.

Root cause: ParserCompoundIdentifier accepts {p:Identifier}.tbl.fn as a 3-part identifier with a parameter hole in the first slot. getFunctionLayer then calls getIdentifierName(identifier), which returns the unset ASTIdentifier::full_name (empty when name_parts contains parameter holes). The result is an ASTFunction with name="". ASTFunction::formatImplWithoutAlias then skips the name and emits just (args), so re-parsing yields a plain parenthesized expression. The round-trip tree-hash check in executeQueryImpl raises the STID 1941-1bfa exception.

The fix rejects such an identifier as a function name at parse time in getFunctionLayer with a clear SYNTAX_ERROR. Parameter substitutions in column, table, and database positions are unaffected.

Pre-fix on the AST fuzzer reproducer:

Logical error: 'Inconsistent AST formatting: the original AST:
... (STID: 1941-1bfa)

Post-fix:

Code: 62. DB::Exception: Function name cannot be empty or a query parameter substitution. (SYNTAX_ERROR)

The new regression test 04277_stid_1941_1bfa_param_subst_function_name.sh covers:

  • the minimal single-part shape {FUNC:Identifier}(-1)
  • the compound shape {DB:Identifier}.test_table.COLUMNS(if(1, 1, id)) that the fuzzer found on AST JSON serialization #100412
  • the DESCRIBE TABLE (...) wrapper used in the fuzzer output

It also checks legitimate parameter usages (column / table / database names) still work and COLUMNS matcher unaffected.

Related: requested by @alexey-milovidov on #100412 (2026-05-26T07:31:35Z, STID 1941-1bfa directive). Issue #104605 tracks the umbrella.

Pre-PR validation gate (the five questions) posted in a follow-up comment below.

Changelog category (leave one):

  • Bug Fix (user-visible misbehavior in an official stable release)

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

Fix a server-aborting LOGICAL_ERROR Inconsistent AST formatting: the original AST: (STID: 1941-1bfa) raised by the AST round-trip check when a query parameter substitution was used in a function-name position, such as {F:Identifier}(args) or {db:Identifier}.tbl.fn(args). Such usages now fail at parse time with a clear SYNTAX_ERROR.

Documentation entry for user-facing changes

  • Documentation is unchanged

@groeneai

Copy link
Copy Markdown
Contributor Author

@groeneai

Copy link
Copy Markdown
Contributor Author

cc @evillique @george-larionov - could you review this? It is a parser-side fix for the chronic STID 1941-1bfa AST round-trip failure: rejects query parameter substitution as a function name ({F:Identifier}(args)) at parse time in getFunctionLayer, since such an identifier produces an ASTFunction with empty name that the formatter writes as just (args) and the round-trip check fails.

@PedroTadim PedroTadim added the can be tested Allows running workflows for external contributors label May 26, 2026
@evillique evillique self-assigned this Jun 2, 2026
@evillique

Copy link
Copy Markdown
Member

@groeneai rebase on top of the fresh master

… name

The AST fuzzer rediscovered the chronic round-trip failure on PR ClickHouse#100412 and
across multiple unrelated PRs (issue ClickHouse#104605). A query parameter substitution
in a function-name position, such as `{F:Identifier}(args)` or
`{db:Identifier}.tbl.fn(args)`, produced an `ASTFunction` with an empty `name`
because `ASTIdentifier::name()` returns the unset `full_name` when
`name_parts` contains parameter holes. `ASTFunction::formatImplWithoutAlias`
then emitted just `(args)` (skipping the missing name), so re-parsing yielded
a different AST (just the parenthesized expression). The round-trip check in
`executeQueryImpl` raised `Inconsistent AST formatting: the original AST:
(STID: 1941-1bfa)`, which aborts the server in debug builds.

The fix rejects such an identifier as a function name at parse time in
`getFunctionLayer` with a clear `SYNTAX_ERROR`. Parameter substitutions in
column, table, and database positions are not affected.

Minimal reproducer:

    SELECT {FUNC:Identifier}(-1)

with `--param_FUNC=abs`. Pre-fix: server aborts with the `STID 1941-1bfa`
exception. Post-fix: returns
`Function name cannot be empty or a query parameter substitution
(SYNTAX_ERROR)`.

The new regression test covers the minimal single-part shape, the compound
`COLUMNS` matcher shape that the AST fuzzer found on PR ClickHouse#100412, and the
`DESCRIBE TABLE` wrapper variant. Sanity checks confirm legitimate
parameter usages (column, table, database names) still work.

Closes part of ClickHouse#104605 (the empty-function-name subvariant of `STID 1941-1bfa`).

Related to PR ClickHouse#100412 (alexey-milovidov directive 2026-05-26T07:31:35Z).
@groeneai groeneai force-pushed the groeneai/fix-stid-1941-1bfa-empty-name-function-param-subst branch from 15c715a to 5de9b39 Compare June 2, 2026 16:04
@groeneai

groeneai commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

@evillique rebased on current master in 5de9b39 (no conflicts). CI rerunning.

@clickhouse-gh

clickhouse-gh Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Workflow [PR], commit [5de9b39]

Summary:


AI Review

Summary

This PR rejects query-parameter placeholders in function-name positions before they can create an empty-name ASTFunction, which addresses the STID 1941-1bfa AST round-trip failure for shapes such as {F:Identifier}(args) and {db:Identifier}.tbl.fn(args). The parser change is narrowly placed in getFunctionLayer, and the new test covers the minimal reproducer, the compound COLUMNS shape, the DESCRIBE TABLE wrapper, and nearby valid parameter substitutions. I did not find a code-level correctness issue.

PR Metadata
  • 💡 The Changelog category should not be Bug Fix (user-visible misbehavior in an official stable release). The PR body says this is a debug-build AST round-trip failure, and the check in executeQueryImpl is under #ifndef NDEBUG; per ClickHouse changelog guidance, debug/sanitizer/fuzzer-only LOGICAL_ERROR fixes are not stable-release bug fixes. Suggested category: Improvement (or CI Fix or Improvement if maintainers want no changelog entry).
  • 💡 If using Improvement, suggested entry: Reject query parameter substitutions in function-name positions, such as {F:Identifier}(args)or{db:Identifier}.tbl.fn(args), at parse time with a clear SYNTAX_ERROR instead of constructing an invalid empty-name function AST.
Final Verdict

Status: ⚠️ Request changes

Minimum required action: update the changelog category, and adjust the changelog entry if keeping it under Improvement.

@clickhouse-gh clickhouse-gh Bot added the pr-bugfix Pull request with bugfix, not backported by default label Jun 2, 2026
@clickhouse-gh

clickhouse-gh Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

LLVM Coverage Report

Metric Baseline Current Δ
Lines 84.40% 84.50% +0.10%
Functions 92.40% 92.40% +0.00%
Branches 77.00% 77.00% +0.00%

Changed lines: Changed C/C++ lines covered by tests: 6/6 (100.00%) | Lost baseline coverage (was covered on master, now uncovered in this PR): 1 line(s) · Uncovered code

Full report · Diff report

@groeneai

Copy link
Copy Markdown
Contributor Author

@groeneai groeneai closed this Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

can be tested Allows running workflows for external contributors pr-bugfix Pull request with bugfix, not backported by default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants