Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 12 Oct 2013 19:52:27 +0000 (UTC)
From:      Devin Teske <dteske@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r256391 - head/usr.sbin/bsdconfig/share
Message-ID:  <201310121952.r9CJqRee025169@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310121952.r9CJqRee025169>