Skip to content
This repository was archived by the owner on Jun 30, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions jar/walker.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,20 @@ type Walker struct {
HandleReport func(path string, r *Report)
// HandleRewrite is called when a JAR is rewritten successfully.
HandleRewrite func(path string, r *Report)
// Parser will be used when checking JARs, if provided. If
// unset, a Parser with sensible defaults will be created.
Parser *Parser
}

// Walk attempts to scan a directory for vulnerable JARs.
func (w *Walker) Walk(dir string) error {
p := w.Parser
if p == nil {
p = &Parser{}
}

fsys := os.DirFS(dir)
wk := walker{w, fsys, dir}
wk := walker{w, fsys, dir, p}

return fs.WalkDir(fsys, ".", func(p string, d fs.DirEntry, err error) error {
if err != nil {
Expand All @@ -88,6 +96,8 @@ type walker struct {
*Walker
fs fs.FS
dir string
// p is the Parser to use for this walk. p is guaranteed to be non-nil.
p *Parser
}

func (w *walker) filepath(path string) string {
Expand Down Expand Up @@ -154,7 +164,7 @@ func (w *walker) visit(p string, d fs.DirEntry) error {
if !IsJAR(zr) {
return nil
}
r, err := Parse(zr)
r, err := w.p.Parse(zr)
if err != nil {
return fmt.Errorf("scanning jar: %v", err)
}
Expand Down
57 changes: 57 additions & 0 deletions jar/walker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package jar

import (
"path/filepath"
"strings"
"testing"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -177,3 +178,59 @@ func TestWalkerRewrite(t *testing.T) {
t.Errorf("walking filesystem after rewrite returned diff (-want, +got): %s", diff)
}
}

// TestNonDefaultParser verifies that Walker can be configured with a
// non-default Parser by scanning a large JAR file with two
// configurations: one where Parser.MaxBytes is larger than the file
// size and one where Parser.MaxBytes is smaller than the file
// size. It ensures that the first case succeeds and the second fails.
func TestNonDefaultParser(t *testing.T) {
jar := "400mb_jar_in_jar.jar"

tempDir := t.TempDir()
src := testdataPath(jar)
dest := filepath.Join(tempDir, jar)
cpFile(t, dest, src)

tests := []struct {
desc string
maxBytes int64
wantErr bool
}{
{
desc: "MaxBytes > JAR size",
maxBytes: 4 << 30, // 4GiB
wantErr: false,
},
{
desc: "MaxBytes < JAR size",
maxBytes: 4 << 20, // 4MiB
wantErr: true,
},
}

for _, tc := range tests {
t.Run(tc.desc, func(t *testing.T) {
var gotErr error

p := &Parser{MaxBytes: tc.maxBytes}
w := &Walker{
Parser: p,
HandleError: func(path string, err error) {
if err != nil && strings.HasSuffix(path, filepath.FromSlash("/"+jar)) {
gotErr = err
}
},
}
if err := w.Walk(tempDir); err != nil {
t.Errorf("Walk returned unexpected error: %v", err)
}

if tc.wantErr && gotErr == nil {
t.Error("Parser failed to generate expected error when scanning JARs > MaxBytes, got nil, want error")
} else if !tc.wantErr && gotErr != nil {
t.Errorf("Parser generated unexpected error when scanning JARs <= MaxBytes, got %v, want nil error", gotErr)
}
})
}
}