Skip to content

--output that is a symlink to the --input folder passes validation and overwrites the source icons (exit 0) #157

Open

Description

@matt-edmondson

What's wrong

Arguments.Validate rejects an --output that is the --input directory. That guard was added for #120 so the masks cannot replace the source icons. But IsSameDirectory (IconHelper/Arguments.cs:95-99) compares the two paths as strings only, using Path.TrimEndingDirectorySeparator and string.Equals with PathComparison. TryResolveDirectory resolves paths with Path.GetFullPath, which does not follow links. So any second spelling of the same directory gets past the check. That covers a symlink, a junction, a bind mount, and on Windows an 8.3 short name.

When that happens, ProcessDirectory writes <base name>.png into the output folder, which is the input folder. The source icons are overwritten in place, and the run prints Done. N file(s) written. and exits 0.

Reproduction (Linux, main @ f640ca4)

mkdir icons && cp some-icon.png icons/a.png
ln -s icons out
md5sum icons/a.png          # ef497c88...
iconhelper -i icons -o out
# Processing .../icons/a.png...
# Done. 1 file(s) written.   (exit 0)
md5sum icons/a.png          # a742e41b...  <- original artwork replaced

iconhelper -i icons -o icons is correctly rejected with "--output must not be the --input directory". The symlinked spelling of the same folder is not.

Suggested fix

When the output directory already exists, compare directory identity instead of path text. Two ways to do that:

  • Resolve both paths to their final targets, for example with Directory.ResolveLinkTarget(path, returnFinalTarget: true) on each segment, or with realpath semantics.
  • Compare the file-system identity of the two directories: device and inode on Unix, volume serial and file ID on Windows.

A non-existent --output cannot alias anything yet, so it can keep the string comparison.

Acceptance criteria

  • Validate fails with the existing "--output must not be the --input directory" error when --output is a symlink to --input.
  • It also fails the other way round, when --input is a symlink to --output.
  • A regression test in ArgumentsTests creates a directory symlink to pin this. It is Inconclusive where symlinks can't be created.
  • A non-existent --output still validates.

Activity

  1. matt-edmondson commented on Oct 30, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions