diff --git a/internal/sourceanalysis/rust.go b/internal/sourceanalysis/rust.go index b6a1c8720db..f7601e15388 100644 --- a/internal/sourceanalysis/rust.go +++ b/internal/sourceanalysis/rust.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "io" - "log" "os" "os/exec" "path/filepath" @@ -193,8 +192,11 @@ func extractRlibArchive(rlibPath string) (bytes.Buffer, error) { } for { header, err := reader.Next() + if errors.Is(err, io.EOF) { + return bytes.Buffer{}, fmt.Errorf("no object file found in rlib archive '%s'", rlibPath) + } if err != nil { - log.Fatalf("%v", err) + return bytes.Buffer{}, fmt.Errorf("failed to read rlib archive '%s': %w", rlibPath, err) } if header.Name == "//" { // "//" is used in GNU ar format as a store for long file names fileBuf := bytes.Buffer{} diff --git a/internal/sourceanalysis/rust_test.go b/internal/sourceanalysis/rust_test.go index 9d7db5f281a..1dca97c477b 100644 --- a/internal/sourceanalysis/rust_test.go +++ b/internal/sourceanalysis/rust_test.go @@ -2,6 +2,7 @@ package sourceanalysis import ( "bytes" + "fmt" "os" "path/filepath" "reflect" @@ -103,3 +104,30 @@ func Test_rustBuildSource(t *testing.T) { } } } + +// An ar archive with no object file member is not an rlib we can analyse, so it should return +// an error. +func Test_extractRlibArchive_noObjectFile(t *testing.T) { + t.Parallel() + + // Built by hand so the test needs no `ar` binary on the machine running it. + var archive bytes.Buffer + archive.WriteString("!\n") + const content = "hi" + // name[16] mtime[12] uid[6] gid[6] mode[8] size[10] fmag[2] + fmt.Fprintf(&archive, "%-16s%-12d%-6d%-6d%-8s%-10d`\n", "a.txt/", 0, 0, 0, "100644", len(content)) + archive.WriteString(content) + + path := filepath.Join(t.TempDir(), "not-an-rlib.rlib") + if err := os.WriteFile(path, archive.Bytes(), 0600); err != nil { + t.Fatalf("failed to write test archive: %v", err) + } + + _, err := extractRlibArchive(path) + if err == nil { + t.Fatal("expected an error for an ar archive with no object file, got nil") + } + if !strings.Contains(err.Error(), "no object file found") { + t.Errorf("expected a 'no object file found' error, got: %v", err) + } +}