Merge commit from fork

This commit is contained in:
Samuel Karp committed 2026-09-04 10:58:38 -07:00
commit 65dcc83dad
2 files changed
+150 -1

No files matched your search

+14 -1
View File
@@ -169,6 +169,9 @@ func applyNaive(ctx context.Context, root string, r io.Reader, options ApplyOpti
// Used for handling opaque directory markers which
// may occur out of order
unpackedPaths = make(map[string]struct{})
// Used for tracking directories that have already processed an
// opaque directory marker to avoid redundant directory walks
opaqueDirs = make(map[string]struct{})
convertWhiteout = options.ConvertWhiteout
)
@@ -179,6 +182,11 @@ func applyNaive(ctx context.Context, root string, r io.Reader, options ApplyOpti
base := filepath.Base(path)
dir := filepath.Dir(path)
if base == whiteoutOpaqueDir {
if _, ok := opaqueDirs[dir]; ok {
return false, nil
}
opaqueDirs[dir] = struct{}{}
_, err := os.Lstat(dir)
if err != nil {
return false, err
@@ -195,7 +203,12 @@ func applyNaive(ctx context.Context, root string, r io.Reader, options ApplyOpti
}
if _, exists := unpackedPaths[path]; !exists {
err := os.RemoveAll(path)
return err
if err != nil {
return err
}
if info.IsDir() {
return filepath.SkipDir
}
}
return nil
})
+136
View File
@@ -715,6 +715,38 @@ func TestBreakouts(t *testing.T) {
// resolution ends up just removing etc
validator: fileNotExists("etc/passwd"),
},
{
name: "WhiteoutOpaque",
apply: fstest.Apply(
fstest.CreateDir("/etc/", 0755),
fstest.CreateFile("/etc/passwd", []byte("all users"), 0644),
fstest.CreateFile("/etc/shadow", []byte("root:secret"), 0600),
),
w: tartest.TarAll(
tc.File("etc/.wh..wh..opq", []byte{}, 0600),
tc.File("etc/group", []byte("all groups"), 0644),
),
validator: all(
fileNotExists("etc/passwd"),
fileNotExists("etc/shadow"),
fileValue("etc/group", []byte("all groups")),
),
},
{
name: "WhiteoutOpaqueOutOfOrder",
apply: fstest.Apply(
fstest.CreateDir("/etc/", 0755),
fstest.CreateFile("/etc/passwd", []byte("all users"), 0644),
),
w: tartest.TarAll(
tc.File("etc/group", []byte("all groups"), 0644),
tc.File("etc/.wh..wh..opq", []byte{}, 0600),
),
validator: all(
fileNotExists("etc/passwd"),
fileValue("etc/group", []byte("all groups")),
),
},
{
name: "SymlinkOverridePath",
w: tartest.TarAll(
@@ -1464,3 +1496,107 @@ func requireTar(t *testing.T) {
t.Skipf("%s not found, skipping", tarCmd)
}
}
func TestRepeatedOpaqueWhiteout(t *testing.T) {
ctx := t.Context()
td := t.TempDir()
// Create base directory with lower-layer file
if err := os.WriteFile(filepath.Join(td, "oldfile"), []byte("lower"), 0644); err != nil {
t.Fatal(err)
}
// Create a tar with interleaved files and opaque whiteouts
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
const n = 500
for i := 0; i < n; i++ {
name := fmt.Sprintf("f%04d", i)
if err := tw.WriteHeader(&tar.Header{
Name: name,
Mode: 0644,
Size: 1,
Typeflag: tar.TypeReg,
}); err != nil {
t.Fatal(err)
}
if _, err := tw.Write([]byte("x")); err != nil {
t.Fatal(err)
}
if err := tw.WriteHeader(&tar.Header{
Name: whiteoutOpaqueDir,
Mode: 0600,
Size: 0,
Typeflag: tar.TypeReg,
}); err != nil {
t.Fatal(err)
}
}
if err := tw.Close(); err != nil {
t.Fatal(err)
}
if _, err := Apply(ctx, td, &buf, WithNoSameOwner()); err != nil {
t.Fatalf("failed to apply tar: %v", err)
}
// Verify oldfile was removed by opaque whiteout
if _, err := os.Lstat(filepath.Join(td, "oldfile")); !os.IsNotExist(err) {
t.Errorf("expected oldfile to be removed, err: %v", err)
}
// Verify all unpacked files exist
for i := 0; i < n; i++ {
p := filepath.Join(td, fmt.Sprintf("f%04d", i))
if _, err := os.Lstat(p); err != nil {
t.Errorf("expected %s to exist, err: %v", p, err)
}
}
}
func BenchmarkRepeatedOpaqueWhiteout(b *testing.B) {
ctx := b.Context()
// Build tar payload with interleaved files and opaque whiteouts
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
const n = 1000
for i := 0; i < n; i++ {
name := fmt.Sprintf("f%04d", i)
if err := tw.WriteHeader(&tar.Header{
Name: name,
Mode: 0644,
Size: 1,
Typeflag: tar.TypeReg,
}); err != nil {
b.Fatal(err)
}
if _, err := tw.Write([]byte("x")); err != nil {
b.Fatal(err)
}
if err := tw.WriteHeader(&tar.Header{
Name: whiteoutOpaqueDir,
Mode: 0600,
Size: 0,
Typeflag: tar.TypeReg,
}); err != nil {
b.Fatal(err)
}
}
if err := tw.Close(); err != nil {
b.Fatal(err)
}
payload := buf.Bytes()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
td := b.TempDir()
if _, err := Apply(ctx, td, bytes.NewReader(payload), WithNoSameOwner()); err != nil {
b.Fatalf("failed to apply tar: %v", err)
}
}
}