haltcase/glob

symlinks should not be followed by default; can cause infinite recursion or list too many things because of just 1 bad symlink

timotheecour opened this issue · 0 comments

tree
.
└── foo
    └── bar
        └── foo_link -> ../

NOTE: these occur in practice, eg on OSX in app folders IIRC.

import glob,strutils,sequtils
echo toSeq(glob.walkGlob("foo", includeDirs=true)).join("\n")
nim c -o:app test.nim
foo/bar
foo/bar/foo_link
foo/bar/foo_link/bar
foo/bar/foo_link/bar/foo_link                                                                                                                                                                                                                      foo/bar/foo_link/bar/foo_link/bar
foo/bar/foo_link/bar/foo_link/bar/foo_link
foo/bar/foo_link/bar/foo_link/bar/foo_link/bar
foo/bar/foo_link/bar/foo_link/bar/foo_link/bar/foo_link
foo/bar/foo_link/bar/foo_link/bar/foo_link/bar/foo_link/bar
foo/bar/foo_link/bar/foo_link/bar/foo_link/bar/foo_link/bar/foo_link
etc... (82 entries)

Note: curiously, this terminates gracefully without error after 82 lines (maybe an OS limit on path depth, since I'm seeing same behavior with D and python):

./app && echo ok || echo errror
ok
./app | wc -l
82
  • there should be an option followSymlinks = false and indeed symlinks shouldn't be followed by default

  • Note, https://dlang.org/phobos/std_file.html#dirEntries uses followSymlink = true but I think that's the wrong default ; likewise python glob follows and i'm not even seeing a way to not follow symlinks...);

Unix find has the correct default (not follow symlinks), and only follow symlinks if -L is provided, see https://unix.stackexchange.com/a/31121/211423 for more on that rationale.
(either symlink recursion as shown above or a single symlink deep down pointing to ~ or / will cause a ton of entries.)

  • glob should also detect and avoid infinite recursion. Note that D's dirEntries and python's glob currently don't seem to detect this case, but unix find does handle that correctly.

NOTE: alternative would be to not have an option followSymlinks and follow symlinks, and let user filter out symlinks via filterDescend from #8 ; however that's a common enough use case that it should have its own option IMO; also it's indeed a tricky thing to handle (eg infinite recursion) so right here in glob is the right place to handle that.