Skip to content

Commit de85fa5

Browse files
committed
fix(spec): don't panic on invalid UTF-8 in requirement names
applyRename built a regexp with regexp.MustCompile from an unescaped requirement name; a name containing invalid UTF-8 (or a bad pattern) panicked the whole process. Use regexp.Compile and fall back to leaving the content unchanged, and ReplaceAllLiteralString so $$ in the new name is not treated as a group reference. Found by the new FuzzParseDeltaSpec target.
1 parent 6209822 commit de85fa5

2 files changed

Lines changed: 11 additions & 2 deletions

File tree

‎internal/spec/delta_fuzz_test.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ func FuzzParseDeltaSpec(f *testing.F) {
1111
f.Add("## ADDED Requirements\n")
1212
f.Add("## REMOVED Requirements\n### Requirement: x\n**Reason**: y")
1313
f.Add("## RENAMED Requirements\n### Requirement: x\n- FROM: a\n- TO: b")
14+
// Regression: a RENAMED requirement name with invalid UTF-8 used to panic
15+
// in applyRename's regexp.MustCompile.
16+
f.Add("## RENAMED Requirements\n### Requirement: x\n- FROM: \xff0\n- TO: y")
1417

1518
f.Fuzz(func(t *testing.T, content string) {
1619
ds, err := ParseDeltaSpec(content)

‎internal/spec/delta_merge.go‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,14 @@ func deleteRemoved(content string, req DeltaRequirement) string {
7272
func applyRename(content string, req DeltaRequirement) string {
7373
oldName := regexp.QuoteMeta(req.OldName)
7474
newName := req.NewName
75-
re := regexp.MustCompile(`(?m)^### Requirement: ` + oldName + `$`)
76-
return re.ReplaceAllString(content, "### Requirement: "+newName)
75+
re, err := regexp.Compile(`(?m)^### Requirement: ` + oldName + `$`)
76+
if err != nil {
77+
// An unparseable name (e.g. invalid UTF-8) must not panic; leave the
78+
// content unchanged.
79+
return content
80+
}
81+
// Literal replacement so "$" in the new name is not treated as a group ref.
82+
return re.ReplaceAllLiteralString(content, "### Requirement: "+newName)
7783
}
7884

7985
// renderRequirementBlock renders a delta requirement as markdown.

0 commit comments

Comments
 (0)