From cfbc9ebf939816b897eb94a72f67c43f11977f5f Mon Sep 17 00:00:00 2001
From: xiekeyang <xiekeyang@huawei.com>
Date: Sun, 18 Sep 2016 18:53:19 +0800
Subject: [PATCH] validate media type of manifest and its descendants

migrate from opencontainers/image-spec/pull/273

Signed-off-by: xiekeyang <xiekeyang@huawei.com>
---
 cmd/oci-image-validate/main.go |  2 +-
 image/manifest.go              | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/cmd/oci-image-validate/main.go b/cmd/oci-image-validate/main.go
index f8849bd..044d146 100644
--- a/cmd/oci-image-validate/main.go
+++ b/cmd/oci-image-validate/main.go
@@ -149,7 +149,7 @@ func (v *validateCmd) validatePath(name string) error {
 
 	switch typ {
 	case image.TypeManifest:
-		return schema.MediaTypeManifest.Validate(f)
+		return image.ValidateManifestMediaType(f)
 	case image.TypeManifestList:
 		return schema.MediaTypeManifestList.Validate(f)
 	case image.TypeConfig:
diff --git a/image/manifest.go b/image/manifest.go
index 641e849..cae71b1 100644
--- a/image/manifest.go
+++ b/image/manifest.go
@@ -51,7 +51,7 @@ func findManifest(w walker, d *descriptor) (*manifest, error) {
 			return errors.Wrapf(err, "%s: error reading manifest", path)
 		}
 
-		if err := schema.MediaTypeManifest.Validate(bytes.NewReader(buf)); err != nil {
+		if err := ValidateManifestMediaType(bytes.NewReader(buf)); err != nil {
 			return errors.Wrapf(err, "%s: manifest validation failed", path)
 		}
 
@@ -240,3 +240,33 @@ loop:
 	}
 	return nil
 }
+
+// ValidateManifestMediaType validate the manifest schema media-type
+// and its descendants fields media type, such as config and layers,
+// to make sure they match to spec definition, or returns an error if
+// the validation failed.
+func ValidateManifestMediaType(r io.Reader) error {
+	header := v1.Manifest{}
+
+	buf, err := ioutil.ReadAll(r)
+	if err != nil {
+		return errors.Wrapf(err, "error reading the io stream")
+	}
+
+	err = json.Unmarshal(buf, &header)
+	if err != nil {
+		return errors.Wrap(err, "manifest format mismatch")
+	}
+
+	if header.Config.MediaType != string(v1.MediaTypeImageConfig) {
+		return fmt.Errorf("illegal config mediaType: %s", header.Config.MediaType)
+	}
+
+	for _, layer := range header.Layers {
+		if layer.MediaType != string(v1.MediaTypeImageLayer) {
+			return fmt.Errorf("illegal layer mediaType: %s", layer.MediaType)
+		}
+	}
+
+	return schema.MediaTypeManifest.Validate(bytes.NewReader(buf))
+}