git: 701d7be6e4a9 - main - Add test cases for safe_eval.sh

From: Simon J. Gerraty <sjg_at_FreeBSD.org>
Date: Mon, 18 May 2026 17:52:34 UTC
The branch main has been updated by sjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=701d7be6e4a9a145700fdee5c038470b355a0e05

commit 701d7be6e4a9a145700fdee5c038470b355a0e05
Author:     Simon J. Gerraty <sjg@FreeBSD.org>
AuthorDate: 2026-05-18 17:51:18 +0000
Commit:     Simon J. Gerraty <sjg@FreeBSD.org>
CommitDate: 2026-05-18 17:51:18 +0000

    Add test cases for safe_eval.sh
    
    safe_set is the routine that does all the work.
    
    In safe_set; if we replace one=`cmd arg` or two=$(cmd arg) add quotes
    around the result eg. one="_cmd arg_"
    Also lines containing `` or $() are too likely to result in syntax
    errors, so just delete them.
    
    Differential Revision:  https://reviews.freebsd.org/D56795
---
 libexec/rc/safe_eval.sh            |  7 +++-
 libexec/rc/tests/Makefile          |  8 ++++-
 libexec/rc/tests/safe_eval_test.sh | 65 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/libexec/rc/safe_eval.sh b/libexec/rc/safe_eval.sh
index 3b3241ae821d..eb1698472624 100644
--- a/libexec/rc/safe_eval.sh
+++ b/libexec/rc/safe_eval.sh
@@ -28,11 +28,16 @@ fi
 # return a safe variable setting
 # any non-alphanumeric chars other than those in "xtras"
 # will be replaced with '_'
+# Lines containing `` or $() are too likely to result in syntax errors
+# so just delete them.
 #
 # "xtras" should be used with caution and cannot include ';'
 # 
 safe_set() {
-    ${SED:-sed} 's/^[ 	]*//;s/[ 	]*#.*//;s/^:.*//;/^[A-Za-z_][A-Za-z0-9_]*=/!d;s;[^A-Za-z0-9_. 	"'"$1"'$,/=:+-];_;g'
+    ${SED:-sed} -e 's/^[ 	]*//;s/[ 	]*#.*//;s/^:.*//' \
+    -e '/`/d' -e '/\$(/d' \
+    -e '/^[A-Za-z_][A-Za-z0-9_]*=/!d;s;[^A-Za-z0-9_. 	"'"$1"'$,/=:+-];_;g;' \
+    -e '/=.*_.*[ 	]/s,=\(.*\),="\1",;s,"",",g'
 }
 
 ##
diff --git a/libexec/rc/tests/Makefile b/libexec/rc/tests/Makefile
index c44c6db90b77..3a6eafea292d 100644
--- a/libexec/rc/tests/Makefile
+++ b/libexec/rc/tests/Makefile
@@ -1,3 +1,9 @@
-ATF_TESTS_SH+=  rc_subr_test
+ATF_TESTS_SH+=  rc_subr_test safe_eval_test
+
+# allow running this as part of the build - in DIRDEPS_BUILD at least
+.if ${.MAKE.LEVEL} > 0 && ${MACHINE:Nhost*} == ""
+SAFE_EVAL:= ${_PARSEDIR:U${.PARSEDIR:tA}:H}/safe_eval.sh
+.export SAFE_EVAL
+.endif
 
 .include <bsd.test.mk>
diff --git a/libexec/rc/tests/safe_eval_test.sh b/libexec/rc/tests/safe_eval_test.sh
new file mode 100644
index 000000000000..a0f3a2784098
--- /dev/null
+++ b/libexec/rc/tests/safe_eval_test.sh
@@ -0,0 +1,65 @@
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright 2026 Simon J Gerraty
+#
+
+atf_test_case safe_set_reject
+safe_set_reject_head()
+{
+	atf_set "descr" "Verify that safe_set rejects shell meta chars"
+}
+
+safe_set_reject_body()
+{
+	__name="$(atf_get ident)"
+	__input=$(mktemp -t "${__name}.input")
+
+	cat <<'EOF' > "$__input"
+: ignore=this
+# ignore this too
+# avoid # in the middle of a quoted value like:
+# oops="this # will cause synatx error"
+quoted="this and that"
+simple=ok          # trailing comments ignored
+  also=ok          # leading white-space ignored
+	 also_wik=ok
+host=`hostname`'   # backtics - delete line
+os=$(uname -s)     # $() - delete line
+oops=one;hostname' # replace ; with _ so: one_hostname
+regex="prefix[abc-]*" # []* replaced with _
+EOF
+
+	__output=$(safe_set < "$__input" | tr '"\012' '\047;')
+	atf_check_equal "$__output" "quoted='this and that';simple=ok;also=ok;also_wik=ok;oops=one_hostname_;regex='prefix_abc-__';"
+}
+
+
+atf_test_case safe_set_xtras
+safe_set_xtras_head()
+{
+	atf_set "descr" "Verify that safe_set handles extra allowed chars"
+}
+
+safe_set_xtras_body()
+{
+	__name="$(atf_get ident)"
+	__input=$(mktemp -t "${__name}.input")
+
+	cat <<'EOF' > "$__input"
+: ignore=this
+# ignore this too
+regex="prefix[abc-]*"
+EOF
+
+	__output=$(safe_set "[]*" < "$__input" | tr '"\012' '\047;')
+	atf_check_equal "$__output" "regex='prefix[abc-]*';"
+}
+
+atf_init_test_cases()
+{
+	SAFE_EVAL=${SAFE_EVAL:-/libexec/safe_eval.sh}
+	. $SAFE_EVAL
+	atf_add_test_case safe_set_reject
+	atf_add_test_case safe_set_xtras
+}