[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#820156: parse_numeric function cannot handle composite device numbers of more than 8 hex digits



Package: initramfs-tools-core
Version: 0.123
Severity: minor
Tags: patch

Congratulations on initramfs-tools version 0.123!  Many bugs in version 0.120
have been fixed in this version.  However, it appears that the parse_numeric
function, while improved over the 0.120 version, still doesn't handle the
general case of a composite device number.  It seems it will only handle 8 hex
digits or less correctly.

I have submitted a patch for your consideration.  The patch will accommodate the
general case of a composite device number of up to 16 hex digits (the limit).
It also tightens up some other error checking corner cases.

Respectfully submitted,

-- 
  .''`.     Stephen Powell    <zlinuxman@fastmail.com>
 : :'  :
 `. `'`
   `-
--- a/functions	2016-01-21 18:33:59.000000000 -0500
+++ b/functions	2016-03-24 08:09:11.000000000 -0400
@@ -128,14 +128,28 @@
 
 # lilo compatibility
 parse_numeric() {
-	case $1 in
+	case "$1" in
 	*:*)
 		# Does it match /[0-9]*:[0-9]*/?
-		minor=${1#*:}
-		major=${1%:*}
-		case $major$minor in
+		minor="${1#*:}"   # Everything after the first colon.
+		major="${1%%:*}"  # Everything before the first colon.
+		[ X"$major" = X ] && return   # major is null.
+		[ X"$minor" = X ] && return   # minor is null.
+		case "$major$minor" in
 		*[!0-9]*)
-			# No.
+			# major or minor contains a non-numeric character.
+			return
+			;;
+		esac
+		case "$major" in
+		0?*)
+			# major has a leading zero.
+			return
+			;;
+		esac
+		case "$minor" in
+		0?*)
+			# minor has a leading zero.
 			return
 			;;
 		esac
@@ -146,9 +160,56 @@
 		;;
 	*)
 		# [A-Fa-f0-9]*
-		value=$(( 0x${1} ))
-		minor=$(( (${value} & 0xff) | (${value} >> 12) & 0xfff00 ))
-		major=$(( (${value} >> 8) & 0xfff ))
+		case "$1" in
+		0?*)
+			# Composite device number has a leading zero.
+			return
+			;;
+		esac
+		[ ${#1} -gt 16 ] && return   # More than 16 hex digits.
+		#
+		# 16 hex digits, with leading zeros suppressed.
+		# Format is MMMMMmmmmmmMMMmm, where the "M"s are the hex
+		# digits of the major device number and the "m"s are the
+		# hex digits of the minor device number.
+		#
+		# Note: the shell uses 64-bit two's complement signed binary
+		# integer arithmetic internally when evaluating arithmetic
+		# expressions, even on 32-bit platforms such as i386.  Bitwise
+		# shift operations are arithmetic shifts, not logical shifts.
+		# Only the right-most 63 bits participate in a shift operation.
+		# The left-most bit, the sign bit, does not participate in
+		# the shift operation and remains unchanged.  For a shift
+		# left operation, bits shifted out of the left-most bit
+		# position which participates in the shift are lost; and zeros
+		# are shifted in on the right.  Arithmetic overflow occurs
+		# if any bits unlike the sign bit are shifted out of the
+		# left-most bit position which participates in the shift.
+		# (However, arithmetic overflow is ignored.)  For a shift
+		# right operation, bits shifted out of the right-most bit
+		# position are lost; and copies of the sign bit are shifted
+		# in on the left.  All 64 bit positions, including the sign
+		# bit, participate in bitwise "and" and bitwise "or"
+		# operations.
+		#
+		# Hexadecimal constants are treated as padded on the left
+		# with zeros, if needed, or truncated on the left, if needed,
+		# to make 16 digits.  If the left-most digit, after padding
+		# or truncating if needed, is in the range 8-f, inclusive,
+		# then the number is treated as negative, in two's complement
+		# form.  Otherwise, the number is treated as positive (or zero
+		# if all digits are zero).
+		#
+		# For the three operators used in the expressions below,
+		# the bitwise shift right operator (>>) has the highest
+		# priority, followed by the bitwise "and" operator (&),
+		# followed by the bitwise "or" operator (|).  Therefore, the
+		# default order of operations is correct; and no parentheses
+		# are needed in the expressions themselves.
+		#
+		devno=$(( 0x$1 ))
+		major=$(( devno >> 8 & 0xfff | devno >> 32 & 0xfffff000 ))
+		minor=$(( devno & 0xff | devno >> 12 & 0xffffff00 ))
 		;;
 	esac
 

Reply to: