Author: dteske
Date: Sat Oct 12 19:52:27 2013
New Revision: 256391
URL: http://svnweb.freebsd.org/changeset/base/256391

Log:
  Fix signed integer overflow detection in f_expand_number() of strings.subr.
  
  Approved by:  re (glebius)

Modified:
  head/usr.sbin/bsdconfig/share/strings.subr

Modified: head/usr.sbin/bsdconfig/share/strings.subr
==============================================================================
--- head/usr.sbin/bsdconfig/share/strings.subr  Sat Oct 12 19:41:35 2013        
(r256390)
+++ head/usr.sbin/bsdconfig/share/strings.subr  Sat Oct 12 19:52:27 2013        
(r256391)
@@ -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
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to