Repository navigation
fix: remove \l/\U replacement case flags from names and flash keys (#4646) - #4652
Merged
Merged
Conversation
Adobe CF 2023 update 26 / 2025 update 14 parse the \l and \U replacement case flags as literal letters, so hyphenated route names became "wheels-l-lis-la-l-lframework", flash keys became "lSuccess", and named route derivation produced "adminUposts". #4649 fixed the \u sites; this covers the remaining \l/\U sites. - hyphenize(): drop the redundant \l flags - the final LCase already lower-cases the inserted letters and the hyphen insertion means the second pass never depends on the first pass's case. - redirection.cfc: lower-case the first character after the flash prefix by hand (Len > 5 mirrors the old required sixth character; CompareNoCase mirrors the case-insensitive prefix). - mapper/matching.cfc: add $upperCaseAfterComma() and use it for named routes; it trims comma runs, removes them, and upper-cases the following word character using the same engine \w class as the old pattern. Output is identical on unpatched engines (guarded differential + explicit expected outputs in the specs). No public API change. Signed-off-by: Peter Amiri <peter@alurium.com>
Adobe's MID parameter validation rejects the two-argument form used in the flash-key rewrite: onApplicationStart failed with FunctionArgMismatchException and every request returned 500 on adobe2023/adobe2025. Pass Len(item) - 6 explicitly; the resulting key is unchanged. Signed-off-by: Peter Amiri <peter@alurium.com>
Follow-up to the Adobe MID fix: prefer RemoveChars(item, 1, 6) over the counted Mid tail (no zero-length slicing for the six-character "flashX" input), add the flash1 and flash- cases to redirectionSpec, guard the three follow-up files against reintroducing the \l/\U replacement case flags, and add non-ASCII entries to the named-route differential corpus. Signed-off-by: Peter Amiri <peter@alurium.com>
This was referenced Oct 28, 2026
Closed
Merged
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.
Summary
Refs #4646 (tracking issue — the
\usites landed in #4649; this covers the remaining\l/\Ureplacement case flags, and keeps the backreference audit open).Adobe CF 2023 update 26 / 2025 update 14 parse the replacement case flags
\l/\Uas literal letters, so on patched builds:hyphenize()turnedwheelsIsAFrameworkintowheels-l-lis-la-l-lframework;lSuccess/lAlertinstead ofsuccess/alert;adminUpostsinstead ofadminPosts.All three sites now use engine-neutral equivalents with no replacement-string case flags.
Changes
global/strings.cfmhyphenize()— removed the two\lflags. They are redundant: the function ends withLCase(), and the first pass inserts a hyphen before the lower-cased letter so the second pass's[a-z][A-Z]boundary never depends on that letter's case.controller/redirection.cfc— the flash key is lowercased by hand:Len(item) > 5mirrors the old pattern's required sixth character,CompareNoCase(Left(item, 5), "flash") == 0mirrorsReReplaceNoCase's case-insensitive^flash, andLCase(Mid(item, 6, 1)) & Mid(item, 7)mirrors the one-character capture.mapper/matching.cfc— new public$helper$upperCaseAfterComma()(same style as the merged$upperCaseAfterDash): trims leading/trailing comma runs, removes comma runs, upper-cases the following character when it matches the engine's own\wclass, then the named-route code calls it.ReFind("^\w$", next)deliberately uses the same engine class as the legacy, +(\w)pattern, so non-ASCII behaviour stays per-engine (RustCFML matchesé, Lucee 7 does not).No public API change (
$upperCaseAfterCommais internal;hyphenize()output unchanged; flash keys and route names produce pre-patch values).Specs
global/stringsSpec.cfc— exacttoBeWithCasecases for the brief's shapes (aB,aBcD,XMLHttpRequest,foo.Bar,a1B,foo_Bar,éclair, empty) plus a guarded differential against the old replacement when the case flags still parse.controller/redirectionSpec.cfc—flashSuccess/flashAlertmap tosuccess/alert; an argument named exactlyflashstaysflash;FlashSuccessmatches the prefix case-insensitively.mapper/MatchingSpec.cfc— table for$upperCaseAfterComma(admin,posts, repeated/leading/trailing commas, digits,-show,a,_b, empty) plus a guarded differential against the old trim +\U+ comma-removal sequence.mapper/NestedResourcesSpec.cfc— the nested-resource integration path now asserts the exact name set captured from the pre-patch mapper (postComments,postComment,newPostComment,editPostComment) instead of a substring check.Focused runs on Lucee 7: strings 23 passed, redirection 56, Matching 25, NestedResources 12; full core suite 7376 passed.
Patch-26 verification limitation
CI/local images are pre-patch (
adobe@2023.0.11+330706,adobe@2025.0.06+331564), so u26/u14 cannot be executed here. Correctness is pinned by explicit expected outputs, the guarded differential (byte-identical to the legacy replacements on pre-patch engines), and a committed source guard (global/adobeU26LowerUpperSourceSpec.cfc) that fails if any of the three files reintroduces a\l/\Ureplacement case flag; confirmation on a patched Adobe build is still required. No backreference-only replacement (\1/\2without case flags) is changed in this PR — the audit list from the brief stays open on #4646.Verification
bash tools/test-local.sh(full core suite) → 7376 passedtools/test-matrix.sh lucee7,adobe2023,adobe2025,boxlang sqlite→ lucee7 7357, boxlang 7357, adobe2023 7351, adobe2025 7352 — all 0 failed / 0 erroredbash tools/rustcfml/run-suite.sh→ RustCFML v0.742.2 7329 passed, 0 failed, 0 errors, 182 skippedAdobe caught during verification
The first CI run failed every Adobe leg with HTTP 500 during engine start. Adobe's
MIDparameter validation rejects the two-argument form, soMid(local.item, 7)in the flash-key rewrite brokeonApplicationStart(FunctionArgMismatchException; every request 500). Fixed by passingLen(local.item) - 6explicitly (commit 3c8c1ad); the resulting key is unchanged, and the Adobe legs pass locally and in CI.Final head (9792f63): the flash-key tail now uses
RemoveChars(local.item, 1, 6)(Adobe-safe, noRight(s,0)), withflash1/flash-/exact-flashcases in redirectionSpec; a newadobeU26LowerUpperSourceSpecpins the absence of\l/\Ureplacement flags in the three production files (it fails if they return); and the MatchingSpec differential corpus includesadmin,éshowfor the engine-specific\wbehaviour. CI green on Lucee 6/7, Adobe 2023/2025 (cold start + smoke), BoxLang and RustCFML; patched u26/u14 still needs community confirmation.