Skip to content

Commit f147267

Browse files
committed
fs: Fix bug with ArchiveFS.Open
Only open the exact filename, not first filename with the same prefix... oops
1 parent a639a2a commit f147267

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

fs.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -438,14 +438,24 @@ func (f ArchiveFS) Open(name string) (fs.File, error) {
438438
// paths in archives can't necessarily be trusted; also clean up any "./" prefix
439439
file.NameInArchive = path.Clean(file.NameInArchive)
440440

441-
if !strings.HasPrefix(file.NameInArchive, name) {
441+
// ignore this entry if it's neither the file we're looking for, nor
442+
// one of its descendents; we can't just check that the filename is
443+
// a prefix of the requested file, because that could wrongly match
444+
// "a/b/c.jpg.json" if the requested filename is "a/b/c.jpg", and
445+
// this could result in loading the wrong file (!!) so we append a
446+
// path separator to ensure that can't happen: "a/b/c.jpg.json/"
447+
// is not prefixed by "a/b/c.jpg/", but it will still match as we
448+
// expect: "a/b/c/d/" is is prefixed by "a/b/c/", allowing us to
449+
// match descenedent files, and "a/b/c.jpg/" is prefixed by
450+
// "a/b/c.jpg/", allowing us to match exact filenames.
451+
if !strings.HasPrefix(file.NameInArchive+"/", name+"/") {
442452
return nil
443453
}
444454

445455
// if this is the requested file, and it's a directory, set up the dirFile,
446-
// which will include a listing of all its contents as we continue the walk
456+
// which will include a listing of all its contents as we continue iterating
447457
if file.NameInArchive == name && file.IsDir() {
448-
fsFile = &dirFile{info: file} // will fill entries slice as we continue the walk
458+
fsFile = &dirFile{info: file} // will fill entries slice as we continue iterating
449459
return nil
450460
}
451461

@@ -738,7 +748,8 @@ func (f *ArchiveFS) Sub(dir string) (fs.FS, error) {
738748
// The exported fields may be changed during the lifetime of a DeepFS value
739749
// (but not concurrently). It is safe to use this type as an FS concurrently.
740750
type DeepFS struct {
741-
// The root filepath on disk.
751+
// The root filepath using OS separator, even if it
752+
// traverses into an archive.
742753
Root string
743754

744755
// An optional context, mainly for cancellation.
@@ -859,7 +870,6 @@ func (*DeepFS) splitPath(path string) (realPath, innerPath string) {
859870

860871
for {
861872
part := strings.TrimRight(strings.ToLower(path[start:end]), " ")
862-
863873
for _, ext := range archiveExtensions {
864874
if strings.HasSuffix(part, ext) {
865875
// we've found an archive extension, so the path until the end of this segment is

0 commit comments

Comments
 (0)