Skip to content

Report a reformatted failpoint header instead of panicking - #158

Open
arpitjain099 wants to merge 1 commit into
etcd-io:masterfrom
arpitjain099:fix/reformatted-failpoint-header
Open

Report a reformatted failpoint header instead of panicking#158
arpitjain099 wants to merge 1 commit into
etcd-io:masterfrom
arpitjain099:fix/reformatted-failpoint-header

Conversation

@arpitjain099

Copy link
Copy Markdown

ToComments spots a generated header by looking for , __fpErr := __fp_ on an if line, then reads the failpoint's type out of that same line:

t := strings.Split(strings.Split(l, ".(")[1], ")")[0]

The generator writes that header as a single line, so this normally works. gofmt splits it across several lines, which leaves the type assertion on a later line than the if. The header match still fires on the if line, strings.Split(l, ".(") returns one element, and indexing it panics.

Three ordinary commands reproduce it, no hand-edited file:

$ gofail enable .
$ gofmt -w svc.go          # or any editor format-on-save, or make fmt
$ gofail disable .
panic: runtime error: index out of range [1] with length 1
  go.etcd.io/gofail/code.ToComments  code/rewrite.go:115
  main.xfrmFile                      gofail.go:62
  main.main                          gofail.go:177

There is a second effect worth knowing about. The crash leaves a zero-byte svc.go.tmp behind, and after that every enable and disable on the tree fails:

$ gofail disable .
open /tmp/gfrepro/mypkg/svc.go.tmp: file exists
$ gofail enable .
open /tmp/gfrepro/mypkg/svc.go.tmp: file exists

so the tool stays wedged until someone deletes the temp file by hand. gofail.go:174 walks every .go file under the given paths, so one reformatted file aborts the whole run.

With the change that same input reports itself and leaves the tree alone:

gofail: failpoint "SlowDown" header is missing its type assertion, the generated code
may have been reformatted: "\tif vSlowDown, __fpErr := __fp_SlowDown.Acquire(); __fpErr == nil {"

No panic, no orphaned .tmp, and a normal enable then disable round trip still restores the original source byte for byte.

Deliberately scoped: teaching ToComments to parse the reformatted multi-line shape would be a bigger change and a separate discussion. This only stops the panic and the wedged temp file. The new test feeds the gofmt'd header straight to ToComments and asserts an error; it panics without the change.

ToComments detects a generated header by looking for ", __fpErr := __fp_" on
an "if" line, then reads the type out of the same line with

  strings.Split(strings.Split(l, ".("), 1)[0]

The generator writes that header as one line, but gofmt splits it, which
leaves the type assertion on a later line. The header match still fires on
the "if" line, so the split returns one element and indexing it panics.

Reproduced with three ordinary commands and no hand-edited file:

  gofail enable .
  gofmt -w svc.go        # or any editor format-on-save
  gofail disable .
  panic: runtime error: index out of range [1] with length 1
    go.etcd.io/gofail/code.ToComments code/rewrite.go:115
    main.xfrmFile gofail.go:62
    main.main gofail.go:177

The crash also leaves a zero-byte svc.go.tmp behind, and every later enable
or disable on that tree then fails with "open ...svc.go.tmp: file exists"
until it is deleted by hand.

Return an error naming the failpoint instead. gofail.go already reports the
error and stops, so the source file is left intact and no temp file is
orphaned. Teaching ToComments to read the reformatted shape would be a
larger change; this only stops the panic.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@kubernetes-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: arpitjain099
Once this PR has been reviewed and has the lgtm label, please assign serathius for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

AruneshDwivedi added a commit to AruneshDwivedi/gofail that referenced this pull request Aug 29, 2026
When gofmt reformats a failpoint header across multiple lines, the type
assertion lands on a later line than the 'if'. ToComments would panic
with index out of range when trying to extract the type from the header
line. Return a descriptive error instead, preventing the crash and the
wedged .tmp file that leaves the tool unusable until manually cleaned up.

Fixes etcd-io#158

Signed-off-by: Arunesh Dwivedi <arunesh.devops@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

1 participant