summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authordteske <dteske@FreeBSD.org>2013-10-12 19:54:12 +0000
committerdteske <dteske@FreeBSD.org>2013-10-12 19:54:12 +0000
commitd58485abbdccf27ecf761ed841b039cfc481aec7 (patch)
treeee52958145b9f64dc6392a6c8e0a9e3941e8829c /usr.sbin
parentc1abbfde2d2ed6e8b37eddbb9bf305f79d3ce103 (diff)
downloadFreeBSD-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.subr58
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
OpenPOWER on IntegriCloud