Skip to content

Commit

Permalink
jar: skip corrupt jar file
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Frost <[email protected]>
Signed-off-by: Hank Donnay <[email protected]>
  • Loading branch information
frostmar authored and hdonnay committed Sep 7, 2023
1 parent d7ef4a1 commit 546f138
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 6 deletions.
23 changes: 17 additions & 6 deletions java/jar/jar.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ func Parse(ctx context.Context, name string, z *zip.Reader) ([]Info, error) {
goto Finish
case errors.Is(err, errUnpopulated):
case strings.HasPrefix(base, "javax") && errors.Is(err, ErrNotAJar):
case errors.Is(err, ErrNotAJar):
return nil, err

Check warning on line 94 in java/jar/jar.go

View check run for this annotation

Codecov / codecov/patch

java/jar/jar.go#L93-L94

Added lines #L93 - L94 were not covered by tests
default:
return nil, mkErr(name, err)
}
Expand All @@ -103,6 +105,8 @@ func Parse(ctx context.Context, name string, z *zip.Reader) ([]Info, error) {
goto Finish
case errors.Is(err, errUnpopulated) || errors.Is(err, errInsaneManifest):
case strings.HasPrefix(base, "javax") && errors.Is(err, ErrNotAJar):
case errors.Is(err, ErrNotAJar):
return nil, err
default:
return nil, mkErr(name, err)
}
Expand Down Expand Up @@ -146,7 +150,7 @@ func extractManifest(ctx context.Context, name string, z *zip.Reader) (Info, err
mf, err := z.Open(manifestPath)
switch {
case errors.Is(err, nil):
case errors.Is(err, fs.ErrNotExist):
case errors.Is(err, fs.ErrNotExist), errors.Is(err, zip.ErrFormat):
return Info{}, mkErr("manifest", notAJar(name, err))
default:
return Info{}, err
Expand All @@ -165,10 +169,13 @@ func extractManifest(ctx context.Context, name string, z *zip.Reader) (Info, err
func extractProperties(ctx context.Context, name string, z *zip.Reader) ([]Info, error) {
const filename = "pom.properties"
mf, err := z.Open(`META-INF`)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return nil, mkErr("properties", notAJar(name, err))
}
switch {
case errors.Is(err, nil):
case errors.Is(err, fs.ErrNotExist),
errors.Is(err, zip.ErrFormat),
errors.Is(err, zip.ErrChecksum):
return nil, mkErr("properties", notAJar(name, err))
default:

Check warning on line 178 in java/jar/jar.go

View check run for this annotation

Codecov / codecov/patch

java/jar/jar.go#L178

Added line #L178 was not covered by tests
return nil, mkErr("properties", err)
}
mf.Close()
Expand All @@ -193,7 +200,11 @@ func extractProperties(ctx context.Context, name string, z *zip.Reader) ([]Info,
ret := make([]Info, len(pf))
for i, p := range pf {
f, err := z.Open(p)
if err != nil {
switch {
case errors.Is(err, nil):
case errors.Is(err, zip.ErrFormat), errors.Is(err, zip.ErrChecksum):
return nil, mkErr("properties", notAJar(name, err))
default:

Check warning on line 207 in java/jar/jar.go

View check run for this annotation

Codecov / codecov/patch

java/jar/jar.go#L205-L207

Added lines #L205 - L207 were not covered by tests
return nil, err
}
err = ret[i].parseProperties(ctx, f)
Expand Down
94 changes: 94 additions & 0 deletions java/jar/jar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,100 @@ func TestJARBadManifest(t *testing.T) {
}
}

// TestMalformed creates a malformed zip, then makes sure the package handles it
// gracefully.
func TestMalformed(t *testing.T) {
const (
jarName = `malformed_zip.jar`
manifest = `testdata/malformed_zip.MF`
)
t.Parallel()
ctx := zlog.Test(context.Background(), t)
dir := integration.PackageCacheDir(t)
fn := filepath.Join(dir, jarName)
Open:
f, err := os.Open(fn)
switch {
case errors.Is(err, nil):
case errors.Is(err, os.ErrNotExist):
// Create the jar-like.
mk, err := os.Create(fn)
if err != nil {
t.Fatal(err)
}
defer func() {
if err := mk.Close(); err != nil {
t.Logf("non-failing error: %v", err)
}
if t.Failed() {
if err := os.Remove(fn); err != nil {
t.Error(err)
}
}
}()
w := zip.NewWriter(mk)
if _, err := w.Create(`META-INF/`); err != nil {
t.Fatal(err)
}
fw, err := w.Create(`META-INF/MANIFEST.MF`)
if err != nil {
t.Fatal(err)
}
mf, err := os.ReadFile(manifest)
if err != nil {
t.Fatal(err)
}
if _, err := io.Copy(fw, bytes.NewReader(mf)); err != nil {
t.Fatal(err)
}
if err := w.Close(); err != nil {
t.Fatal(err)
}

// Then, corrupt it.
// Seek to the central directory footer:
pos, err := mk.Seek(-0x16+0x10 /* sizeof(footer) + offset(dir_offset)*/, io.SeekEnd)
if err != nil {
t.Fatal(err)
}
b := make([]byte, 4)
if _, err := io.ReadFull(mk, b); err != nil {
t.Fatal(err)
}
// Offset everything so the reader slowly descends into madness.
b[0] -= 7
if _, err := mk.WriteAt(b, pos); err != nil {
t.Fatal(err)
}

if err := mk.Sync(); err != nil {
t.Error(err)
}
goto Open
default:
t.Fatal(err)
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
t.Fatal(err)
}
z, err := zip.NewReader(f, fi.Size())
if err != nil {
t.Fatal(err)
}
infos, err := Parse(ctx, jarName, z)
t.Logf("returned error: %v", err)
switch {
case errors.Is(err, ErrNotAJar):
default:
t.Fail()
}
if len(infos) != 0 {
t.Errorf("returned infos: %#v", infos)
}
}

func TestManifestSectionReader(t *testing.T) {
var ms []string
d := os.DirFS("testdata")
Expand Down
5 changes: 5 additions & 0 deletions java/jar/testdata/malformed_zip.MF
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Manifest-Version: 1.0
Created-By: 666 (claircore testing)

Name: foo
Other-Key: blah

0 comments on commit 546f138

Please sign in to comment.