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: