more robust manifest <-> tarball handling

This commit is contained in:
Motiejus Jakštys 2021-05-24 00:11:58 +03:00
parent 10dc856e92
commit 7f2293859b
2 changed files with 26 additions and 6 deletions

View File

@ -15,13 +15,13 @@ import (
const (
_manifestJSON = "manifest.json"
_layerSuffix = "/layer.tar"
_tarSuffix = ".tar"
_whReaddir = ".wh..wh..opq"
_whPrefix = ".wh."
)
var (
errBadManifest = errors.New("bad or missing manifest.json")
errBadManifest = errors.New("bad manifest.json")
)
type (
@ -63,7 +63,7 @@ func Flatten(rd io.ReadSeeker, w io.Writer) (err error) {
if err := dec.Decode(&manifest); err != nil {
return fmt.Errorf("decode %s: %w", _manifestJSON, err)
}
case strings.HasSuffix(hdr.Name, _layerSuffix):
case strings.HasSuffix(hdr.Name, _tarSuffix):
here, err := rd.Seek(0, io.SeekCurrent)
if err != nil {
return err
@ -72,8 +72,8 @@ func Flatten(rd io.ReadSeeker, w io.Writer) (err error) {
}
}
if len(manifest) == 0 || len(layerOffsets) != len(manifest[0].Layers) {
return errBadManifest
if err := validateManifest(layerOffsets, manifest); err != nil {
return err
}
// enumerate layers the way they would be laid down in the image
@ -228,6 +228,21 @@ func whiteoutDirs(whreaddir map[string]int, nlayers int) []*tree {
return ret
}
// validateManifest
func validateManifest(layerOffsets map[string]int64, manifest dockerManifestJSON) error {
if len(manifest) == 0 {
return fmt.Errorf("empty or missing manifest")
}
for _, layer := range manifest[0].Layers {
if _, ok := layerOffsets[layer]; !ok {
return fmt.Errorf("%s defined in manifest, missing in tarball", layer)
}
}
return nil
}
// openTargz creates a tar reader from a targzip or tar.
//
// It will try to open a gzip stream, and, if that fails, silently fall back to

View File

@ -44,10 +44,15 @@ func TestRootFS(t *testing.T) {
image: tarball{manifest{}},
want: []extractable{},
},
{
name: "no manifest",
image: tarball{},
wantErr: "empty or missing manifest",
},
{
name: "missing layer",
image: tarball{manifest{"layer0/layer.tar"}},
wantErr: "bad or missing manifest.json",
wantErr: "layer0/layer.tar defined in manifest, missing in tarball",
},
{
name: "basic file overwrite, layer order mixed",