From 1e69fd5e21b619ec154def106ae49db814357746 Mon Sep 17 00:00:00 2001 From: Manuel Streuhofer Date: Mon, 5 Dec 2016 22:52:22 +0100 Subject: [PATCH] removed all usage of eval, proper usage of unset replaced all `eval` with `printf -v` for security reasons. the behaviour of unset without -v/-f is actually undefined so make the intent clear. --- main.sh | 45 +++++++++++++----------- test/fixture/main-usage-defaults.stdio | 4 +-- test/scenario/main-usage-defaults/run.sh | 6 ++-- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/main.sh b/main.sh index 7193bc6..6c815b2 100755 --- a/main.sh +++ b/main.sh @@ -32,8 +32,8 @@ if [ "${BASH_SOURCE[0]}" != "${0}" ]; then __b3bp_tmp_source_idx=1 fi else - [ ! -z "${__usage+x}" ] && unset __usage - [ ! -z "${__helptext+x}" ] && unset __helptext + [ ! -z "${__usage+x}" ] && unset -v __usage + [ ! -z "${__helptext+x}" ] && unset -v __helptext fi # Set magic variables for current file, directory, os, etc. @@ -159,21 +159,17 @@ while read -r __b3bp_tmp_line; do __b3bp_tmp_long_opt="${__b3bp_tmp_long_opt%% *}" fi - __b3bp_tmp_long_opt_mangled="${__b3bp_tmp_long_opt//-/_}" - # map long name back to short name - __b3bp_tmp_varname="__b3bp_tmp_short_opt_${__b3bp_tmp_long_opt_mangled}" - eval "${__b3bp_tmp_varname}=\"${__b3bp_tmp_opt}\"" + printf -v "__b3bp_tmp_short_opt_${__b3bp_tmp_long_opt//-/_}" '%s' "${__b3bp_tmp_opt}" # check if option takes an argument - __b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt}" if [[ ! "${__b3bp_tmp_line}" =~ \[.*\] ]]; then __b3bp_tmp_init="0" # it's a flag. init with 0 - eval "${__b3bp_tmp_varname}=0" + printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "0" else __b3bp_tmp_opt="${__b3bp_tmp_opt}:" # add : if opt has arg __b3bp_tmp_init="" # it has an arg. init with "" - eval "${__b3bp_tmp_varname}=1" + printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "1" fi __b3bp_tmp_opts="${__b3bp_tmp_opts:-}${__b3bp_tmp_opt}" fi @@ -186,11 +182,19 @@ while read -r __b3bp_tmp_line; do if [ "${!__b3bp_tmp_varname}" = "1" ]; then __b3bp_tmp_init="${__b3bp_tmp_line##*Default=}" + __b3bp_tmp_re='^"(.*)"$' + if [[ "${__b3bp_tmp_init}" =~ ${__b3bp_tmp_re} ]]; then + __b3bp_tmp_init="${BASH_REMATCH[1]}" + else + __b3bp_tmp_re="^'(.*)'$" + if [[ "${__b3bp_tmp_init}" =~ ${__b3bp_tmp_re} ]]; then + __b3bp_tmp_init="${BASH_REMATCH[1]}" + fi + fi fi fi - __b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}" - eval "${__b3bp_tmp_varname}=\"${__b3bp_tmp_init}\"" + printf -v "arg_${__b3bp_tmp_opt:0:1}" '%s' "${__b3bp_tmp_init}" done <<< "${__usage:-}" # run getopts only if options were specified in __usage @@ -213,17 +217,18 @@ if [ -n "${__b3bp_tmp_opts:-}" ]; then if [[ "${OPTARG}" =~ .*=.* ]]; then # --key=value format __b3bp_tmp_long_opt=${OPTARG/=*/} - __b3bp_tmp_long_opt_mangled="${__b3bp_tmp_long_opt//-/_}" # Set opt to the short option corresponding to the long option - eval "__b3bp_tmp_opt=\"\${__b3bp_tmp_short_opt_${__b3bp_tmp_long_opt_mangled}}\"" + __b3bp_tmp_varname="__b3bp_tmp_short_opt_${__b3bp_tmp_long_opt//-/_}" + printf -v "__b3bp_tmp_opt" '%s' "${!__b3bp_tmp_varname}" OPTARG=${OPTARG#*=} else # --key value format # Map long name to short version of option - __b3bp_tmp_long_opt_mangled="${OPTARG//-/_}" - eval "__b3bp_tmp_opt=\"\${__b3bp_tmp_short_opt_${__b3bp_tmp_long_opt_mangled}}\"" + __b3bp_tmp_varname="__b3bp_tmp_short_opt_${OPTARG//-/_}" + printf -v "__b3bp_tmp_opt" '%s' "${!__b3bp_tmp_varname}" # Only assign OPTARG if option takes an argument - eval "OPTARG=\"\${@:OPTIND:\${__b3bp_tmp_has_arg_${__b3bp_tmp_opt}}}\"" + __b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt}" + printf -v "OPTARG" '%s' "${@:OPTIND:${!__b3bp_tmp_varname}}" # shift over the argument if argument is expected ((OPTIND+=__b3bp_tmp_has_arg_${__b3bp_tmp_opt})) fi @@ -237,7 +242,7 @@ if [ -n "${__b3bp_tmp_opts:-}" ]; then __b3bp_tmp_value="1" fi - eval "${__b3bp_tmp_varname}=\"${__b3bp_tmp_value}\"" + printf -v "${__b3bp_tmp_varname}" '%s' "${__b3bp_tmp_value}" debug "cli arg ${__b3bp_tmp_varname} = ($__b3bp_tmp_default) -> ${!__b3bp_tmp_varname}" done set -o nounset # no more unbound variable references expected @@ -252,17 +257,17 @@ fi ############################################################################## for __tmp_varname in ${!__b3bp_tmp_*}; do - eval "unset ${__tmp_varname}" + unset -v "${__tmp_varname}" done -unset __tmp_varname +unset -v __tmp_varname ### Externally supplied __usage. Nothing else to do here ############################################################################## if [ "${__b3bp_external_usage:-}" = "true" ]; then - unset __b3bp_external_usage + unset -v __b3bp_external_usage return fi diff --git a/test/fixture/main-usage-defaults.stdio b/test/fixture/main-usage-defaults.stdio index 380792a..2b93b13 100644 --- a/test/fixture/main-usage-defaults.stdio +++ b/test/fixture/main-usage-defaults.stdio @@ -1,7 +1,7 @@ ACCPTST:STDIO_REPLACE_DATETIMES {datetime} UTC [ info] arg_1: 0 {datetime} UTC [ info] arg_2: 0 -{datetime} UTC [ info] arg_3: THREE -{datetime} UTC [ info] arg_4: FOUR +{datetime} UTC [ info] arg_3: 'THREE' +{datetime} UTC [ info] arg_4: "FOUR" {datetime} UTC [ info] arg_5: OOOPS {datetime} UTC [ info] arg_6: diff --git a/test/scenario/main-usage-defaults/run.sh b/test/scenario/main-usage-defaults/run.sh index 0b37c8c..cd8d1f8 100755 --- a/test/scenario/main-usage-defaults/run.sh +++ b/test/scenario/main-usage-defaults/run.sh @@ -16,12 +16,12 @@ read -r -d '' __usage <<-'EOF' || true # exits non-zero when EOF encountered More description. -2 --two Do two things. More description. Default="TWO" - -3 --three [arg] Do three things. Default="THREE" + -3 --three [arg] Do three things. Default="'THREE'" More description. -4 --four [arg] Do four things. - More description. Default="FOUR" + More description. Default='"FOUR"' -5 --five [arg] Do five things. Default="FIVE" - More description. Default="OOOPS" + More description. Default='OOOPS' -6 --six [arg] Do six things. More description. EOF