From a8124280d25262379d26d13816c7c9fcee31d7ca Mon Sep 17 00:00:00 2001 From: Lewis Marshall Date: Sat, 6 Dec 2014 02:30:03 +0000 Subject: [PATCH] Fix chroot untar for zero padded archive from slow reader Signed-off-by: Lewis Marshall --- chrootarchive/archive.go | 5 +++++ chrootarchive/archive_test.go | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/chrootarchive/archive.go b/chrootarchive/archive.go index 41eb79e..f9108c5 100644 --- a/chrootarchive/archive.go +++ b/chrootarchive/archive.go @@ -6,6 +6,7 @@ import ( "flag" "fmt" "io" + "io/ioutil" "os" "path/filepath" "runtime" @@ -38,6 +39,10 @@ func untar() { if err := archive.Unpack(os.Stdin, "/", options); err != nil { fatal(err) } + // fully consume stdin in case it is zero padded + if _, err := ioutil.ReadAll(os.Stdin); err != nil { + fatal(err) + } os.Exit(0) } diff --git a/chrootarchive/archive_test.go b/chrootarchive/archive_test.go index 69e18e3..8477c06 100644 --- a/chrootarchive/archive_test.go +++ b/chrootarchive/archive_test.go @@ -1,10 +1,12 @@ package chrootarchive import ( + "io" "io/ioutil" "os" "path/filepath" "testing" + "time" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/reexec" @@ -42,3 +44,42 @@ func TestChrootTarUntar(t *testing.T) { t.Fatal(err) } } + +type slowEmptyTarReader struct { + size int + offset int + chunkSize int +} + +// Read is a slow reader of an empty tar (like the output of "tar c --files-from /dev/null") +func (s *slowEmptyTarReader) Read(p []byte) (int, error) { + time.Sleep(100 * time.Millisecond) + count := s.chunkSize + if len(p) < s.chunkSize { + count = len(p) + } + for i := 0; i < count; i++ { + p[i] = 0 + } + s.offset += count + if s.offset > s.size { + return count, io.EOF + } + return count, nil +} + +func TestChrootUntarEmptyArchiveFromSlowReader(t *testing.T) { + tmpdir, err := ioutil.TempDir("", "docker-TestChrootUntarEmptyArchiveFromSlowReader") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + dest := filepath.Join(tmpdir, "dest") + if err := os.MkdirAll(dest, 0700); err != nil { + t.Fatal(err) + } + stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024} + if err := Untar(stream, dest, nil); err != nil { + t.Fatal(err) + } +}