Skip to content

Commit

Permalink
tarfs: handle tars without trailer
Browse files Browse the repository at this point in the history
Spotted some layers in the wild without the two-block trailer. This changes the
tar parsing code to allow EOFs at block boundaries.

Signed-off-by: Hank Donnay <[email protected]>
  • Loading branch information
hdonnay committed Oct 3, 2022
1 parent ffb3960 commit 6fb6ef5
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 7 deletions.
14 changes: 9 additions & 5 deletions pkg/tarfs/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,18 @@ Scan:
off := blk * blockSz
n, err := r.ReadAt(b, off)
switch {
case n != blockSz:
case errors.Is(err, nil) && n != blockSz:
// Should be impossible with a well-formed archive, so raise an
// error.
return nil, parseErr("short read at offset: %d", off)
case errors.Is(err, io.EOF) && !zeroes:
// error. Should also be impossible with a conforming [io.ReaderAt].
return nil, parseErr("short read at offset: %d (got: %d, want: %d)", off, n, blockSz)
case errors.Is(err, nil): // OK
case errors.Is(err, io.EOF) && n == 0:
// This is an early EOF: in a well-formed archive, ReadAt should
// only return EOF on the second block of zeroes.
case errors.Is(err, nil): // OK
//
// Handle this case because some layers in the wild are a single
// directory block, with no trailer.
break Scan
case errors.Is(err, io.EOF) && zeroes:
break Scan
default:
Expand Down
20 changes: 20 additions & 0 deletions pkg/tarfs/tarfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,23 @@ func TestSymlinks(t *testing.T) {
}
}))
}

func TestKnownLayers(t *testing.T) {
ents, err := os.ReadDir(`testdata/known`)
if err != nil {
t.Fatal(err)
}
for _, ent := range ents {
n := ent.Name()
t.Run(n, func(t *testing.T) {
f, err := os.Open(filepath.Join(`testdata/known`, n))
if err != nil {
t.Fatal(err)
}
defer f.Close()
if _, err := New(f); err != nil {
t.Fatal(err)
}
})
}
}
4 changes: 2 additions & 2 deletions pkg/tarfs/testdata/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
*
!.gitignore
*.layer
fstest.tar
Binary file added pkg/tarfs/testdata/known/oddlayer.tar
Binary file not shown.

0 comments on commit 6fb6ef5

Please sign in to comment.