Skip to content

Detect locale code that leaves a string literal open - #328

Merged
nank1ro merged 1 commit into
mainfrom
fix/detect-unterminated-string-literals
Sep 18, 2026
Merged

nank1ro merged 1 commit into
mainfrom
fix/detect-unterminated-string-literals

Conversation

@nank1ro

@nank1ro nank1ro commented Sep 18, 2026

Copy link
Copy Markdown
Owner

A translation pass can drop a \n escape, turning printf("%f\n", x) into a real newline inside the literal, which no longer compiles. Nothing caught this today: the Dart validator never executes type-1 code, check_outputs.py skips type 1, and check_locales.py blanks comment text rather than quotes.

The 12 files this found were already fixed in #312, so it reports zero now — this lands the detector that found them.

How it works

strip_comments in check_locales.py already lexes each language properly (triple-quoted strings, // inside a string, quotes in char literals and comments, backslash escapes), so the checker borrows it rather than matching quotes itself. Two new optional out-params collect what that scan already sees: every line leaving a literal open, and the offset of every /* that never closes.

That second one matters because an unclosed /* is deliberately not comment state — the opener is emitted as text and scanning continues — so an apostrophe in the prose behind it would read as a string opener. en/c/comments/5.md asks the learner to close such a /*, and it/c/comments/5.md writes "il doppio dell'input" behind it. Findings from that offset on are dropped; taking the offset from the lexer keeps a /* inside a string or behind a // from counting.

Seeds holding a [/] placeholder are skipped, since a placeholder can stand for a quote and balance is undecidable; the --solutions-- copy is checked instead. Findings are addressed by (fence, line) so the en baseline excuses only the line en itself trips on, not the whole fence around it.

Verification

  • python3 scripts/test_check_locales.py → ok
  • python3 scripts/check_string_literals.py → 0 unterminated string literal(s), exit 0

Local-only tool, consistent with the other scripts/check_*.py; not wired into CI.

Reviewed independently (gpt-5.6-sol); both findings it raised — fence-wide suppression hiding locale slips, and non-lexical /* counting truncating valid code — are fixed here with regression tests.

A translation pass can drop a \n escape, turning printf("%f\n", x) into a real
newline inside the literal, which no longer compiles. Nothing caught this: the
Dart validator never executes type-1 code, check_outputs.py skips type 1, and
check_locales.py blanks comment text rather than quotes.

strip_comments already lexes each language properly - triple-quoted strings,
// inside a string, quotes in char literals and comments, backslash escapes -
so the checker borrows it rather than matching quotes itself. Two new optional
out-params collect what that scan already sees: every line leaving a literal
open, and the offset of every /* that never closes.

That second one matters because an unclosed /* is deliberately not comment
state - the opener is emitted as text and scanning continues - so an apostrophe
in the prose behind it would read as a string opener. en/c/comments/5.md asks
the learner to close such a /*, and it/c/comments/5.md writes "il doppio
dell'input" behind it. Findings from that offset on are dropped; taking the
offset from the lexer keeps a /* inside a string or behind a // from counting.

Seeds holding a [/] placeholder are skipped, since a placeholder can stand for
a quote and balance is undecidable; the --solutions-- copy is checked instead.
Findings are addressed by (fence, line) so the en baseline excuses only the
line en itself trips on, not the whole fence around it.

The 12 files this found were fixed in #312; it now reports zero.
@nank1ro
nank1ro merged commit 8ad382e into main Sep 18, 2026
4 checks passed
@nank1ro
nank1ro deleted the fix/detect-unterminated-string-literals branch September 18, 2026 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant