From e1c1c328a21e4c077688b4a50dbdc622f84d587e Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Thu, 16 Sep 2021 22:15:00 +0200 Subject: [PATCH] Robustness: Check for broken symlinks to custom actions and complain Instead of potentially falling back to the built-in action that a custom action was intended to override, but (e.g. due to file system reorganizations) now results in a broken link. The extension functionality that is then skipped may result in undesired results, but this may not be immedately obvious to the user (if the extension is not particularly verbose), so some data corruption could occur if this remains undetected. To avoid duplicating (or somehow extracting) all the built-in actions, simply detect _any_ broken symlink; i.e. offer a superset of the required functionality. So this would also complain about a broken symlink to a non-executable custom (auxiliary) file (rarely used) if that is mistakenly passed as a custom action (unlikely). Fixes #359 --- tests/actions-test-lib.sh | 4 ++-- tests/t8000-actions.sh | 46 +++++++++++++++++++++++++++++++++++++++ todo.sh | 8 ++++++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/tests/actions-test-lib.sh b/tests/actions-test-lib.sh index 2530fb8..71cd4fd 100644 --- a/tests/actions-test-lib.sh +++ b/tests/actions-test-lib.sh @@ -20,7 +20,7 @@ make_action() { unset TODO_ACTIONS_DIR [ -d .todo.actions.d ] || mkdir .todo.actions.d - make_dummy_action ".todo.actions.d/$1" + [ -z "$1" ] || make_dummy_action ".todo.actions.d/$1" } make_action_in_folder() @@ -28,5 +28,5 @@ make_action_in_folder() unset TODO_ACTIONS_DIR [ -d .todo.actions.d ] || mkdir .todo.actions.d mkdir ".todo.actions.d/$1" - make_dummy_action ".todo.actions.d/$1/$1" "in folder $1" + [ -z "$1" ] || make_dummy_action ".todo.actions.d/$1/$1" "in folder $1" } diff --git a/tests/t8000-actions.sh b/tests/t8000-actions.sh index 763c4e9..2facc8f 100755 --- a/tests/t8000-actions.sh +++ b/tests/t8000-actions.sh @@ -44,4 +44,50 @@ custom action bad === 42 EOF +make_action +ln -s /actionsdir/doesnotexist/badlink .todo.actions.d/badlink +# On Cygwin, the Windows ACL may still grant execution rights. In this case, we +# skip the test. +if [ -x .todo.actions.d/badlink ]; then + SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8000.6 t8000.7" +fi +test_todo_session 'broken symlink' <>> todo.sh badlink | sed "s#'[^']*\(\\.todo\\.actions\\.d/[^']\{1,\}\)'#'\1'#g" +Fatal Error: Broken link to custom action: '.todo.actions.d/badlink' + +>>> todo.sh do >/dev/null +=== 1 +EOF + +make_action +mkdir .todo.actions.d/badfolderlink +ln -s /actionsdir/doesnotexist/badfolderlink .todo.actions.d/badfolderlink/badfolderlink +# On Cygwin, the Windows ACL may still grant execution rights. In this case, we +# skip the test. +if [ -x .todo.actions.d/badfolderlink/badfolderlink ]; then + SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8000.8 t8000.9" +fi +test_todo_session 'broken symlink in folder' <>> todo.sh badfolderlink | sed "s#'[^']*\(\\.todo\\.actions\\.d/[^']\{1,\}\)'#'\1'#g" +Fatal Error: Broken link to custom action: '.todo.actions.d/badfolderlink/badfolderlink' + +>>> todo.sh do >/dev/null +=== 1 +EOF + +make_action +ln -s /actionsdir/doesnotexist/do .todo.actions.d/do +# On Cygwin, the Windows ACL may still grant execution rights. In this case, we +# skip the test. +if [ -x .todo.actions.d/do ]; then + SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8000.10 t8000.11" +fi +test_todo_session 'broken symlink overrides built-in action' <>> todo.sh do | sed "s#'[^']*\(\\.todo\\.actions\\.d/[^']\{1,\}\)'#'\1'#g" +Fatal Error: Broken link to custom action: '.todo.actions.d/do' + +>>> todo.sh do >/dev/null +=== 1 +EOF + test_done diff --git a/todo.sh b/todo.sh index 37eca5e..f128e67 100755 --- a/todo.sh +++ b/todo.sh @@ -1038,7 +1038,13 @@ listWordsWithSigil() hasCustomAction() { - [ -d "${1:?}" ] && [ -x "${1:?}/${2:?}" ] + [ -d "${1:?}" ] || return 1 + [ -x "$1/${2:?}" ] && return 0 + if [ -h "$1/$2" ] && [ ! -e "$1/$2" ] + then + dieWithHelp "$2" "Fatal Error: Broken link to custom action: '$1/$2'" + fi + return 1 } export -f cleaninput getPrefix getTodo getNewtodo shellquote filtercommand _list listWordsWithSigil getPadding _format die