Summary
The action panics with index out of range [1] with length 1 at diff/diff.go:44 when a pull request contains a file whose only change is a permission/mode bit (no content diff). The bug is present in both v2.0.0 and v2.1.0.
A fix with a regression test is available in PR #221.
How to reproduce
Open a pull request that includes at least one file with a mode-only change — for example removing the executable bit from a file with no content changes:
git checkout -b repro/mode-change
chmod -x some-file.yaml # was 100755, becomes 100644
git add some-file.yaml
git commit -m "chore: remove execute bit"
git push origin repro/mode-change
# open PR — the action panics during "Preprocessing diffs..."
The resulting diff contains a block with no --- / +++ file headers:
diff --git a/some-file.yaml b/some-file.yaml
old mode 100755
new mode 100644
Observed behaviour
panic: runtime error: index out of range [1] with length 1
goroutine 1 [running]:
github.com/launchdarkly/find-code-references-in-pull-request/diff.checkDiffFile(...)
/app/diff/diff.go:44 +0x46a
github.com/launchdarkly/find-code-references-in-pull-request/diff.PreprocessDiffs(...)
/app/diff/diff.go:21 +0x9d
main.main()
/app/main.go:60 +0x4c5
Note: a stat: no such file or directory line is sometimes printed just before the panic — that comes from a separate, preceding file processed normally and is unrelated to the crash.
Root cause
checkDiffFile splits OrigName and NewName on / and unconditionally accesses index [1]:
// diff/diff.go:42-45
parsedFileA := strings.SplitN(parsedDiff.OrigName, "/", 2)
parsedFileB := strings.SplitN(parsedDiff.NewName, "/", 2)
fullPathToA := workspace + "/" + parsedFileA[1] // line 44 — PANICS
fullPathToB := workspace + "/" + parsedFileB[1]
For a standard git diff, file names always carry an a/ or b/ prefix (or are /dev/null), so SplitN always returns two elements. Mode-only diffs have no --- / +++ headers at all. The sourcegraph/go-diff parser therefore returns OrigName = "" and NewName = "" for those entries:
strings.SplitN("", "/", 2) // returns [""] — length 1, not 2
Accessing [1] on a single-element slice is a runtime panic.
Fix
PR #221 adds a length guard before indexing and a regression test:
if len(parsedFileA) < 2 || len(parsedFileB) < 2 {
return "", true // no file headers → nothing to scan, skip entry
}
Environment
|
|
| Action version |
v2.1.0 (30f4c4ab) and v2.0.0 |
| Runner OS |
Linux (self-hosted, x64) |
go-diff |
github.com/sourcegraph/go-diff v0.6.1 |
Summary
The action panics with
index out of range [1] with length 1atdiff/diff.go:44when a pull request contains a file whose only change is a permission/mode bit (no content diff). The bug is present in both v2.0.0 and v2.1.0.A fix with a regression test is available in PR #221.
How to reproduce
Open a pull request that includes at least one file with a mode-only change — for example removing the executable bit from a file with no content changes:
The resulting diff contains a block with no
---/+++file headers:diff --git a/some-file.yaml b/some-file.yaml old mode 100755 new mode 100644Observed behaviour
Root cause
checkDiffFilesplitsOrigNameandNewNameon/and unconditionally accesses index[1]:For a standard git diff, file names always carry an
a/orb/prefix (or are/dev/null), soSplitNalways returns two elements. Mode-only diffs have no---/+++headers at all. Thesourcegraph/go-diffparser therefore returnsOrigName = ""andNewName = ""for those entries:Accessing
[1]on a single-element slice is a runtime panic.Fix
PR #221 adds a length guard before indexing and a regression test:
Environment
30f4c4ab) and v2.0.0go-diffgithub.com/sourcegraph/go-diff v0.6.1