Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

MFC r256391:

Fix signed integer overflow detection in f_expand_number() of strings.subr.

Approved by:	re (glebius)
  • Loading branch information...
commit d58485abbdccf27ecf761ed841b039cfc481aec7 1 parent c1abbfd
@devinteske devinteske authored
Showing with 34 additions and 24 deletions.
  1. +34 −24 usr.sbin/bsdconfig/share/strings.subr
View
58 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
Please sign in to comment.
Something went wrong with that request. Please try again.