archive: fix corrupt listings when listing a zip directory more than once
The zip archiver handed out its cached directory tree directly. Any caller which filters a listing in place (as the core listing code does) altered the cache, so later listings of the same directory could be corrupted. Return a copy of the cached listing instead.
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -217,7 +218,8 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
|
|||||||
return nil, fs.ErrorDirNotFound
|
return nil, fs.ErrorDirNotFound
|
||||||
}
|
}
|
||||||
fs.Debugf(f, "dir=%q, entries=%v", dir, entries)
|
fs.Debugf(f, "dir=%q, entries=%v", dir, entries)
|
||||||
return entries, nil
|
// Return a copy as callers may filter the listing in place
|
||||||
|
return slices.Clone(entries), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewObject finds the Object at remote.
|
// NewObject finds the Object at remote.
|
||||||
|
|||||||
@@ -128,3 +128,30 @@ func TestReadZipRootNamedEntry(t *testing.T) {
|
|||||||
remotes := allRemotes(t, f)
|
remotes := allRemotes(t, f)
|
||||||
assert.Equal(t, []string{"good.txt"}, remotes)
|
assert.Equal(t, []string{"good.txt"}, remotes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listings are served from a cache which must survive callers
|
||||||
|
// filtering the returned slice in place, as fs/list does.
|
||||||
|
func TestListCacheNotAliased(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
dir := t.TempDir()
|
||||||
|
name := writeZip(t, dir, "test.zip", "a.txt", "b.txt", "c.txt")
|
||||||
|
|
||||||
|
localFs, err := cache.Get(ctx, dir)
|
||||||
|
require.NoError(t, err)
|
||||||
|
f, err := New(ctx, localFs, name, "", "")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
entries, err := f.List(ctx, "")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, entries, 3)
|
||||||
|
// Compact in place, dropping the first entry
|
||||||
|
copy(entries, entries[1:])
|
||||||
|
|
||||||
|
entries, err = f.List(ctx, "")
|
||||||
|
require.NoError(t, err)
|
||||||
|
var remotes []string
|
||||||
|
for _, entry := range entries {
|
||||||
|
remotes = append(remotes, entry.Remote())
|
||||||
|
}
|
||||||
|
assert.Equal(t, []string{"a.txt", "b.txt", "c.txt"}, remotes)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user