diff --git a/weed/mount/weedfs_dir_read.go b/weed/mount/weedfs_dir_read.go index e5493001b..57186e08c 100644 --- a/weed/mount/weedfs_dir_read.go +++ b/weed/mount/weedfs_dir_read.go @@ -3,6 +3,7 @@ package mount import ( "context" "errors" + "strings" "sync" "time" @@ -219,7 +220,11 @@ func (wfs *WFS) doReadDirectory(input *fuse.ReadIn, out DirEntrySink, isPlusMode processEachEntryFn := func(entry *filer.Entry, index int64) bool { dirEntry.Name = entry.Name() dirEntry.Mode = toSyscallMode(entry.Mode) - childPath := dirPath.Child(dirEntry.Name) + // Rebuild only for a sanitized name: that is the one a LOOKUP carries. + childPath := entry.FullPath + if !strings.HasSuffix(string(childPath), dirEntry.Name) { + childPath = dirPath.Child(dirEntry.Name) + } var inode uint64 if takesLookupRef { inode = wfs.inodeToPath.Lookup(childPath, entry.Crtime.Unix(), entry.IsDirectory(), len(entry.HardLinkId) > 0, entry.Inode, false) diff --git a/weed/mount/weedfs_dir_read_pagination_test.go b/weed/mount/weedfs_dir_read_pagination_test.go index c2690b403..ba38b3db1 100644 --- a/weed/mount/weedfs_dir_read_pagination_test.go +++ b/weed/mount/weedfs_dir_read_pagination_test.go @@ -336,3 +336,24 @@ func TestReadDirDirectTrimsConsumedEntries(t *testing.T) { t.Errorf("handle held %d entries at peak, want well under the %d in the directory", peak, total) } } + +// The table has to key on the sanitized name, not the stored bytes. +func TestReadDirPlusSanitizedName(t *testing.T) { + dir := util.FullPath("/images") + const rawName = "bad\xffname.jpg" + wfs := newPagingWFS(t, dir, []string{"good.jpg", rawName}, 0) + dirInode, _ := wfs.inodeToPath.GetInode(dir) + + sink := &benchSink{plus: true, takesRef: true, sinkLimit: 16} + if got := walkOnce(t, wfs, dirInode, sink, false); got != 4 { + t.Fatalf("listed %d entries, want 4 (. .. and two children)", got) + } + + sanitized := dir.Child(util.SanitizeUTF8Name(rawName)) + if !wfs.inodeToPath.HasPath(sanitized) { + t.Errorf("%s not in the inode table", sanitized) + } + if wfs.inodeToPath.HasPath(dir.Child(rawName)) { + t.Errorf("%s keyed on the unsanitized name", dir.Child(rawName)) + } +}