Skip to content

[fix](nereids) Fix SQL masking and view rewrites after supplementary characters - #70366

Open
morningman wants to merge 1 commit into
apache:masterfrom
morningman:b2m-t38f-codepoint-offsets
Open

morningman wants to merge 1 commit into
apache:masterfrom
morningman:b2m-t38f-codepoint-offsets

Conversation

@morningman

Copy link
Copy Markdown
Contributor

Background

Several FE features rewrite the text of a statement by cutting the original SQL string at token positions from the parser. Audit masking replaces credential properties and passwords with *XXX before the statement reaches fe.audit.log, __internal_schema.audit_log and the FE log; CREATE / ALTER VIEW and CREATE MATERIALIZED VIEW expand * and qualify names in the definition they store; the parser reads /*+ ... */ hints from comment tokens. The lexer counts its input by Unicode code point, while a Java String holds a supplementary character, such as an emoji, as two chars.

What problem does this PR solve?

Issue Number: None
Related PR: #47595 (introduced the bug in audit masking), #32743 (introduced the bug in view rewriting), #70338 (its review found the masking leak)
PR Type: Bugfix

Problem Summary:

After each supplementary character in a statement, these token positions point one char too early, so the text is cut at the wrong place. A credential after or inside such characters stays partly or fully in clear text in the audit log, CREATE VIEW fails with a syntax error, CREATE MATERIALIZED VIEW stores a broken query, and a hint after such a character is silently ignored. This PR converts the positions to String offsets, or reads the text through the token, at the five places that cut the original SQL. Tests are 89% of the diff.

Details

  • Change map: production code +33 -33 in 3 files; tests +240 in 5 files (FE unit tests and one regression suite); generated .out +16. (1) BaseViewInfo.rewriteSql, shared by audit masking, views and MTMV, converts its positions; the sync-MV builder drops its private copy of it, and rewriteProjectsToUserDefineAlias replaces the select list through it. (2) NereidsParser.getHintMap reads hints from the token text. (3) NereidsParser.tryParseExplainPlan converts the start of the EXPLAIN PLAN body.
  • Frequency: Always, when a character above U+FFFF (an emoji, CJK Extension B) comes before or inside the rewritten part, for example a catalog COMMENT of emoji in front of 's3.secret_key' = 'secret'.
  • Root cause: CaseInsensitiveStream.fromString keeps ANTLR's code-point stream for any input with a surrogate (before [improvement](parser) Add case-insensitive stream fast paths #67452 every input used CharStreams.fromString), so Token.getStartIndex() and getStopIndex() count code points. The five places in the Change map used them as String indexes.
  • Why existing tests missed it: Unit tests: the masking (EncryptSQLTest, RepositoryAuditEncryptionTest), view and MTMV (CreateViewTest, CreateMTMVCommandTest) and hint tests (LeanTokenModeTest) use only BMP text, where both kinds of position coincide; CaseInsensitiveStreamTest uses an emoji but checks only the stream's own positions. Regression: audit/test_external_catalog_credential_masking and the ddl_p0/create_view_nereids suites have no supplementary characters, and the masking suite only checks that the whole credential is absent, which a leaked tail passes.
  • Fix: Convert where the text is cut. rewriteSql converts each position with String.offsetByCodePoints, walking the sorted positions once so the cost stays linear; rewriteProjectsToUserDefineAlias reads expressions through the token's input stream; getHintMap reads the hint from the token text, as removeCommentAndTrimBlank does. Changing the stream to report String positions was rejected: [improvement](parser) Add case-insensitive stream fast paths #67452 made code-point positions part of CaseInsensitiveStream's contract, and CaseInsensitiveStreamTest pins them.
  • Other paths and branches: Fixed here: the 19 masking visitors of LogicalPlanBuilderForEncryption with every caller of geneEncryptionSQL (audit log, FE statement log, _query_plan) and the streaming insert job; the view, MTMV and sync-MV rewrites. Not affected: the other uses of token positions read text through the token's own stream (such as getOriginSql) or only compare positions with each other. branch-3.1, branch-4.0, branch-4.1 and branch-4.2 have the same code. Introduced by [feat](nereids) support create view in nereids #32743 (views), [Feature](nereids) support encrypt sql for audit log #47595 (masking), [feature](nereids)use mtmv to match legacy mv #33699 (sync MV) and [enhancement](Nereids) Enable parse sql from sql cache #33262 (EXPLAIN PLAN); hints since at least [fix](Nereids) fix lexer Backtracking or Ambiguity cause of key word duplicate #39590.

Testing

  • New unit tests fail on master f1bc8b3690c and pass with the fix, run locally: EncryptSQLTest#testEncryptionAfterSupplementaryCharacters, through MysqlConnectProcessor to the audit event (emoji inside a credential, in a catalog COMMENT, in the first of two property clauses, in a user name before PASSWORD(...); master left secret, abc, 123 and 123456 in clear text); CreateViewTest#testCreateViewRewritesAfterSupplementaryCharacters (master: mismatched input 'e'); CreateMTMVCommandTest#testCreateMTMVRewritesQuerySqlAfterSupplementaryCharacters (master kept SELECT '😀😀' A`e` e`internal`...); SupplementaryCharacterOffsetTest (master dropped the hint, cut the EXPLAIN PLAN body to AN SELECT 100, and rewrote the sync MV to avg_stateg(k)))).
  • New regression suite ddl_p0/create_view_nereids/test_create_view_supplementary_chars: fails without the fix with the same syntax error and passes with it; the .out is generated by the script. Run locally on one FE and one BE, an older master FE build with the three changed classes swapped in.
  • 27 existing FE UT classes around the change (467 tests) pass. Reverting each part of the fix alone, moving the end of a replaced span by one, or not advancing the position cursor each fails a new test; the off-by-one also fails existing ASCII cases.
  • By hand on that cluster, without the fix: the secret stayed in audit_log, /* 😀 */ select /*+ SET_VAR(query_timeout=1) */ sleep(3) ran for 3 s, and an MTMV over select '😀😀' as e, ... was created but failed to refresh (Nereids parse failed). With the fix: "s3.secret_key" = "*XXX"), and the query times out after 1 s.

Notes for Reviewers

  • getHintMap loses its sql parameter, which nothing reads any more; its three callers are in NereidsParser.
  • rewriteProjectsToUserDefineAlias replaces the select list through rewriteSql instead of StringUtils.overlay, so the conversion lives in one method.
  • Stored definitions are not repaired: an MTMV created by an affected version from such a query keeps its broken definition and has to be recreated.

Release note

Fix passwords and credentials left partly or fully unmasked in the audit log and the FE log when a supplementary character, such as an emoji, comes before or inside them. Also fix CREATE VIEW failing, CREATE MATERIALIZED VIEW storing a broken query, and hints such as SET_VAR being ignored after such a character; materialized views already created with a broken query must be recreated.

Check List (For Author)

  • Behavior changed: No
  • Does this need documentation: No
  • Pre-submission status: Ready

AI Disclosure

@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@morningman

Copy link
Copy Markdown
Contributor Author

run buildall

@morningman

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed at PR head 910dabb against base f1bc8b3. I found no verified blocking or non-blocking defects, so there are no new inline findings and no existing P0/P1 threads to carry forward.

The change goal is met: the shared rewriteSql path converts ANTLR code-point positions to Java UTF-16 offsets while preserving ordered multi-range and zero-width replacements; all audited masking, view/MTMV, sync-MV, and streaming callers use positions from the same source text. The alias rewrite reparses the already rewritten SQL and extracts exact source intervals, and the hint and EXPLAIN paths preserve token text and convert body offsets consistently.

Critical checkpoints: data/version/delete-bitmap, FE-BE protocol, persistence, transactions, concurrency, locking, lifecycle, configuration, observability, and BE memory/nullability concerns are not involved in this FE parser/string-only change. The focused FE/Nereids checks found no exception, rewrite-loop, or parallel-path regression. The added unit and regression tests cover supplementary characters in masking, views, MTMV, hints, EXPLAIN, aliases, and sync-MV rewriting; they were inspected but not executed because this invocation is static-only. No user-provided additional focus was supplied.

The review converged in round 1 after complete changed-file and call-chain coverage plus independent risk-focused reviews. Remaining limitation: runtime/build/test behavior was not executed under the review contract.

Review converged after 1 round(s).

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28118 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 910dabb10438b37c9a4b83bedd7c8bf430cec726, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17607	5123	5020	5020
q2	2115	297	271	271
q3	10243	1365	817	817
q4	4682	454	331	331
q5	7419	797	521	521
q6	178	184	150	150
q7	734	788	593	593
q8	9251	1338	1046	1046
q9	5409	4161	4162	4161
q10	6815	1305	1006	1006
q11	434	240	224	224
q12	635	394	270	270
q13	18108	3568	2979	2979
q14	264	263	241	241
q15	q16	738	723	675	675
q17	1175	741	577	577
q18	6939	6173	6087	6087
q19	1117	952	584	584
q20	379	336	224	224
q21	4852	2090	2210	2090
q22	341	290	251	251
Total cold run time: 99435 ms
Total hot run time: 28118 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5576	5557	5600	5557
q2	699	553	522	522
q3	5219	5422	4997	4997
q4	1991	2154	1532	1532
q5	5323	5161	5399	5161
q6	265	200	154	154
q7	2385	2013	1919	1919
q8	3011	2658	2632	2632
q9	8128	8000	7965	7965
q10	3743	3979	3205	3205
q11	621	442	412	412
q12	697	677	523	523
q13	3500	3781	3290	3290
q14	344	317	283	283
q15	q16	725	726	651	651
q17	8102	6994	6874	6874
q18	13016	12191	12860	12191
q19	902	783	796	783
q20	2138	2152	1915	1915
q21	5598	4610	4753	4610
q22	497	466	391	391
Total cold run time: 72480 ms
Total hot run time: 65567 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 153719 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 910dabb10438b37c9a4b83bedd7c8bf430cec726, data reload: false

query5	4301	498	412	412
query6	431	209	197	197
query7	4821	428	229	229
query8	322	168	149	149
query9	8775	3220	3194	3194
query10	480	323	251	251
query11	5912	3881	3559	3559
query12	144	93	86	86
query13	1254	435	316	316
query14	6108	3927	3638	3638
query14_1	3383	3426	3414	3414
query15	208	200	183	183
query16	944	443	409	409
query17	860	651	551	551
query18	2412	418	308	308
query19	194	169	148	148
query20	85	84	82	82
query21	215	126	103	103
query22	12911	12967	12795	12795
query23	13417	12909	12496	12496
query23_1	13028	12797	12669	12669
query24	7369	826	482	482
query24_1	482	489	486	486
query25	559	404	343	343
query26	1264	261	135	135
query27	2763	436	276	276
query28	4615	2069	2066	2066
query29	1539	586	444	444
query30	302	213	176	176
query31	997	955	802	802
query32	142	89	90	89
query33	513	295	239	239
query34	921	851	490	490
query35	734	760	620	620
query36	825	806	764	764
query37	125	96	82	82
query38	1762	1745	1653	1653
query39	783	782	741	741
query39_1	723	727	736	727
query40	218	117	98	98
query41	65	62	62	62
query42	86	86	81	81
query43	340	358	306	306
query44	1315	707	711	707
query45	177	181	168	168
query46	824	960	562	562
query47	2927	2941	2629	2629
query48	295	310	218	218
query49	581	398	299	299
query50	676	276	214	214
query51	10858	10554	10614	10554
query52	79	84	70	70
query53	187	215	156	156
query54	238	193	199	193
query55	75	74	66	66
query56	230	206	225	206
query57	1647	1598	1571	1571
query58	283	270	250	250
query59	2087	2133	2010	2010
query60	303	275	227	227
query61	150	150	144	144
query62	392	339	291	291
query63	190	162	161	161
query64	2742	922	775	775
query65	3355	3260	3269	3260
query66	1760	415	294	294
query67	22554	22582	22403	22403
query68	2988	984	618	618
query69	399	276	248	248
query70	866	771	763	763
query71	308	243	214	214
query72	2667	2655	2296	2296
query73	511	519	291	291
query74	4622	4485	4326	4326
query75	2338	2292	1912	1912
query76	2326	1025	592	592
query77	346	375	257	257
query78	9552	9719	9220	9220
query79	891	849	526	526
query80	476	399	349	349
query81	511	320	275	275
query82	206	140	109	109
query83	199	200	201	200
query84	287	127	101	101
query85	764	460	378	378
query86	256	243	230	230
query87	1934	1927	1789	1789
query88	3697	2787	2746	2746
query89	318	282	255	255
query90	1917	163	171	163
query91	165	156	130	130
query92	103	89	89	89
query93	990	993	585	585
query94	548	299	290	290
query95	587	385	303	303
query96	687	512	236	236
query97	2442	2459	2339	2339
query98	166	151	151	151
query99	759	775	667	667
Total cold run time: 235744 ms
Total hot run time: 153719 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.91 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 910dabb10438b37c9a4b83bedd7c8bf430cec726, data reload: false

query1	0.00	0.00	0.00
query2	0.09	0.05	0.06
query3	0.26	0.09	0.09
query4	1.61	0.10	0.10
query5	0.23	0.24	0.23
query6	1.18	0.69	0.69
query7	0.04	0.01	0.01
query8	0.05	0.03	0.03
query9	0.40	0.34	0.36
query10	0.58	0.60	0.56
query11	0.20	0.14	0.15
query12	0.19	0.15	0.14
query13	0.48	0.50	0.50
query14	1.02	1.02	1.02
query15	0.63	0.62	0.62
query16	0.35	0.34	0.33
query17	1.14	1.14	1.15
query18	0.19	0.20	0.19
query19	2.08	2.00	2.00
query20	0.02	0.01	0.01
query21	15.47	0.20	0.13
query22	4.86	0.06	0.05
query23	16.27	0.31	0.12
query24	1.08	0.25	0.15
query25	0.08	0.05	0.05
query26	0.79	0.21	0.16
query27	0.03	0.03	0.03
query28	3.82	0.79	0.35
query29	12.50	4.06	3.22
query30	0.28	0.13	0.10
query31	2.78	0.56	0.32
query32	3.23	0.60	0.49
query33	3.18	3.11	3.20
query34	15.43	4.00	3.39
query35	3.33	3.32	3.32
query36	0.54	0.45	0.41
query37	0.09	0.06	0.06
query38	0.05	0.03	0.04
query39	0.03	0.02	0.02
query40	0.17	0.15	0.14
query41	0.08	0.02	0.02
query42	0.04	0.02	0.02
query43	0.05	0.03	0.03
Total cold run time: 94.92 s
Total hot run time: 23.91 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 100.00% (19/19) 🎉
Increment coverage report
Complete coverage report

@morningman

Copy link
Copy Markdown
Contributor Author

run buildall

@morningman

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review of PR #70366 at head 910dabb against base f1bc8b3: no verified new defects found. All nine changed files and their relevant producer/consumer paths were reviewed. There are no existing inline findings to carry forward and no additional user-provided focus.

Critical checkpoint conclusions:

  1. Goal/correctness: the inspected code consistently converts ANTLR code-point positions at Java String boundaries. Masking, CREATE/ALTER VIEW, MTMV, sync-MV, hints and EXPLAIN use coordinates from the SQL being rewritten. Added tests assert the intended corrected text and hint objects.
  2. Scope/reuse: the three production changes are focused; sync-MV and explicit-column rewriting reuse BaseViewInfo.rewriteSql instead of separate slicing logic.
  3. Concurrency/locking: no new threads, shared mutable state or lock operations. Replacement maps, cursors and parser inputs remain local to the existing statement flow.
  4. Lifecycle/static initialization: no new resource ownership or static initialization. Token input remains reachable while its source text is extracted.
  5. Configuration: no configuration added or changed.
  6. Compatibility: getHintMap callers are updated; no wire or storage schema changes. Corrected definitions enter existing storage paths; already malformed stored MV definitions are not repaired by this change.
  7. Thrift/protobuf: no definitions changed; field-id review is inapplicable.
  8. Parallel paths: traced all direct shared-rewrite callers, including streaming job/task audit SQL, view/MTMV analysis-generated spans, generic/create-view/sync-MV hint parsing, and full-scan versus lean tokens. Encryption continues to omit execution hints intentionally.
  9. Conditional checks/errors: the hint prefix check matches the existing comment-normalization convention. Inclusive ends, BMP text, supplementary characters before and within replacements, adjacent ranges and query-relative sync-MV positions are consistent; existing exception/fallback behavior is preserved.
  10. Test coverage: inspected added FE tests for audit-event masking, views and explicit aliases, MTMV definitions, hints, EXPLAIN and sync-MV aggregates, plus the view regression suite. Existing BMP/control cases support compatibility. No new malformed-input semantics or error path is introduced.
  11. Expected results: the new regression definitions and rows match the suite's inserted data, filter and aliases; query results use order_qt. Output generation and author-reported test success were not independently executed.
  12. Observability: this local deterministic text correction adds no operational boundary requiring new logs or metrics; existing parser/MV/audit diagnostics remain available.
  13. Persistence/transactions: rewritten view/MV text uses existing persistence paths; no EditLog, transaction, failover or replay protocol changes.
  14. Data writes/atomicity: no change to data mutation, visibility, version or delete-bitmap logic; no new crash-recovery or write lifecycle.
  15. FE/BE variables: no new transmitted variables or send paths.
  16. Performance/memory: conversion advances through original input once for disjoint ranges and remains linear in source plus output length. Source extraction is bounded by the relevant intervals. No BE allocation or nullability code is involved.
  17. Other issues: no additional verified issue after independent review and the final missed-case sweep. The map comparator's existing end ordering and overlap limitations introduce no new failure for the inspected producers.

The review converged in two rounds after complete static coverage and independent challenge of this frozen payload. Both recorded coordinate/source-text risk focuses were dismissed with code evidence; no unresolved candidates or static coverage gaps remain. Validation limit: no builds, tests, benchmarks, cluster execution or output regeneration were performed under the static-only review contract.

Review converged after 2 round(s).

…characters

### Background

Several FE features rewrite the text of a statement by cutting the original SQL string at token positions from the parser. Audit masking replaces credential properties and passwords with `*XXX` before the statement reaches `fe.audit.log`, `__internal_schema.audit_log` and the FE log; CREATE / ALTER VIEW and CREATE MATERIALIZED VIEW expand `*` and qualify names in the definition they store; the parser reads `/*+ ... */` hints from comment tokens. The lexer counts its input by Unicode code point, while a Java `String` holds a supplementary character, such as an emoji, as two `char`s.

### What problem does this PR solve?

Issue Number: None
Related PR: apache#47595 (introduced the bug in audit masking), apache#32743 (introduced the bug in view rewriting), apache#70338 (its review found the masking leak)
PR Type: Bugfix

Problem Summary:

After each supplementary character in a statement, these token positions point one `char` too early, so the text is cut at the wrong place. A credential after or inside such characters stays partly or fully in clear text in the audit log, CREATE VIEW fails with a syntax error, CREATE MATERIALIZED VIEW stores a broken query, and a hint after such a character is silently ignored. This PR converts the positions to `String` offsets, or reads the text through the token, at the five places that cut the original SQL. Tests are 89% of the diff.

### Details

- **Change map:** production code +33 -33 in 3 files; tests +240 in 5 files (FE unit tests and one regression suite); generated `.out` +16. (1) `BaseViewInfo.rewriteSql`, shared by audit masking, views and MTMV, converts its positions; the sync-MV builder drops its private copy of it, and `rewriteProjectsToUserDefineAlias` replaces the select list through it. (2) `NereidsParser.getHintMap` reads hints from the token text. (3) `NereidsParser.tryParseExplainPlan` converts the start of the EXPLAIN PLAN body.
- **Frequency:** Always, when a character above U+FFFF (an emoji, CJK Extension B) comes before or inside the rewritten part, for example a catalog COMMENT of emoji in front of `'s3.secret_key' = 'secret'`.
- **Root cause:** `CaseInsensitiveStream.fromString` keeps ANTLR's code-point stream for any input with a surrogate (before apache#67452 every input used `CharStreams.fromString`), so `Token.getStartIndex()` and `getStopIndex()` count code points. The five places in the Change map used them as `String` indexes.
- **Why existing tests missed it:** Unit tests: the masking (`EncryptSQLTest`, `RepositoryAuditEncryptionTest`), view and MTMV (`CreateViewTest`, `CreateMTMVCommandTest`) and hint tests (`LeanTokenModeTest`) use only BMP text, where both kinds of position coincide; `CaseInsensitiveStreamTest` uses an emoji but checks only the stream's own positions. Regression: `audit/test_external_catalog_credential_masking` and the `ddl_p0/create_view_nereids` suites have no supplementary characters, and the masking suite only checks that the whole credential is absent, which a leaked tail passes.
- **Fix:** Convert where the text is cut. `rewriteSql` converts each position with `String.offsetByCodePoints`, walking the sorted positions once so the cost stays linear; `rewriteProjectsToUserDefineAlias` reads expressions through the token's input stream; `getHintMap` reads the hint from the token text, as `removeCommentAndTrimBlank` does. Changing the stream to report `String` positions was rejected: apache#67452 made code-point positions part of `CaseInsensitiveStream`'s contract, and `CaseInsensitiveStreamTest` pins them.
- **Other paths and branches:** Fixed here: the 19 masking visitors of `LogicalPlanBuilderForEncryption` with every caller of `geneEncryptionSQL` (audit log, FE statement log, `_query_plan`) and the streaming insert job; the view, MTMV and sync-MV rewrites. Not affected: the other uses of token positions read text through the token's own stream (such as `getOriginSql`) or only compare positions with each other. branch-3.1, branch-4.0, branch-4.1 and branch-4.2 have the same code. Introduced by apache#32743 (views), apache#47595 (masking), apache#33699 (sync MV) and apache#33262 (EXPLAIN PLAN); hints since at least apache#39590.

### Testing

- New unit tests fail on master `f1bc8b3690c` and pass with the fix, run locally: `EncryptSQLTest#testEncryptionAfterSupplementaryCharacters`, through `MysqlConnectProcessor` to the audit event (emoji inside a credential, in a catalog COMMENT, in the first of two property clauses, in a user name before `PASSWORD(...)`; master left `secret`, `abc`, `123` and `123456` in clear text); `CreateViewTest#testCreateViewRewritesAfterSupplementaryCharacters` (master: `mismatched input '`e`'`); `CreateMTMVCommandTest#testCreateMTMVRewritesQuerySqlAfterSupplementaryCharacters` (master kept ``SELECT '😀😀' A`e` e`internal`...``); `SupplementaryCharacterOffsetTest` (master dropped the hint, cut the EXPLAIN PLAN body to `AN SELECT 100`, and rewrote the sync MV to `avg_stateg(k)))`).
- New regression suite `ddl_p0/create_view_nereids/test_create_view_supplementary_chars`: fails without the fix with the same syntax error and passes with it; the `.out` is generated by the script. Run locally on one FE and one BE, an older master FE build with the three changed classes swapped in.
- 27 existing FE UT classes around the change (467 tests) pass. Reverting each part of the fix alone, moving the end of a replaced span by one, or not advancing the position cursor each fails a new test; the off-by-one also fails existing ASCII cases.
- By hand on that cluster, without the fix: the secret stayed in `audit_log`, `/* 😀 */ select /*+ SET_VAR(query_timeout=1) */ sleep(3)` ran for 3 s, and an MTMV over `select '😀😀' as e, ...` was created but failed to refresh (`Nereids parse failed`). With the fix: `"s3.secret_key" = "*XXX")`, and the query times out after 1 s.

### Notes for Reviewers

- `getHintMap` loses its `sql` parameter, which nothing reads any more; its three callers are in `NereidsParser`.
- `rewriteProjectsToUserDefineAlias` replaces the select list through `rewriteSql` instead of `StringUtils.overlay`, so the conversion lives in one method.
- Stored definitions are not repaired: an MTMV created by an affected version from such a query keeps its broken definition and has to be recreated.

### Release note

Fix passwords and credentials left partly or fully unmasked in the audit log and the FE log when a supplementary character, such as an emoji, comes before or inside them. Also fix CREATE VIEW failing, CREATE MATERIALIZED VIEW storing a broken query, and hints such as SET_VAR being ignored after such a character; materialized views already created with a broken query must be recreated.

### Check List (For Author)

- Behavior changed: No
- Does this need documentation: No
- Pre-submission status: Ready

### AI Disclosure

- Tool: Claude Code (Claude Opus 5.5)
- Generated: the fix, the tests, and this description
- Human review: The author reviewed part of the changes.
- Prompts: After the review bot on apache#70338 reported the masking leak, the author confirmed it is an existing engine defect shared by all masking paths and asked for a separate engine PR that fixes it, followed by a reply on apache#70338 with the link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@morningman
morningman force-pushed the b2m-t38f-codepoint-offsets branch from 910dabb to 9f6f906 Compare November 13, 2026 08:32
@morningman

Copy link
Copy Markdown
Contributor Author

run buildall

@morningman

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review of PR #70366 at head 9f6f906: no verified new defects found. All nine changed files and their relevant producer/consumer paths were reviewed. There are no existing inline P0/P1 findings to carry forward and no additional user-provided review focus.

Critical checkpoint conclusions:

  1. Goal and correctness: the changes consistently translate ANTLR code-point positions at Java String boundaries. Masking, view/MV definitions, hints and EXPLAIN use the text and coordinate origins expected by their callers. The added assertions exercise the intended corrected statements, definitions and hint objects.
  2. Scope and reuse: the fix is focused in three production files. Sync-MV and explicit-column rewriting reuse the shared replacement helper, removing duplicate slicing logic.
  3. Concurrency and locks: no threads, shared mutable state or lock operations are added. New cursors/builders are local to existing statement parsing and analysis.
  4. Lifecycle and initialization: token input remains reachable during extraction; no new retained resource, ownership rule or static initialization dependency.
  5. Configuration: no configuration changes.
  6. Compatibility: all in-repository getHintMap callers use the updated signature; no wire or storage-schema changes. Corrected view/MV definitions use existing persistence. Previously malformed stored MV definitions are not repaired automatically, as the PR documents.
  7. Thrift/protobuf: no definitions changed, so field-ID compatibility checks are inapplicable.
  8. Parallel paths: traced CREATE/ALTER VIEW, async/IVM and sync MV, audit logging, both FE statement-log masking paths, HTTP plan audit and streaming job/task rewriting. Generic, create-view and sync-MV hint parsing all use the updated method; masking continues to omit execution hints.
  9. Conditions and errors: bracketed comments survive lean tokenization with original text, and the prefix check matches the existing comment-normalization convention. Inclusive interval ends, query-relative sync-MV positions, empty/adjacent replacements and source-text identity are consistent. Existing failure boundaries remain intact.
  10. Test coverage: inspected new FE cases for supplementary characters before and inside credentials, multiple property regions, explicit view aliases, MTMV definitions, hints, EXPLAIN and sync-MV aggregate rewriting, alongside existing BMP/lean-token controls. No new malformed-input contract or failure path requires a different negative expectation.
  11. Expected results: regression SHOW CREATE definitions and selected rows match the inserted data, filter and aliases; row comparisons are ordered. Script generation and author-reported test success were not independently rerun.
  12. Observability: the local text-index correction introduces no new operational boundary requiring logs or metrics; existing parser, audit and MV diagnostics remain available.
  13. Persistence and transactions: no EditLog, replay, failover or transaction protocol changes. Rewritten definitions continue through existing validation/storage paths.
  14. Data writes and atomicity: row mutation, visibility/version, delete-bitmap and crash-recovery behavior are unchanged.
  15. FE/BE variables: no new transmitted variables or send paths.
  16. Performance and memory: the replacement cursor advances through the original disjoint spans once, retaining linear source/output complexity. No repeated prefix scan, new parser pass or BE allocation/nullability change was introduced.
  17. Additional review: all analysis-stage interval writers preserve parser-origin coordinates. The existing comparator orders by interval end, which also orders disjoint intervals by start; this change adds no overlapping-span producer. No further verified issue emerged from the independent reviews and final missed-case sweep.

The review converged in round 1: both complete-review agents and the additional risk-focused agent returned NO_NEW_VALUABLE_FINDINGS, all three recorded risks were resolved with code evidence, and no unresolved candidates or static coverage gaps remain. Validation limits: no builds, tests, benchmarks, cluster execution or output regeneration were performed under the static-only contract.

Review converged after 1 round(s).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants