From a7889e442fd5ec4d7c512591ef4d590f04bab79b Mon Sep 17 00:00:00 2001 From: Greg Look Date: Thu, 24 Sep 2020 14:59:01 -0700 Subject: [PATCH] Ensure resume suggestions are shell-escaped. --- src/lein_monolith/task/each.clj | 12 +++++++----- src/lein_monolith/task/util.clj | 13 +++++++++++++ test/lein_monolith/task/util_test.clj | 10 ++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/lein_monolith/task/each.clj b/src/lein_monolith/task/each.clj index fbd8626..516abdd 100644 --- a/src/lein_monolith/task/each.clj +++ b/src/lein_monolith/task/each.clj @@ -306,11 +306,13 @@ (assoc @results :success true) (catch Exception ex (when-not (or (:parallel opts) (:endure opts)) - (let [resume-args (concat - ["lein monolith each"] - (opts->args (dissoc opts :start)) - [:start target] - (:task ctx))] + (let [resume-args (into + ["lein" "monolith" "each"] + (map u/shell-escape) + (concat + (opts->args (dissoc opts :start)) + [:start target] + (:task ctx)))] (lein/warn (format "\n%s %s\n" (colorize [:bold :red] "Resume with:") (str/join " " resume-args))))) diff --git a/src/lein_monolith/task/util.clj b/src/lein_monolith/task/util.clj index b866227..95abe53 100644 --- a/src/lein_monolith/task/util.clj +++ b/src/lein_monolith/task/util.clj @@ -6,6 +6,19 @@ [leiningen.core.main :as lein])) +(defn shell-escape + "Escape the provided argument for use in a shell." + [arg] + (let [s (if (string? arg) + arg + (pr-str arg))] + (if (or (str/includes? s " ") + (str/includes? s "'") + (str/includes? s "\"")) + (str \' (str/escape s {\' "\\'"}) \') + s))) + + (defn parse-kw-args "Given a sequence of string arguments, parse out expected keywords. Returns a vector with a map of keywords to values (or `true` for flags) followed by diff --git a/test/lein_monolith/task/util_test.clj b/test/lein_monolith/task/util_test.clj index 942cc24..771acea 100644 --- a/test/lein_monolith/task/util_test.clj +++ b/test/lein_monolith/task/util_test.clj @@ -4,6 +4,16 @@ [lein-monolith.task.util :as u])) +(deftest shell-escaping + (is (= "nil" (u/shell-escape nil))) + (is (= "123" (u/shell-escape 123))) + (is (= "foo" (u/shell-escape "foo"))) + (is (= ":abc" (u/shell-escape :abc))) + (is (= "'[123 true]'" (u/shell-escape [123 true]))) + (is (= "'\\'foo'" (u/shell-escape "'foo"))) + (is (= "'\"xyz\"'" (u/shell-escape "\"xyz\"")))) + + (deftest kw-arg-parsing (testing "empty arguments" (is (= [{} []]