diff options
| author | Taras Madan <tarasmadan@google.com> | 2023-07-21 11:51:35 +0200 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2023-07-24 09:12:13 +0000 |
| commit | a36fe24b8383f6cd9b3519cd3eabdb9675d8992d (patch) | |
| tree | 3fef9a57760ccc4013289acd60e94e083db466e6 | |
| parent | 7549a7e1b57831cf6b08ce4700fc6e53417919f9 (diff) | |
all: use errors.As instead of .(type)
| -rw-r--r-- | dashboard/app/access_test.go | 5 | ||||
| -rw-r--r-- | dashboard/app/app_test.go | 9 | ||||
| -rw-r--r-- | dashboard/app/bisect_test.go | 5 | ||||
| -rw-r--r-- | dashboard/app/handler.go | 5 | ||||
| -rw-r--r-- | dashboard/app/reporting_email.go | 14 | ||||
| -rw-r--r-- | dashboard/app/reporting_external.go | 4 | ||||
| -rw-r--r-- | dashboard/app/util_test.go | 5 | ||||
| -rw-r--r-- | pkg/asset/storage.go | 6 | ||||
| -rw-r--r-- | pkg/bisect/bisect.go | 51 | ||||
| -rw-r--r-- | pkg/build/build.go | 5 | ||||
| -rw-r--r-- | pkg/gce/gce.go | 10 | ||||
| -rw-r--r-- | pkg/ifuzz/x86/gen/gen.go | 13 | ||||
| -rw-r--r-- | pkg/instance/instance.go | 7 | ||||
| -rw-r--r-- | pkg/osutil/osutil.go | 13 | ||||
| -rw-r--r-- | pkg/runtest/run.go | 4 | ||||
| -rw-r--r-- | syz-ci/jobs.go | 20 | ||||
| -rw-r--r-- | syz-ci/manager.go | 24 | ||||
| -rw-r--r-- | syz-ci/updater.go | 4 | ||||
| -rw-r--r-- | tools/syz-testbuild/testbuild.go | 31 | ||||
| -rw-r--r-- | vm/gce/gce.go | 6 | ||||
| -rw-r--r-- | vm/vmimpl/merger_test.go | 4 | ||||
| -rw-r--r-- | vm/vmimpl/vmimpl.go | 9 |
22 files changed, 152 insertions, 102 deletions
diff --git a/dashboard/app/access_test.go b/dashboard/app/access_test.go index f7d02d990..7bd412acf 100644 --- a/dashboard/app/access_test.go +++ b/dashboard/app/access_test.go @@ -5,6 +5,7 @@ package main import ( "bytes" + "errors" "fmt" "net/http" "strconv" @@ -387,8 +388,8 @@ func TestAccess(t *testing.T) { t.Fatal(err1) } c.expectNE(err, nil) - httpErr, ok := err.(*HTTPError) - c.expectTrue(ok) + var httpErr *HTTPError + c.expectTrue(errors.As(err, &httpErr)) c.expectEQ(httpErr.Code, http.StatusTemporaryRedirect) c.expectEQ(httpErr.Headers["Location"], []string{loginURL}) } else { diff --git a/dashboard/app/app_test.go b/dashboard/app/app_test.go index d7aae91ed..241e5141d 100644 --- a/dashboard/app/app_test.go +++ b/dashboard/app/app_test.go @@ -4,6 +4,7 @@ package main import ( + "errors" "fmt" "net/http" "os" @@ -820,8 +821,8 @@ func checkLoginRedirect(c *Ctx, accessLevel AccessLevel, url string) { func checkRedirect(c *Ctx, accessLevel AccessLevel, from, to string, status int) { _, err := c.AuthGET(accessLevel, from) c.expectNE(err, nil) - httpErr, ok := err.(*HTTPError) - c.expectTrue(ok) + var httpErr *HTTPError + c.expectTrue(errors.As(err, &httpErr)) c.expectEQ(httpErr.Code, status) c.expectEQ(httpErr.Headers["Location"], []string{to}) } @@ -829,8 +830,8 @@ func checkRedirect(c *Ctx, accessLevel AccessLevel, from, to string, status int) func checkResponseStatusCode(c *Ctx, accessLevel AccessLevel, url string, status int) { _, err := c.AuthGET(accessLevel, url) c.expectNE(err, nil) - httpErr, ok := err.(*HTTPError) - c.expectTrue(ok) + var httpErr *HTTPError + c.expectTrue(errors.As(err, &httpErr)) c.expectEQ(httpErr.Code, status) } diff --git a/dashboard/app/bisect_test.go b/dashboard/app/bisect_test.go index a61f51286..334d5a04d 100644 --- a/dashboard/app/bisect_test.go +++ b/dashboard/app/bisect_test.go @@ -5,6 +5,7 @@ package main import ( "bytes" + "errors" "fmt" "net/http" "strings" @@ -1106,8 +1107,8 @@ func TestBugBisectionInvalidation(t *testing.T) { // Mark bisection as invalid. _, err = c.AuthGET(AccessAdmin, "/admin?action=invalidate_bisection&key="+jobKey.Encode()) - httpErr, ok := err.(*HTTPError) - c.expectTrue(ok) + var httpErr *HTTPError + c.expectTrue(errors.As(err, &httpErr)) c.expectEQ(httpErr.Code, http.StatusFound) // The invalidated bisection should have vanished from the web UI diff --git a/dashboard/app/handler.go b/dashboard/app/handler.go index 6a115d0b2..6b72da0bb 100644 --- a/dashboard/app/handler.go +++ b/dashboard/app/handler.go @@ -50,7 +50,8 @@ func handleContext(fn contextHandler) http.Handler { http.Error(w, "403 Forbidden", http.StatusForbidden) return } - if redir, ok := err.(ErrRedirect); ok { + var redir *ErrRedirect + if errors.As(err, &redir) { http.Redirect(w, r, redir.Error(), http.StatusFound) return } @@ -201,7 +202,7 @@ func commonHeader(c context.Context, r *http.Request, w http.ResponseWriter, ns ns = adminPage } if ns != adminPage || !isAdminPage { - return nil, ErrRedirect{fmt.Errorf("/%v", ns)} + return nil, &ErrRedirect{fmt.Errorf("/%v", ns)} } } if ns != adminPage { diff --git a/dashboard/app/reporting_email.go b/dashboard/app/reporting_email.go index ee87169b7..26a3e57ef 100644 --- a/dashboard/app/reporting_email.go +++ b/dashboard/app/reporting_email.go @@ -703,17 +703,19 @@ func handleTestCommand(c context.Context, info *bugInfoResult, user: msg.Author, extID: msg.MessageID, link: msg.Link, patch: []byte(msg.Patch), repo: args[0], branch: args[1], jobCC: msg.Cc}) if err != nil { - switch e := err.(type) { - case *TestRequestDeniedError: + var testDenied *TestRequestDeniedError + var badTest *BadTestRequestError + switch { + case errors.As(err, &testDenied): // Don't send a reply in this case. - log.Errorf(c, "patch test request denied: %v", e) - case *BadTestRequestError: - reply = e.Error() + log.Errorf(c, "patch test request denied: %v", testDenied) + case errors.As(err, &badTest): + reply = badTest.Error() default: // Don't leak any details to the reply email. reply = "Processing failed due to an internal error" // .. but they are useful for debugging, so we'd like to see it on the Admin page. - log.Errorf(c, "handleTestRequest error: %v", e) + log.Errorf(c, "handleTestRequest error: %v", err) } } return reply diff --git a/dashboard/app/reporting_external.go b/dashboard/app/reporting_external.go index ffe3f00c8..b296139ec 100644 --- a/dashboard/app/reporting_external.go +++ b/dashboard/app/reporting_external.go @@ -5,6 +5,7 @@ package main import ( "encoding/json" + "errors" "fmt" "net/http" @@ -95,7 +96,8 @@ func apiNewTestJob(c context.Context, r *http.Request, payload []byte) (interfac err := handleExternalTestRequest(c, req) if err != nil { resp.ErrorText = err.Error() - if _, ok := err.(*BadTestRequestError); !ok { + var badTest *BadTestRequestError + if !errors.As(err, &badTest) { // Log errors that are not related to the invalid input. log.Errorf(c, "external patch posting error: %v", err) } diff --git a/dashboard/app/util_test.go b/dashboard/app/util_test.go index f748e0dcd..b0ac1c6fe 100644 --- a/dashboard/app/util_test.go +++ b/dashboard/app/util_test.go @@ -8,6 +8,7 @@ package main import ( "bytes" + "errors" "fmt" "io" "net/http" @@ -107,8 +108,8 @@ func (c *Ctx) expectFailureStatus(err error, code int) { if err == nil { c.t.Fatalf("expected to fail as %d, but it does not", code) } - httpErr, ok := err.(*HTTPError) - if !ok || httpErr.Code != code { + var httpErr *HTTPError + if !errors.As(err, &httpErr) || httpErr.Code != code { c.t.Fatalf("expected to fail as %d, but it failed as %v", code, err) } } diff --git a/pkg/asset/storage.go b/pkg/asset/storage.go index 1debdaa4a..8bec1cca8 100644 --- a/pkg/asset/storage.go +++ b/pkg/asset/storage.go @@ -123,7 +123,8 @@ func (storage *Storage) uploadFileStream(reader io.Reader, assetType dashapi.Ass compressor = typeDescr.customCompressor } res, err := compressor(req, storage.backend.upload) - if existsErr, ok := err.(*FileExistsError); ok { + var existsErr *FileExistsError + if errors.As(err, &existsErr) { storage.tracer.Log("asset %s already exists", path) if extra == nil || !extra.SkipIfExists { return "", err @@ -137,7 +138,8 @@ func (storage *Storage) uploadFileStream(reader io.Reader, assetType dashapi.Ass if err != nil { more := "" closeErr := res.writer.Close() - if exiterr, ok := closeErr.(*exec.ExitError); ok { + var exiterr *exec.ExitError + if errors.As(closeErr, &exiterr) { more = fmt.Sprintf(", process state '%s'", exiterr.ProcessState) } return "", fmt.Errorf("failed to redirect byte stream: copied %d bytes, error %w%s", diff --git a/pkg/bisect/bisect.go b/pkg/bisect/bisect.go index 4c02e6336..e1e251cd9 100644 --- a/pkg/bisect/bisect.go +++ b/pkg/bisect/bisect.go @@ -4,6 +4,7 @@ package bisect import ( + "errors" "fmt" "math" "os" @@ -622,12 +623,14 @@ func (env *env) test() (*testResult, error) { } if err != nil { errInfo := fmt.Sprintf("failed building %v: ", current.Hash) - if verr, ok := err.(*osutil.VerboseError); ok { + var verr *osutil.VerboseError + var kerr *build.KernelError + if errors.As(err, &verr) { errInfo += verr.Title env.saveDebugFile(current.Hash, 0, verr.Output) - } else if verr, ok := err.(*build.KernelError); ok { - errInfo += string(verr.Report) - env.saveDebugFile(current.Hash, 0, verr.Output) + } else if errors.As(err, &kerr) { + errInfo += string(kerr.Report) + env.saveDebugFile(current.Hash, 0, kerr.Output) } else { errInfo += err.Error() env.log("%v", err) @@ -722,38 +725,40 @@ func (env *env) processResults(current *vcs.Commit, results []instance.EnvTestRe verdicts = append(verdicts, "OK") continue } - switch err := res.Error.(type) { - case *instance.TestError: - if err.Infra { + var testError *instance.TestError + var crashError *instance.CrashError + switch { + case errors.As(res.Error, &testError): + if testError.Infra { infra++ - verdicts = append(verdicts, fmt.Sprintf("infra problem: %v", err)) - } else if err.Boot { - verdicts = append(verdicts, fmt.Sprintf("boot failed: %v", err)) + verdicts = append(verdicts, fmt.Sprintf("infra problem: %v", testError)) + } else if testError.Boot { + verdicts = append(verdicts, fmt.Sprintf("boot failed: %v", testError)) } else { - verdicts = append(verdicts, fmt.Sprintf("basic kernel testing failed: %v", err)) + verdicts = append(verdicts, fmt.Sprintf("basic kernel testing failed: %v", testError)) } - output := err.Output - if err.Report != nil { - output = err.Report.Output + output := testError.Output + if testError.Report != nil { + output = testError.Report.Output } env.saveDebugFile(current.Hash, i, output) - case *instance.CrashError: - verdicts = append(verdicts, fmt.Sprintf("crashed: %v", err)) - output := err.Report.Report + case errors.As(res.Error, &crashError): + verdicts = append(verdicts, fmt.Sprintf("crashed: %v", crashError)) + output := crashError.Report.Report if len(output) == 0 { - output = err.Report.Output + output = crashError.Report.Output } env.saveDebugFile(current.Hash, i, output) - if env.isTransientError(err.Report) { - verdicts = append(verdicts, fmt.Sprintf("ignore: %v", err)) + if env.isTransientError(crashError.Report) { + verdicts = append(verdicts, fmt.Sprintf("ignore: %v", crashError)) break } bad++ - reports = append(reports, err.Report) - verdicts = append(verdicts, fmt.Sprintf("crashed: %v", err)) + reports = append(reports, crashError.Report) + verdicts = append(verdicts, fmt.Sprintf("crashed: %v", crashError)) default: infra++ - verdicts = append(verdicts, fmt.Sprintf("failed: %v", err)) + verdicts = append(verdicts, fmt.Sprintf("failed: %v", res.Error)) } } unique := make(map[string]bool) diff --git a/pkg/build/build.go b/pkg/build/build.go index 9bcacbd90..52873e3b2 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -7,6 +7,7 @@ package build import ( "bytes" "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -195,8 +196,8 @@ func extractRootCause(err error, OS, kernelSrc string) error { if err == nil { return nil } - verr, ok := err.(*osutil.VerboseError) - if !ok { + var verr *osutil.VerboseError + if !errors.As(err, &verr) { return err } reason, file := extractCauseInner(verr.Output, kernelSrc) diff --git a/pkg/gce/gce.go b/pkg/gce/gce.go index 71b88e2ec..ecc2c9853 100644 --- a/pkg/gce/gce.go +++ b/pkg/gce/gce.go @@ -12,6 +12,7 @@ package gce import ( + "errors" "fmt" "io" "math/rand" @@ -170,7 +171,8 @@ retry: return "", fmt.Errorf("failed to create instance: %w", err) } if err := ctx.waitForCompletion("zone", "create image", op.Name, false); err != nil { - if _, ok := err.(resourcePoolExhaustedError); ok && instance.Scheduling.Preemptible { + var resourcePoolExhaustedError resourcePoolExhaustedError + if errors.As(err, &resourcePoolExhaustedError) && instance.Scheduling.Preemptible { instance.Scheduling.Preemptible = false goto retry } @@ -206,7 +208,8 @@ func (ctx *Context) DeleteInstance(name string, wait bool) error { op, err = ctx.computeService.Instances.Delete(ctx.ProjectID, ctx.ZoneID, name).Do() return }) - if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == 404 { + var apiErr *googleapi.Error + if errors.As(err, &apiErr) && apiErr.Code == 404 { return nil } if err != nil { @@ -270,7 +273,8 @@ func (ctx *Context) DeleteImage(imageName string) error { op, err = ctx.computeService.Images.Delete(ctx.ProjectID, imageName).Do() return }) - if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == 404 { + var apiErr *googleapi.Error + if errors.As(err, &apiErr) && apiErr.Code == 404 { return nil } if err != nil { diff --git a/pkg/ifuzz/x86/gen/gen.go b/pkg/ifuzz/x86/gen/gen.go index aae7429c0..01ba8420b 100644 --- a/pkg/ifuzz/x86/gen/gen.go +++ b/pkg/ifuzz/x86/gen/gen.go @@ -7,6 +7,7 @@ package main import ( "bufio" + "errors" "fmt" "os" "reflect" @@ -19,7 +20,7 @@ import ( "github.com/google/syzkaller/pkg/tool" ) -// nolint: gocyclo, gocognit, funlen +// nolint: gocyclo, gocognit, funlen, dupl func main() { if len(os.Args) != 2 { tool.Failf("usage: gen instructions.txt") @@ -113,8 +114,9 @@ func main() { insn1 = new(x86.Insn) *insn1 = *insn if err := parsePattern(insn1, vals); err != nil { - if _, ok := err.(errSkip); !ok { - reportError(err.Error()) + var errSkip errSkip + if !errors.As(err, &errSkip) { + reportError(errSkip.Error()) } if err.Error() != "" { fmt.Fprintf(os.Stderr, "skipping %v on line %v (%v)\n", insn.Name, i, err) @@ -127,8 +129,9 @@ func main() { break } if err := parseOperands(insn1, vals); err != nil { - if _, ok := err.(errSkip); !ok { - reportError(err.Error()) + var errSkip errSkip + if !errors.As(err, &errSkip) { + reportError(errSkip.Error()) } if err.Error() != "" { fmt.Fprintf(os.Stderr, "skipping %v on line %v (%v)\n", insn.Name, i, err) diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go index ea4084def..7696a945d 100644 --- a/pkg/instance/instance.go +++ b/pkg/instance/instance.go @@ -7,6 +7,7 @@ package instance import ( "encoding/json" + "errors" "fmt" "net" "os" @@ -305,7 +306,8 @@ func (inst *inst) test() EnvTestResult { ret := EnvTestResult{ Error: testErr, } - if bootErr, ok := err.(vm.BootErrorer); ok { + var bootErr vm.BootErrorer + if errors.As(err, &bootErr) { testErr.Title, testErr.Output = bootErr.BootError() ret.RawOutput = testErr.Output rep := inst.reporter.Parse(testErr.Output) @@ -327,7 +329,8 @@ func (inst *inst) test() EnvTestResult { testErr.Title = rep.Title } else { testErr.Infra = true - if infraErr, ok := err.(vm.InfraErrorer); ok { + var infraErr vm.InfraErrorer + if errors.As(err, &infraErr) { // In case there's more info available. testErr.Title, testErr.Output = infraErr.InfraError() } diff --git a/pkg/osutil/osutil.go b/pkg/osutil/osutil.go index 1687cef9d..478c091dc 100644 --- a/pkg/osutil/osutil.go +++ b/pkg/osutil/osutil.go @@ -7,6 +7,7 @@ import ( "bytes" "compress/gzip" "context" + "errors" "fmt" "io" "os" @@ -67,7 +68,8 @@ func Run(timeout time.Duration, cmd *exec.Cmd) ([]byte, error) { text = fmt.Sprintf("timedout after %v %q", timeout, cmd.Args) } exitCode := 0 - if exitErr, ok := err.(*exec.ExitError); ok { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { exitCode = status.ExitStatus() } @@ -120,10 +122,11 @@ func (err *VerboseError) Error() string { } func PrependContext(ctx string, err error) error { - switch err1 := err.(type) { - case *VerboseError: - err1.Title = fmt.Sprintf("%v: %v", ctx, err1.Title) - return err1 + var verboseError *VerboseError + switch { + case errors.As(err, &verboseError): + verboseError.Title = fmt.Sprintf("%v: %v", ctx, verboseError.Title) + return verboseError default: return fmt.Errorf("%v: %w", ctx, err) } diff --git a/pkg/runtest/run.go b/pkg/runtest/run.go index 4f6170fbb..864a9f5f1 100644 --- a/pkg/runtest/run.go +++ b/pkg/runtest/run.go @@ -13,6 +13,7 @@ package runtest import ( "bufio" "bytes" + "errors" "fmt" "os" "path/filepath" @@ -691,7 +692,8 @@ func runTestC(req *RunRequest) { // Tell ASAN to not mess with our NONFAILING. cmd.Env = append(append([]string{}, os.Environ()...), "ASAN_OPTIONS=handle_segv=0 allow_user_segv_handler=1") req.Output, req.Err = osutil.Run(20*time.Second, cmd) - if verr, ok := req.Err.(*osutil.VerboseError); ok { + var verr *osutil.VerboseError + if errors.As(req.Err, &verr) { // The process can legitimately do something like exit_group(1). // So we ignore the error and rely on the rest of the checks (e.g. syscall return values). req.Err = nil diff --git a/syz-ci/jobs.go b/syz-ci/jobs.go index 203a7a8e3..89276c04e 100644 --- a/syz-ci/jobs.go +++ b/syz-ci/jobs.go @@ -5,6 +5,7 @@ package main import ( "bytes" + "errors" "fmt" "io" "os" @@ -517,7 +518,8 @@ func (jp *JobProcessor) bisect(job *Job, mgrcfg *mgrconfig.Config) error { res, err := bisect.Run(cfg) resp.Log = trace.Bytes() if err != nil { - if _, ok := err.(*bisect.InfraError); ok { + var infraErr *bisect.InfraError + if errors.As(err, &infraErr) { resp.Flags |= dashapi.BisectResultInfraError } return err @@ -735,18 +737,20 @@ func aggregateTestResults(results []instance.EnvTestResult) (*patchTestResult, e continue } anyErr = res.Error - switch err := res.Error.(type) { - case *instance.TestError: + var testError *instance.TestError + var crashError *instance.CrashError + switch { + case errors.As(res.Error, &testError): // We should not put rep into resp.CrashTitle/CrashReport, // because that will be treated as patch not fixing the bug. - if rep := err.Report; rep != nil { + if rep := testError.Report; rep != nil { testErr = fmt.Errorf("%v\n\n%s\n\n%s", rep.Title, rep.Report, rep.Output) } else { - testErr = fmt.Errorf("%v\n\n%s", err.Title, err.Output) + testErr = fmt.Errorf("%v\n\n%s", testError.Title, testError.Output) } - case *instance.CrashError: - if resReport == nil || (len(resReport.report.Report) == 0 && len(err.Report.Report) != 0) { - resReport = &patchTestResult{report: err.Report, rawOutput: res.RawOutput} + case errors.As(res.Error, &crashError): + if resReport == nil || (len(resReport.report.Report) == 0 && len(crashError.Report.Report) != 0) { + resReport = &patchTestResult{report: crashError.Report, rawOutput: res.RawOutput} } } } diff --git a/syz-ci/manager.go b/syz-ci/manager.go index 14dd6114c..13f8768e1 100644 --- a/syz-ci/manager.go +++ b/syz-ci/manager.go @@ -5,6 +5,7 @@ package main import ( "crypto/sha256" + "errors" "fmt" "io" "net/http" @@ -339,14 +340,16 @@ func (mgr *Manager) build(kernelCommit *vcs.Commit) error { rep := &report.Report{ Title: fmt.Sprintf("%v build error", mgr.mgrcfg.RepoAlias), } - switch err1 := err.(type) { - case *build.KernelError: - rep.Report = err1.Report - rep.Output = err1.Output - rep.Recipients = err1.Recipients - case *osutil.VerboseError: - rep.Report = []byte(err1.Title) - rep.Output = err1.Output + var kernelError *build.KernelError + var verboseError *osutil.VerboseError + switch { + case errors.As(err, &kernelError): + rep.Report = kernelError.Report + rep.Output = kernelError.Output + rep.Recipients = kernelError.Recipients + case errors.As(err, &verboseError): + rep.Report = []byte(verboseError.Title) + rep.Output = verboseError.Output default: rep.Report = []byte(err.Error()) } @@ -437,8 +440,9 @@ func (mgr *Manager) testImage(imageDir string, info *BuildInfo) error { continue } failures++ - switch err := res.Error.(type) { - case *instance.TestError: + var err *instance.TestError + switch { + case errors.As(res.Error, &err): if rep := err.Report; rep != nil { what := "test" if err.Boot { diff --git a/syz-ci/updater.go b/syz-ci/updater.go index 1d632ddcd..41d6d48f9 100644 --- a/syz-ci/updater.go +++ b/syz-ci/updater.go @@ -4,6 +4,7 @@ package main import ( + "errors" "fmt" "os" "path/filepath" @@ -297,7 +298,8 @@ func (upd *SyzUpdater) build(commit *vcs.Commit) error { func (upd *SyzUpdater) uploadBuildError(commit *vcs.Commit, buildErr error) { var title string var output []byte - if verbose, ok := buildErr.(*osutil.VerboseError); ok { + var verbose *osutil.VerboseError + if errors.As(buildErr, &verbose) { title = verbose.Title output = verbose.Output } else { diff --git a/tools/syz-testbuild/testbuild.go b/tools/syz-testbuild/testbuild.go index daadff3e3..a0d80f057 100644 --- a/tools/syz-testbuild/testbuild.go +++ b/tools/syz-testbuild/testbuild.go @@ -23,6 +23,7 @@ package main import ( "encoding/json" + "errors" "flag" "fmt" "log" @@ -143,7 +144,8 @@ func test(repo vcs.Repo, bisecter vcs.Bisecter, kernelConfig []byte, env instanc KernelConfig: bisectEnv.KernelConfig, }) if err != nil { - if verr, ok := err.(*osutil.VerboseError); ok { + var verr *osutil.VerboseError + if errors.As(err, &verr) { log.Printf("BUILD BROKEN: %v", verr.Title) saveLog(com.Hash, 0, verr.Output) } else { @@ -162,23 +164,26 @@ func test(repo vcs.Repo, bisecter vcs.Bisecter, kernelConfig []byte, env instanc verdicts = append(verdicts, "OK") continue } - switch err := res.Error.(type) { - case *instance.TestError: - if err.Boot { - verdicts = append(verdicts, fmt.Sprintf("boot failed: %v", err)) + + var testError *instance.TestError + var crashError *instance.CrashError + switch { + case errors.As(res.Error, &testError): + if testError.Boot { + verdicts = append(verdicts, fmt.Sprintf("boot failed: %v", testError)) } else { - verdicts = append(verdicts, fmt.Sprintf("basic kernel testing failed: %v", err)) + verdicts = append(verdicts, fmt.Sprintf("basic kernel testing failed: %v", testError)) } - output := err.Output - if err.Report != nil { - output = err.Report.Output + output := testError.Output + if testError.Report != nil { + output = testError.Report.Output } saveLog(com.Hash, i, output) - case *instance.CrashError: - verdicts = append(verdicts, fmt.Sprintf("crashed: %v", err)) - output := err.Report.Report + case errors.As(res.Error, &crashError): + verdicts = append(verdicts, fmt.Sprintf("crashed: %v", crashError)) + output := crashError.Report.Report if len(output) == 0 { - output = err.Report.Output + output = crashError.Report.Output } saveLog(com.Hash, i, output) default: diff --git a/vm/gce/gce.go b/vm/gce/gce.go index 60a88010c..5c91f08de 100644 --- a/vm/gce/gce.go +++ b/vm/gce/gce.go @@ -15,6 +15,7 @@ import ( "archive/tar" "bytes" "compress/gzip" + "errors" "fmt" "io" "os" @@ -318,14 +319,15 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin ssh.Process.Kill() merger.Wait() con.Wait() + var mergeError *vmimpl.MergerError if cmdErr := ssh.Wait(); cmdErr == nil { // If the command exited successfully, we got EOF error from merger. // But in this case no error has happened and the EOF is expected. err = nil - } else if merr, ok := err.(vmimpl.MergerError); ok && merr.R == conRpipe { + } else if errors.As(err, &mergeError) && mergeError.R == conRpipe { // Console connection must never fail. If it does, it's either // instance preemption or a GCE bug. In either case, not a kernel bug. - log.Logf(0, "%v: gce console connection failed with %v", inst.name, merr.Err) + log.Logf(0, "%v: gce console connection failed with %v", inst.name, mergeError.Err) err = vmimpl.ErrTimeout } else { // Check if the instance was terminated due to preemption or host maintenance. diff --git a/vm/vmimpl/merger_test.go b/vm/vmimpl/merger_test.go index 8308aff5e..ef5570509 100644 --- a/vm/vmimpl/merger_test.go +++ b/vm/vmimpl/merger_test.go @@ -5,6 +5,7 @@ package vmimpl import ( "bytes" + "errors" "io" "testing" "time" @@ -62,9 +63,10 @@ func TestMerger(t *testing.T) { t.Fatalf("bad line: '%s', want '%s'", got, want) } + var merr MergerError if err := <-merger.Err; err == nil { t.Fatalf("merger did not produce an error on pipe close") - } else if merr := err.(MergerError); merr.Name != "pipe1" || merr.R != rp1 || merr.Err != io.EOF { + } else if !errors.As(err, &merr) || merr.Name != "pipe1" || merr.R != rp1 || merr.Err != io.EOF { t.Fatalf("merger produced wrong error: %v", err) } diff --git a/vm/vmimpl/vmimpl.go b/vm/vmimpl/vmimpl.go index 9dbd61a92..0a4ada028 100644 --- a/vm/vmimpl/vmimpl.go +++ b/vm/vmimpl/vmimpl.go @@ -93,12 +93,11 @@ type BootError struct { } func MakeBootError(err error, output []byte) error { - switch err1 := err.(type) { - case *osutil.VerboseError: - return BootError{err1.Title, append(err1.Output, output...)} - default: - return BootError{err.Error(), output} + var verboseError *osutil.VerboseError + if errors.As(err, &verboseError) { + return BootError{verboseError.Title, append(verboseError.Output, output...)} } + return BootError{err.Error(), output} } func (err BootError) Error() string { |
