Skip to content

Commit

Permalink
Add zlib support to extractGzip (#713)
Browse files Browse the repository at this point in the history
* Add zlib support to extractGzip

Signed-off-by: egibs <[email protected]>

* Appease the linter

Signed-off-by: egibs <[email protected]>

* Use Z instead of zlib

Signed-off-by: egibs <[email protected]>

---------

Signed-off-by: egibs <[email protected]>
  • Loading branch information
egibs authored Dec 18, 2024
1 parent 3db3999 commit f297f5d
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
50 changes: 39 additions & 11 deletions pkg/action/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"archive/zip"
"compress/bzip2"
"compress/gzip"
"compress/zlib"
"context"
"errors"
"fmt"
Expand All @@ -19,6 +20,7 @@ import (
"github.com/cavaliergopher/cpio"
"github.com/cavaliergopher/rpm"
"github.com/chainguard-dev/clog"
"github.com/chainguard-dev/malcontent/pkg/programkind"

"github.com/egibs/go-debian/deb"

Expand Down Expand Up @@ -225,7 +227,6 @@ func extractTar(ctx context.Context, d string, f string) error {
// extractGzip extracts .gz archives.
func extractGzip(ctx context.Context, d string, f string) error {
logger := clog.FromContext(ctx).With("dir", d, "file", f)
logger.Debug("extracting gzip")

// Check if the file is valid
_, err := os.Stat(f)
Expand All @@ -239,23 +240,50 @@ func extractGzip(ctx context.Context, d string, f string) error {
}
defer gf.Close()

gr, err := gzip.NewReader(gf)
// Determine if we're extracting a gzip- or zlib-compressed file
ft, err := programkind.File(f)
if err != nil {
return fmt.Errorf("failed to create gzip reader: %w", err)
return fmt.Errorf("failed to determine file type: %w", err)
}
defer gr.Close()

logger.Debugf("extracting %s", ft.Ext)

base := filepath.Base(f)
target := filepath.Join(d, base[:len(base)-len(filepath.Ext(base))])

ef, err := os.Create(target)
if err != nil {
return fmt.Errorf("failed to create extracted file: %w", err)
}
defer ef.Close()
switch ft.Ext {
case "gzip":
gr, err := gzip.NewReader(gf)
if err != nil {
return fmt.Errorf("failed to create gzip reader: %w", err)
}
defer gr.Close()

if _, err := io.Copy(ef, io.LimitReader(gr, maxBytes)); err != nil {
return fmt.Errorf("failed to copy file: %w", err)
ef, err := os.Create(target)
if err != nil {
return fmt.Errorf("failed to create extracted file: %w", err)
}
defer ef.Close()

if _, err := io.Copy(ef, io.LimitReader(gr, maxBytes)); err != nil {
return fmt.Errorf("failed to copy file: %w", err)
}
case "Z":
zr, err := zlib.NewReader(gf)
if err != nil {
return fmt.Errorf("failed to create zlib reader: %w", err)
}
defer zr.Close()

ef, err := os.Create(target)
if err != nil {
return fmt.Errorf("failed to create extracted file: %w", err)
}
defer ef.Close()

if _, err := io.Copy(ef, io.LimitReader(zr, maxBytes)); err != nil {
return fmt.Errorf("failed to copy file: %w", err)
}
}

return nil
Expand Down
10 changes: 9 additions & 1 deletion pkg/programkind/programkind.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
// file extension to MIME type, if it's a good scanning target.
var supportedKind = map[string]string{
"7z": "",
"Z": "application/zlib",
"asm": "",
"bash": "application/x-bsh",
"bat": "application/bat",
Expand All @@ -39,6 +40,7 @@ var supportedKind = map[string]string{
"expect": "text/x-expect",
"fish": "text/x-fish",
"go": "text/x-go",
"gzip": "application/gzip",
"h": "text/x-h",
"hh": "text/x-h",
"html": "",
Expand All @@ -57,9 +59,9 @@ var supportedKind = map[string]string{
"pyc": "application/x-python-code",
"rb": "text/x-ruby",
"rs": "text/x-rust",
"script": "text/x-generic-script",
"scpt": "application/x-applescript",
"scptd": "application/x-applescript",
"script": "text/x-generic-script",
"service": "text/x-systemd",
"sh": "application/x-sh",
"so": "application/x-sharedlib",
Expand Down Expand Up @@ -101,6 +103,8 @@ func makeFileType(path string, ext string, mime string) *FileType {
}

// File detects what kind of program this file might be.
//
//nolint:cyclop // ignore complexity of 38
func File(path string) (*FileType, error) {
// Follow symlinks and return cleanly if the target does not exist
_, err := filepath.EvalSymlinks(path)
Expand Down Expand Up @@ -176,6 +180,10 @@ func File(path string) (*FileType, error) {
return Path(".c"), nil
case strings.Contains(s, "BEAMAtU8"):
return Path(".beam"), nil
case hdr[0] == '\x1f' && hdr[1] == '\x8b':
return Path(".gzip"), nil
case hdr[0] == '\x78' && hdr[1] == '\x5E':
return Path(".Z"), nil
}
return nil, nil
}
Expand Down

0 comments on commit f297f5d

Please sign in to comment.