After two days of turning my brain into an unrecog...
# development
b
After two days of turning my brain into an unrecognizable slurry slaving over symlink support in Pants' engine, including mentally debugging and programming while rocking my son at 3am in a pitchblack-room, sound-machine full-blast; I am PLEASED to present this very evil test case passes:
Copy code
pytest.param(
            CreateDigest(
                [
                    FileContent("file.txt", b"four\n"),
                    SymlinkEntry("a/dirlink", "../b/c/d"),
                    SymlinkEntry("b/c/d/link", "../../file.txt"),
                ]
            ),
            # NOTE: No "b/c/d/link", because that'd result in "a/file.txt"
            ("a/dirlink/link", "file.txt"),
            ("a", "a/dirlink", "b", "b/c", "b/c/d"),
            id="symlink-makes-updir-valid",
        ),
Please let me know your favorite evil symlink scenario, and we'll turn the testing up to 11.
2
b
Ohh, this is exciting! Some of my "favourite" cases (
lhs -> rhs
is a link called
lhs
pointing to a file
rhs
, i.e. created via
ln -s rhs lhs
)
Copy code
.
├── broken -> doesnt_exist
├── dir
│   ├── parent -> ..
│   ├── self -> .
│   ├── self_obtusely -> ../dir
│   └── self_very_obtusely -> self/self/self/self/self_obtusely/parent/dir/parent/dir/parent/dir/self
├── escape
│   ├── absolute -> /etc/passwd
│   └── traversal -> ../../../../../../../../../../../../etc/passwd
└── loop
    ├── chain1 -> chain2
    ├── chain2 -> chain3
    ├── chain3 -> chain1
    ├── self -> self
    ├── via_chain -> chain1/file.txt
    └── via_self -> self/file.txt
Most of these are ... going out of my way to be difficult, but: • I imagine the
escape/absolute
one could come in practice, e.g. a Python venv seems to have an absolute symlink to its interpreter. •
readlink -f dir/self_very_obtusely
confirms that it is pointing to
dir/
• Naive tooling may infinite-loop on some of the
loop
ones too.
😈 1
b
(Luckly absolute paths are not traversed in this code)
Oh
self_obtusely
is gnarly. Since the preceder is
.
, you can't just go resolve the parent directory but lopping off the component above it. You need to resolve that, then go up one!
"."
is the evilest symlink in existance
😈 1