fix(adopt): two real bugs found in a live adoption (ReDoS + slug-hyphen breakage) - #47
Merged
Merged
Conversation
adopt.sh's Phase 5 wiring step hung indefinitely (observed >10min, ctrl-C required) on any adoptee whose [workspace.package] edition was already "2024" - i.e. anything NOT "2015"/"2018"/"2021". The (?ms) flag combo put `.` in DOTALL mode inside a repeated (?:(?!^[).*\n)*? group; once the tail literal fails to match, the engine exhausts exponentially many backtrack paths before giving up. Dropping the DOTALL flag (keep only (?m), matching the sibling regex three lines up that never had this bug) makes the same search linear: confirmed via isolated repro, still running after 5s before the fix, ~0.1ms after. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
adopt.sh's placeholder rename (step 3) substituted the raw SLUG verbatim everywhere, including inside copied .rs source. SLUG is validated as [a-z][a-z0-9-]* - kebab-case is the norm for crate/tool names - but Rust identifiers can't contain '-'. A hyphenated slug (e.g. "uffs-products") turned `acmex_version::` into `uffs-products_version::` in every copied tool crate: invalid syntax, silent build breakage. Cargo.toml/paths are unaffected and correctly stay kebab-case (Cargo itself maps package name "foo-bar" to module path `foo_bar` at compile time) - only *.rs files needed the underscore form done here instead. Reported live: adoption into a repo with a hyphenated slug broke all 4 copied template tool crates (acmex-version and friends) the same way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
githubrobbi
force-pushed
the
fix/adopt-redos-edition-regex
branch
from
July 20, 2026 22:45
6a922c0 to
6646b43
Compare
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
Two independent bugs in
adopt.sh, both found live during an adoption into an existing repo (uffs-products), not from code review:ReDoS in the edition-bump regex (
adopt.shPhase 5 wiring).(?ms)puts.in DOTALL mode inside a repeated group(?:(?!^\[).*\n)*?. When the trailing literal fails to match - any adoptee already on edition 2024, i.e. not "2015"/"2018"/"2021" - the engine backtracks combinatorially instead of failing fast. Observed: 10+ minutes hung, had to ctrl-C. Fix: drop thesflag, keep(?m)only - matches the sibling regex three lines up (tbl_m) which never had DOTALL and never hung. Isolated repro: still running after 5s before the fix, ~0.1ms after.Slug-hyphen breaks Rust syntax (
adopt.shstep 3, placeholder rename).SLUGis validated as[a-z][a-z0-9-]*- kebab-case project slugs are the norm - but the rename pass substituted the raw hyphenatedSLUGverbatim into.rsfiles too.acmex_version::becameuffs-products_version::: invalid Rust syntax, breaking all 4 copied template tool crates. Cargo.toml/paths are correctly unaffected (Cargo already maps package namefoo-bar-> module pathfoo_barat compile time) - only.rsfile substitution needed the underscore form. Fix: computeSLUG_IDENT/CAP_IDENT/UP_IDENT(hyphens -> underscores) and use those specifically when the destination file is*.rs; every other file type keeps the kebab-case form.Test plan
[workspace.package]block already on edition 2024) - hangs >5s before, ~0.1ms after.SLUG=uffs-products- confirmsuse uffs_products_version::VERSION;(wasuffs-products_version::VERSION;), Cargo.tomlname = "uffs-products-version"unaffected.bash -n adopt.sh- syntax OK.PYWIREheredoc,python3 -m py_compile- syntax OK.lint-fast+lint-pre-pushgates passed locally on both commits.adopt.shend-to-end - opening a follow-up issue to add a smoke test (adopt into a fixture repo with a hyphenated slug already on edition 2024) so both regression classes are caught automatically.A third bug from the same live adoption - a
justrecipe-name collision between the template'sjust/analysis.just(audit:) and a pre-existing projectjust/dev.justalso definingaudit:, which brokejustentirely - is not fixed here; it needs real collision-detection design (adopt.sh's copy step only checks destination file existence, not recipe-name collisions across files). Filed separately as #49.