Browse code

Fix for zero-sized layers

Moved a defer up to a better spot.

Fixed TestUntarPathWithInvalidDest to actually fail for the right reason

Closes #18170

Signed-off-by: Doug Davis <dug@us.ibm.com>

Doug Davis authored on 2015/11/24 10:20:44
Showing 5 changed files
... ...
@@ -112,12 +112,12 @@ func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS) (layer.Lay
112 112
 		logrus.Debugf("Error reading embedded tar: %v", err)
113 113
 		return nil, err
114 114
 	}
115
+	defer rawTar.Close()
116
+
115 117
 	inflatedLayerData, err := archive.DecompressStream(rawTar)
116 118
 	if err != nil {
117 119
 		return nil, err
118 120
 	}
119
-
120
-	defer rawTar.Close()
121 121
 	defer inflatedLayerData.Close()
122 122
 
123 123
 	return l.ls.Register(inflatedLayerData, rootFS.ChainID())
... ...
@@ -291,3 +291,12 @@ func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
291 291
 	c.Assert(found, checker.Equals, true, check.Commentf("failed to find the layer with the right content listing"))
292 292
 
293 293
 }
294
+
295
+// Test loading a weird image where one of the layers is of zero size.
296
+// The layer.tar file is actually zero bytes, no padding or anything else.
297
+// See issue: 18170
298
+func (s *DockerSuite) TestLoadZeroSizeLayer(c *check.C) {
299
+	testRequires(c, DaemonIsLinux)
300
+
301
+	dockerCmd(c, "load", "-i", "fixtures/load/emptyLayer.tar")
302
+}
294 303
new file mode 100644
295 304
Binary files /dev/null and b/integration-cli/fixtures/load/emptyLayer.tar differ
... ...
@@ -128,7 +128,13 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
128 128
 	p := pools.BufioReader32KPool
129 129
 	buf := p.Get(archive)
130 130
 	bs, err := buf.Peek(10)
131
-	if err != nil {
131
+	if err != nil && err != io.EOF {
132
+		// Note: we'll ignore any io.EOF error because there are some odd
133
+		// cases where the layer.tar file will be empty (zero bytes) and
134
+		// that results in an io.EOF from the Peek() call. So, in those
135
+		// cases we'll just treat it as a non-compressed stream and
136
+		// that means just create an empty layer.
137
+		// See Issue 18170
132 138
 		return nil, err
133 139
 	}
134 140
 
... ...
@@ -216,11 +216,16 @@ func TestUntarPathWithInvalidDest(t *testing.T) {
216 216
 	invalidDestFolder := path.Join(tempFolder, "invalidDest")
217 217
 	// Create a src file
218 218
 	srcFile := path.Join(tempFolder, "src")
219
-	_, err = os.Create(srcFile)
219
+	tarFile := path.Join(tempFolder, "src.tar")
220
+	os.Create(srcFile)
221
+	os.Create(invalidDestFolder) // being a file (not dir) should cause an error
222
+	cmd := exec.Command("/bin/sh", "-c", "tar cf "+tarFile+" "+srcFile)
223
+	_, err = cmd.CombinedOutput()
220 224
 	if err != nil {
221
-		t.Fatalf("Fail to create the source file")
225
+		t.Fatal(err)
222 226
 	}
223
-	err = UntarPath(srcFile, invalidDestFolder)
227
+
228
+	err = UntarPath(tarFile, invalidDestFolder)
224 229
 	if err == nil {
225 230
 		t.Fatalf("UntarPath with invalid destination path should throw an error.")
226 231
 	}