git: 0fa0966b6a5a - main - safe_eval.sh add safe_var_set

From: Simon J. Gerraty <sjg_at_FreeBSD.org>
Date: Sun, 11 Oct 2026 04:58:58 UTC
The branch main has been updated by sjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=0fa0966b6a5a6000e4b98104e17629161f6f1f04

commit 0fa0966b6a5a6000e4b98104e17629161f6f1f04
Author:     Simon J. Gerraty <sjg@FreeBSD.org>
AuthorDate: 2026-10-11 04:58:50 +0000
Commit:     Simon J. Gerraty <sjg@FreeBSD.org>
CommitDate: 2026-10-11 04:58:50 +0000

    safe_eval.sh add safe_var_set
    
    safe_var_set can be used to safely handle var=val args from command line.
    eg.
    
            while :
            do
                    case "$1" in
                    *=*)    # eval "$1" can be very dangerous
                            # safe_var_set will only eval if
                            # both var and value are sane.
                            if ! safe_var_set "$1"; then
                                    case "$?" in
                                    1) echo invalid variable name;;
                                    2) echo invalide value;;
                                    3) echo variabel not allowed;;
                                    esac
                            fi
                            shift
                            ;;
                    *)      break
                            ;;
                    esac
            done
---
 libexec/rc/safe_eval.sh | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/libexec/rc/safe_eval.sh b/libexec/rc/safe_eval.sh
index eb1698472624..b5ad1ca8639d 100644
--- a/libexec/rc/safe_eval.sh
+++ b/libexec/rc/safe_eval.sh
@@ -1,6 +1,6 @@
 :
 # RCSid:
-#	$Id: safe_eval.sh,v 1.28 2026/04/22 16:36:32 sjg Exp $
+#	$Id: safe_eval.sh,v 1.30 2026/10/11 04:48:37 sjg Exp $
 #
 #	@(#) Copyright (c) 2023-2026 Simon J. Gerraty
 #
@@ -22,6 +22,54 @@ else
     _local=:
 fi
 
+##
+# safe_set_var "var=val" ["allowed_vars" ["only_chars" ["extra_chars"]]]
+#
+# Useful for processing command line input like 'var=val'
+# We perform a number of sanity checks similar to safe_set.
+# We set ssv_var=var and ssv_val=val so that caller can produce
+# error messages if desired.  ssv_var or ssv_val will be set to
+# 'invalid' if they fail the relevant checks.
+# 1. if "var" contains anything but 'A-Za-z0-9_' or matches 'ssv_*'
+#    we set ssv_var=invalid and return 1
+# 3. if "val" contains anything not in the combined set of
+#    "only_chars" and "extra_chars" we will set ssv_val=invalid
+#    and return 3
+# 2. if "allowed_vars" and "var" is not a member we return 2
+# If "only_chars" is not provided we use 'A-Za-z0-9_  ,/=:+-'
+# similar to save_set.
+# If we pass all that, we eval "var=val" and return 0
+#
+safe_set_var() {
+    eval $_local ssv_rc
+    ssv_rc=
+    if ${isPOSIX_SHELL:-false}; then
+        ssv_var="${1%%=*}"
+        ssv_val="${1#*=}"
+    else
+        ssv_var=`expr "$1" : '\([^=]*\)=.*'`
+        ssv_val=`expr "$1" : '[^=]*=\(.*\)'`
+    fi
+    : first is ssv_var sane?
+    case "$ssv_var" in
+    *[!A-Za-z0-9_]*|ssv_*) ssv_var=invalid; ssv_rc=1;;
+    esac
+    case "$ssv_val" in
+    *[!${3:-A-Za-z0-9_  ,/=:+-}$4]*) ssv_val=invalid; ssv_rc=${ssv_rc:-2};;
+    esac
+    : is $ssv_var is allowed
+    case " ${2:-$ssv_var} " in
+    *" $ssv_var "*) ;;
+    *) ssv_rc=${ssv_rc:-3};;
+    esac
+    ssv_rc=${ssv_rc:-0}
+    if [ $ssv_rc = 0 ]; then
+        : this should be safe
+        eval "$ssv_var=\"$ssv_val\""
+    fi
+    return $ssv_rc
+}
+
 ##
 # safe_set [xtras]
 #