@@ -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.
740750type 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