diff options
author | dteske <dteske@FreeBSD.org> | 2013-10-12 19:54:12 +0000 |
---|---|---|
committer | dteske <dteske@FreeBSD.org> | 2013-10-12 19:54:12 +0000 |
commit | d58485abbdccf27ecf761ed841b039cfc481aec7 (patch) | |
tree | ee52958145b9f64dc6392a6c8e0a9e3941e8829c /usr.sbin | |
parent | c1abbfde2d2ed6e8b37eddbb9bf305f79d3ce103 (diff) | |
download | FreeBSD-src-d58485abbdccf27ecf761ed841b039cfc481aec7.zip FreeBSD-src-d58485abbdccf27ecf761ed841b039cfc481aec7.tar.gz |
MFC r256391:
Fix signed integer overflow detection in f_expand_number() of strings.subr.
Approved by: re (glebius)
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bsdconfig/share/strings.subr | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index 4621fda..f78948b 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -341,17 +341,19 @@ f_shell_unescape() # # NOTE: Prefixes are case-insensitive. # -# Upon successful completion, the value 0 is returned (or stored to -# $var_to_set); otherwise -1. Reasons for a -1 return include: +# Upon successful completion, success status is returned; otherwise the number +# -1 is produced ($var_to_set set to -1 or if $var_to_set is NULL or missing) +# on standard output. In the case of failure, the error status will be one of: # -# Given $string contains no digits. -# An unrecognized prefix was given. -# Result too large to calculate. +# Status Reason +# 1 Given $string contains no digits +# 2 An unrecognized prefix was given +# 3 Result too large to calculate # f_expand_number() { local __string="$1" __var_to_set="$2" - local __cp __num + local __cp __num __bshift __maxinput # Remove any leading non-digits while :; do @@ -360,14 +362,14 @@ f_expand_number() [ "$__string" = "$__cp" ] && break done - # Return `-1' if string didn't contain any digits + # Produce `-1' if string didn't contain any digits if [ ! "$__string" ]; then if [ "$__var_to_set" ]; then setvar "$__var_to_set" -1 else echo -1 fi - return $FAILURE + return 1 # 1 = "Given $string contains no digits" fi # Store the numbers @@ -390,9 +392,23 @@ f_expand_number() [ "$__string" = "$__cp" ] && break done - # Test for invalid prefix + # + # Test for invalid prefix (and determine bitshift length) + # case "$__string" in - ""|[KkMmGgTtPpEe]*) : known prefix ;; + ""|[[:space:]]*) # Shortcut + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" $__num + else + echo $__num + fi + return $SUCCESS ;; + [Kk]*) __bshift=10 ;; + [Mm]*) __bshift=20 ;; + [Gg]*) __bshift=30 ;; + [Tt]*) __bshift=40 ;; + [Pp]*) __bshift=50 ;; + [Ee]*) __bshift=60 ;; *) # Unknown prefix if [ "$__var_to_set" ]; then @@ -400,29 +416,23 @@ f_expand_number() else echo -1 fi - return $FAILURE + return 2 # 2 = "An unrecognized prefix was given" esac - # Multiply the number out - case "$__string" in - [Kk]) __num=$(( $__num * 1024 )) ;; - [Mm]) __num=$(( $__num * 1048576 )) ;; - [Gg]) __num=$(( $__num * 1073741824 )) ;; - [Tt]) __num=$(( $__num * 1099511627776 )) ;; - [Pp]) __num=$(( $__num * 1125899906842624 )) ;; - [Ee]) __num=$(( $__num * 1152921504606846976 )) ;; - esac - if [ $__num -le 0 ]; then - # Arithmetic overflow + # Determine if the wheels fall off + __maxinput=$(( 0x7fffffffffffffff >> $__bshift )) + if [ $__num -gt $__maxinput ]; then + # Input (before expanding) would exceed 64-bit signed int if [ "$__var_to_set" ]; then setvar "$__var_to_set" -1 else echo -1 fi - return $FAILURE + return 3 # 3 = "Result too large to calculate" fi - # Return the number + # Shift the number out and produce it + __num=$(( $__num << $__bshift )) if [ "$__var_to_set" ]; then setvar "$__var_to_set" $__num else |