Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't follow symlinks when adding files to tarballs #634

Merged
merged 1 commit into from
Nov 30, 2018

Conversation

fhunleth
Copy link
Contributor

Path.wildcard("**") follows symlinks when collecting all of the files
under a path. This can lead to files in the tarball containing paths
with the symlink in them. If the directory corresponding to the symlink
hasn't been created, then the extraction will fail.

As an example, the "create with files" unit test now contains a symlink
in a directory. Without the fix, it fails like this:

  1) test create with files (Mix.Tasks.Hex.BuildTest)
     test/mix/tasks/hex.build_test.exs:42
     ** (MatchError) no match of right hand side value: {:error, :eexist}
     code: in_tmp(fn ->
     stacktrace:
       test/mix/tasks/hex.build_test.exs:13: Mix.Tasks.Hex.BuildTest.extract/2
       test/mix/tasks/hex.build_test.exs:69: anonymous fn/0 in Mix.Tasks.Hex.BuildTest."test create with files"/1
       (elixir) lib/file.ex:1443: File.cd!/2
       test/mix/tasks/hex.build_test.exs:45: (test)

Untaring the contents.tar.gz shows the problem.

$ tar tfz contents.tar.gz
myfile.txt
executable.sh
dir/.dotfile
dir/a_link_to_dir2
dir/a_link_to_dir2/test.txt
dir/dir2/test.txt
empty_dir/
link_dir

dir/a_link_to_dir2 is created as a symlink to dir/dir2. The
test.txt file is then extracted to it. This fails since dir2 hasn't
been created yet so a_link_to_dir2 is dangling. It's also not
desirable that test.txt was included twice.

This test seems like it is dependent on the order that the OS lists
files in a directory. My tests are on Linux, but OSX orders files
differently. The symlink starts with an "a" to try to force it to list
first.

After the fix in this commit, the contents.tar.gz looks like this:

$ tar tfz contents.tar.gz
myfile.txt
executable.sh
dir/a_link_to_dir2
dir/dir2/test.txt
dir/.dotfile
empty_dir/
link_dir

As you can see, test.txt is listed once and its parent directory is
the real directory, dir2, and not the symlink.

Fixes #631.

Path.wildcard("**") follows symlinks when collecting all of the files
under a path. This can lead to files in the tarball containing paths
with the symlink in them. If the directory corresponding to the symlink
hasn't been created, then the extraction will fail.

As an example, the "create with files" unit test now contains a symlink
in a directory. Without the fix, it fails like this:

```
  1) test create with files (Mix.Tasks.Hex.BuildTest)
     test/mix/tasks/hex.build_test.exs:42
     ** (MatchError) no match of right hand side value: {:error, :eexist}
     code: in_tmp(fn ->
     stacktrace:
       test/mix/tasks/hex.build_test.exs:13: Mix.Tasks.Hex.BuildTest.extract/2
       test/mix/tasks/hex.build_test.exs:69: anonymous fn/0 in Mix.Tasks.Hex.BuildTest."test create with files"/1
       (elixir) lib/file.ex:1443: File.cd!/2
       test/mix/tasks/hex.build_test.exs:45: (test)
```

Untaring the `contents.tar.gz` shows the problem.

```sh
$ tar tfz contents.tar.gz
myfile.txt
executable.sh
dir/.dotfile
dir/a_link_to_dir2
dir/a_link_to_dir2/test.txt
dir/dir2/test.txt
empty_dir/
link_dir
```

`dir/a_link_to_dir2` is created as a symlink to `dir/dir2`. The
`test.txt` file is then extracted to it. This fails since `dir2` hasn't
been created yet so `a_link_to_dir2` is dangling. It's also not
desirable that `test.txt` was included twice.

This test seems like it is dependent on the order that the OS lists
files in a directory. My tests are on Linux, but OSX orders files
differently. The symlink starts with an "a" to try to force it to list
first.

After the fix in this commit, the `contents.tar.gz` looks like this:

```sh
$ tar tfz contents.tar.gz
myfile.txt
executable.sh
dir/a_link_to_dir2
dir/dir2/test.txt
dir/.dotfile
empty_dir/
link_dir
```

As you can see, `test.txt` is listed once and its parent directory is
the real directory, `dir2`, and not the symlink.

Fixes hexpm#631.
@wojtekmach wojtekmach merged commit 4a6e4fa into hexpm:master Nov 30, 2018
@wojtekmach
Copy link
Member

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

nerves_system_br packages built with v0.17.3 and later fail to untar (missing directories?)
3 participants