From 70660a7a4a6449d4cc8e3c42f818c3c09d2cfc77 Mon Sep 17 00:00:00 2001 From: "app-runtime-interfaces@cloudfoundry.org" Date: Wed, 3 Dec 2025 18:00:53 +0000 Subject: [PATCH] Update libbuildpack --- go.mod | 2 +- go.sum | 4 +- .../cloudfoundry/libbuildpack/util.go | 168 ++++++++++++++++++ vendor/modules.txt | 2 +- 4 files changed, 172 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index cdd1712ae..3ace6a7c8 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.4 require ( github.com/Dynatrace/libbuildpack-dynatrace v1.8.0 github.com/Masterminds/semver v1.5.0 - github.com/cloudfoundry/libbuildpack v0.0.0-20240717165421-f2ae8069fcba + github.com/cloudfoundry/libbuildpack v0.0.0-20251202224209-b07cc3dab65e github.com/cloudfoundry/switchblade v0.9.0 github.com/golang/mock v1.6.0 github.com/onsi/ginkgo v1.16.5 diff --git a/go.sum b/go.sum index 94a0f8518..23bcb144e 100644 --- a/go.sum +++ b/go.sum @@ -805,8 +805,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= -github.com/cloudfoundry/libbuildpack v0.0.0-20240717165421-f2ae8069fcba h1:RdbOeYpXLO3wdrQrKuQFUIl7aLx6cdk95Lh/uFwAA9c= -github.com/cloudfoundry/libbuildpack v0.0.0-20240717165421-f2ae8069fcba/go.mod h1:kn4FHMwI8bTd9gT92wPGjXHzUvGcj8CkPxG8q3AGBAQ= +github.com/cloudfoundry/libbuildpack v0.0.0-20251202224209-b07cc3dab65e h1:L9bl+eey+J8CQ5Dv24nJ5giUx00gdigZv4ElqzR0uRA= +github.com/cloudfoundry/libbuildpack v0.0.0-20251202224209-b07cc3dab65e/go.mod h1:kn4FHMwI8bTd9gT92wPGjXHzUvGcj8CkPxG8q3AGBAQ= github.com/cloudfoundry/switchblade v0.9.0 h1:4yxlAb526G4XIDEoH9Vp+erCCYcXTD3aYaz5THKhskY= github.com/cloudfoundry/switchblade v0.9.0/go.mod h1:lbxYZXU/aSVmEafP0NZgQaxrf9nBfdT8t2EIiwrP4bU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= diff --git a/vendor/github.com/cloudfoundry/libbuildpack/util.go b/vendor/github.com/cloudfoundry/libbuildpack/util.go index db0b08fc7..686103266 100644 --- a/vendor/github.com/cloudfoundry/libbuildpack/util.go +++ b/vendor/github.com/cloudfoundry/libbuildpack/util.go @@ -150,6 +150,53 @@ func ExtractZip(zipfile, destDir string) error { return nil } +// ExtractZipWithStrip extracts zipfile to destDir, optionally stripping N leading path components +// stripComponents works like tar's --strip-components flag: +// +// 0 = extract as-is (default) +// 1 = remove top-level directory +// 2 = remove two levels, etc. +func ExtractZipWithStrip(zipfile, destDir string, stripComponents int) error { + r, err := zip.OpenReader(zipfile) + if err != nil { + return err + } + defer r.Close() + + for _, f := range r.File { + // Strip leading path components + name := filepath.Clean(f.Name) + if stripComponents > 0 { + parts := strings.Split(name, string(filepath.Separator)) + if len(parts) <= stripComponents { + // Skip files/dirs that would be completely stripped away + continue + } + name = filepath.Join(parts[stripComponents:]...) + } + + path := filepath.Join(destDir, name) + + rc, err := f.Open() + if err != nil { + return err + } + + if f.FileInfo().IsDir() { + err = os.MkdirAll(path, f.Mode()) + } else { + err = writeToFile(rc, path, f.Mode()) + } + + rc.Close() + if err != nil { + return err + } + } + + return nil +} + func ExtractTarXz(tarfile, destDir string) error { file, err := os.Open(tarfile) if err != nil { @@ -161,6 +208,23 @@ func ExtractTarXz(tarfile, destDir string) error { return extractTar(xz, destDir) } +// ExtractTarXzWithStrip extracts tar.xz to destDir, optionally stripping N leading path components +// stripComponents works like tar's --strip-components flag: +// +// 0 = extract as-is (default) +// 1 = remove top-level directory +// 2 = remove two levels, etc. +func ExtractTarXzWithStrip(tarfile, destDir string, stripComponents int) error { + file, err := os.Open(tarfile) + if err != nil { + return err + } + defer file.Close() + xz := xzReader(file) + defer xz.Close() + return extractTarWithStrip(xz, destDir, stripComponents) +} + func xzReader(r io.Reader) io.ReadCloser { rpipe, wpipe := io.Pipe() @@ -208,6 +272,26 @@ func ExtractTarGz(tarfile, destDir string) error { return extractTar(gz, destDir) } +// ExtractTarGzWithStrip extracts tar.gz to destDir, optionally stripping N leading path components +// stripComponents works like tar's --strip-components flag: +// +// 0 = extract as-is (default) +// 1 = remove top-level directory +// 2 = remove two levels, etc. +func ExtractTarGzWithStrip(tarfile, destDir string, stripComponents int) error { + file, err := os.Open(tarfile) + if err != nil { + return err + } + defer file.Close() + gz, err := gzip.NewReader(file) + if err != nil { + return err + } + defer gz.Close() + return extractTarWithStrip(gz, destDir, stripComponents) +} + // CopyFile copies source file to destFile, creating all intermediate directories in destFile func CopyFile(source, destFile string) error { fh, err := os.Open(source) @@ -309,6 +393,90 @@ func extractTar(src io.Reader, destDir string) error { return nil } +func extractTarWithStrip(src io.Reader, destDir string, stripComponents int) error { + tr := tar.NewReader(src) + + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + + // Strip leading path components + name := cleanPath(hdr.Name) + if stripComponents > 0 { + parts := strings.Split(name, string(filepath.Separator)) + if len(parts) <= stripComponents { + // Skip files/dirs that would be completely stripped away + continue + } + name = filepath.Join(parts[stripComponents:]...) + } + + path := filepath.Join(destDir, name) + + fi := hdr.FileInfo() + if fi.IsDir() { + if err := os.MkdirAll(path, hdr.FileInfo().Mode()); err != nil { + return err + } + } else if hdr.Typeflag == tar.TypeSymlink { + if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + return err + } + + if filepath.IsAbs(hdr.Linkname) { + return fmt.Errorf("cannot link to an absolute path when extracting archives") + } + + fullLink, err := filepath.Abs(filepath.Join(filepath.Dir(path), hdr.Linkname)) + if err != nil { + return err + } + + fullDest, err := filepath.Abs(destDir) + if err != nil { + return err + } + + // check that the relative link does not escape the destination dir + if !strings.HasPrefix(fullLink, fullDest) { + return fmt.Errorf("cannot link outside of the destination diretory when extracting archives") + } + + if err = os.Symlink(hdr.Linkname, path); err != nil { + return err + } + } else if hdr.Typeflag == tar.TypeLink { + // For hard links, also strip the link target path + linkname := cleanPath(hdr.Linkname) + if stripComponents > 0 { + parts := strings.Split(linkname, string(filepath.Separator)) + if len(parts) <= stripComponents { + // Skip if link target would be stripped away + continue + } + linkname = filepath.Join(parts[stripComponents:]...) + } + originalPath := filepath.Join(destDir, linkname) + file, err := os.Open(originalPath) + if err != nil { + return err + } + + if err := writeToFile(file, path, hdr.FileInfo().Mode()); err != nil { + return err + } + + } else { + if err := writeToFile(tr, path, hdr.FileInfo().Mode()); err != nil { + return err + } + } + } + return nil +} + func filterURI(rawURL string) (string, error) { unsafeURL, err := url.Parse(rawURL) diff --git a/vendor/modules.txt b/vendor/modules.txt index e4c50da73..d7f54b994 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -20,7 +20,7 @@ github.com/blang/semver # github.com/cenkalti/backoff/v4 v4.3.0 ## explicit; go 1.18 github.com/cenkalti/backoff/v4 -# github.com/cloudfoundry/libbuildpack v0.0.0-20240717165421-f2ae8069fcba +# github.com/cloudfoundry/libbuildpack v0.0.0-20251202224209-b07cc3dab65e ## explicit; go 1.22.5 github.com/cloudfoundry/libbuildpack github.com/cloudfoundry/libbuildpack/ansicleaner