summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Mat M <matm@gmx.fr>2019-12-08 00:25:53 +0100
committerGravatar Mike Burns <mburns@thoughtbot.com>2020-01-17 16:46:06 -0500
commitf2fb351c391dca7c188a8623e71519619c2ce9a0 (patch)
tree28efb32af5fa87d62807131e85dbe1529ef23c4a
parentfb8045f1cf3c8a76cba700d4e0507992be738f89 (diff)
Do not symlink a symlink in mkrc
We have a bug when calling mkrc(1) on a symlink: ```sh mkrc ~/.vimrc # links ~/.vimrc to ~/.dotfiles/vimrc mkrc ~/.vimrc # deletes ~/.dotfiles/vimrc ``` This catches that case ahead of time, preventing the user from running mkrc(1) on a symlink. Fix #144.
-rw-r--r--Makefile.am1
-rw-r--r--NEWS.md.in2
-rwxr-xr-xbin/mkrc.in23
-rwxr-xr-xbin/rcup.in4
-rw-r--r--share/rcm.sh.in4
-rw-r--r--test/mkrc-no-symlinks.t26
6 files changed, 56 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index 16164d9..4af524d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,6 +24,7 @@ TESTS = \
test/mkrc-copy-file.t \
test/mkrc-host-file.t \
test/mkrc-hostname.t \
+ test/mkrc-no-symlinks.t \
test/mkrc-simple-output.t \
test/mkrc-spaces.t \
test/mkrc-symlink-dirs.t \
diff --git a/NEWS.md.in b/NEWS.md.in
index 6af5d4e..4461a2f 100644
--- a/NEWS.md.in
+++ b/NEWS.md.in
@@ -1,5 +1,7 @@
rcm (@PACKAGE_VERSION@) unstable; urgency=low
+ * Fix #144 and more: all symlinks in input are rejected (Mat M)
+
-- Mike Burns <mburns@thoughtbot.com> Fri, 13 Jul 2018 14:12:00 -0500
rcm (1.3.3) unstable; urgency=low
diff --git a/bin/mkrc.in b/bin/mkrc.in
index 5d6af7e..d246c33 100755
--- a/bin/mkrc.in
+++ b/bin/mkrc.in
@@ -20,6 +20,28 @@ destination() {
fi
}
+exit_if_dangerous() {
+ local file="$1"
+
+ if [ -L "$file" ]; then
+ $ERROR 1 "'$file' is a symlink. Cannot process file."
+ elif is_nested "$file"; then
+ # Remove DEST_DIR in case $HOME is under a symlink
+ saved_ifs="$IFS"
+ IFS=/
+ set -- $(dirname "$file" | sed "s|$DEST_DIR/||")
+ IFS="$saved_ifs"
+
+ built_dir="$DEST_DIR"
+ for dir in $@; do
+ built_dir="$built_dir/$dir"
+ if [ -L "$built_dir" ]; then
+ $ERROR 1 "'$file' path contains a symlink ($dir). Cannot process file."
+ fi
+ done
+ fi
+}
+
show_help() {
local exit_code=${1:-0}
@@ -84,6 +106,7 @@ fi
files=""
for i; do
+ exit_if_dangerous "$i"
files="$(printf "$files\n$i")"
done
diff --git a/bin/rcup.in b/bin/rcup.in
index 910e534..78f5faa 100755
--- a/bin/rcup.in
+++ b/bin/rcup.in
@@ -121,10 +121,6 @@ replace_file() {
link_file "$src" "$dest" "$sigil"
}
-is_nested() {
- echo "$1" | sed "s:$DEST_DIR/::" | grep '/' >/dev/null
-}
-
is_identical() {
diff -c "$1" "$2" > /dev/null 2>&1
}
diff --git a/share/rcm.sh.in b/share/rcm.sh.in
index a2b4492..f7c6137 100644
--- a/share/rcm.sh.in
+++ b/share/rcm.sh.in
@@ -58,6 +58,10 @@ is_relative() {
echo "$1" | grep -v '^/' >/dev/null
}
+is_nested() {
+ echo "$1" | sed "s|$DEST_DIR/||" | grep '/' >/dev/null
+}
+
version() {
cat << EOV
$1 (rcm) $VERSION
diff --git a/test/mkrc-no-symlinks.t b/test/mkrc-no-symlinks.t
new file mode 100644
index 0000000..e37d56a
--- /dev/null
+++ b/test/mkrc-no-symlinks.t
@@ -0,0 +1,26 @@
+ $ . "$TESTDIR/helper.sh"
+
+Passing a linked file is rejected.
+We need a second path not under what will be $HOME
+
+ $ EXTDIR="${CRAMTMP}2"
+ > mkdir -p "$EXTDIR"
+ > echo 'Content' > "$EXTDIR/example"
+ > ln -s "$EXTDIR/example" "$HOME/.example"
+
+ $ mkrc .example
+ '.example' is a symlink. Cannot process file.
+ [1]
+
+ $ refute "is a symlink" -h $HOME/.dotfiles/.example
+
+Passing a file in one linked dir is rejected
+
+ $ mkdir "$HOME/.config"
+ > ln -s "$EXTDIR/" "$HOME/.config/tmpdir"
+
+ $ mkrc -v .config/tmpdir/example
+ '.config/tmpdir/example' path contains a symlink (tmpdir). Cannot process file.
+ [1]
+
+ $ refute "is a symlink" -h "$HOME/.dotfiles/config/tmpdir/example"