px-2ms: refuse \U like \u in string escapes - #227
Merged
Merged
Conversation
The lexer's escape refusal matched lowercase ?u only, so "caf\U00e9" fell through the generic escape clause and lexed silently to "cafU00e9". Two spellings of one escape refused differently is the defect: the refusal clause in take_string/6 now guards on `u in [?u, ?U]` and returns the same error for both. Nothing else about escapes changes - `\x` still stands for itself. The language reference's "any other escaped character" rule names the two refused spellings, and the refusal example carries a doctest for each. Refs: px-2ms
Codecov Report✅ All modified and coverable lines are covered by tests.
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves px-2ms (campaign RF047, RQ-RF047-8: refuse
\U, the document-only arm declined).What changed
The lexer's escape refusal in
take_string/6matched lowercase?uonly, so"caf\U00e9"fell through the generic escape clause and lexed silently to"cafU00e9". The clause now guards onu in [?u, ?U]and returns the sameParseErrormessage for both spellings. This is a narrowing of the existingrefusal - exactly the surface the ruling names - and nothing else about escapes
changes:
"a\qb"is stillaqband"Unknown \x escape"is still"Unknown x escape".lib/predicator/lexer.ex- the guard and the comment above it.test/predicator/lexer_test.exs- one negative test pinning\Urefused withthe byte-identical
\umessage, with a one-line sabotage note above it.docs/reference/language.md- the "any other escaped character stands foritself" rule now names
\uand\Uas the refused spellings (the narrowingthe change makes to that rule), and the refusal example carries a doctest for
each spelling. Both run under
test/docs_examples_test.exs.changelog.d/px-2ms.md- a### Fixedfragment (pxchangelog.d/README.md:22-27: "a bug fix a user could have noticed").
No version bump (RQ-RF046-13 stands: no predicator 9.4.2; the fix ships with the
next release).
@versionis unchanged at9.4.1.Sabotage
Mutation: drop
?Ufrom thewhen u in [?u, ?U]guard. Run red - the new testfails with
{:ok, [{:string, 1, 1, 8, "U0041", :double, {1, 9}}, ...]}instead ofan error. Reverted from a copy taken before the mutation;
mix test test/predicator/lexer_test.exsgreen after the revert. (px'sgate.sabotage.test_rootsis a fixed file list that excludeslexer_test.exs,so the gate does not demand the note; the bead does, so it is written.)
Gate
mix qualityon the committed tree, green:gate=green. The repo gate lock and a machine slot were held across the gate run
and the commit; the committed tree is byte-identical to the tree that ran green
(
git write-tree=5e715dabd811de82c520a8feea96a428d6a1c31fbefore and aftergit commit), so the commit step's internal gate re-run was taken in thebare-commit shape citing this run.
Firewall
Terminology scan over the full outbound diff plus the new fragment: hard=0,
soft=0. Constructed positive control: one term from the firewall's hard pattern
(the vendor/integration-name arm) injected into a throwaway copy of the scanned
text; the scan printed a match on that copy, and the copy was deleted when the
result was read.
Provenance
Files touched are exactly the brief's file map minus
conformance/:lib/predicator/lexer.ex,test/predicator/lexer_test.exs,changelog.d/px-2ms.md,docs/reference/language.md.conformance/carries no\uor\Ucase (grep overconformance/returns zero hits), so the also-gatedpath is untouched. No sibling PR was rebased over; the branch is cut from
origin/mainatd06ece1and is one commit ahead.docs/adr/is untouched(
git diff --stat origin/main -- docs/adr/is empty).Scout finding F4 is addressed: the general rule at
docs/reference/language.mdthat the
\qdoctest pins is restated so it stays true under the narrowing, andthe
\qand\xsiblings stay green.