From: Laszlo Ersek <lersek@redhat.com>
To: Hao Wu <hao.a.wu@intel.com>, edk2-devel@lists.01.org
Cc: Feng Tian <feng.tian@intel.com>, guoheyi@huawei.com
Subject: Re: [PATCH] MdeModulePkg/ScsiDiskDxe: Fix potential implicit sign extension
Date: Mon, 10 Apr 2017 17:46:51 +0200 [thread overview]
Message-ID: <e8bfc036-e224-6bdf-ef4e-e30abd10a7a2@redhat.com> (raw)
In-Reply-To: <20170410074324.16340-1-hao.a.wu@intel.com>
(Gary, is your Linaro email still alive?)
On 04/10/17 09:43, Hao Wu wrote:
> In function GetMediaInfo(), the following expression:
> ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity10->LastLba3 << 24) |
> (Capacity10->LastLba2 << 16) |
> (Capacity10->LastLba1 << 8) |
> Capacity10->LastLba0;
> will involve implicit sign extension.
>
> Since Capacity10->LastLbaX is of type UINT8, and
> ScsiDiskDevice->BlkIo.Media->LastBlock is of type UINT64. Therefore,
> Capacity10->LastLbaX will be promoted to int (32 bits, signed) first,
> perform the bit shift and or. Then the result will be sign-extended to
> type UINT64.
>
> If bit 7 of Capacity10->LastLba3 is 1, then the high 32 bits of
> ScsiDiskDevice->BlkIo.Media->LastBlock will all be set to 1.
>
> This commit will add an explicit UINT32 type cast for
> Capacity10->LastLba3 to resolve this issue.
>
> Cc: Feng Tian <feng.tian@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Hao Wu <hao.a.wu@intel.com>
> ---
> MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> index b5eff25b9b..2289f20152 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> @@ -1,7 +1,7 @@
> /** @file
> SCSI disk driver that layers on every SCSI IO protocol in the system.
>
> -Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> This program and the accompanying materials
> are licensed and made available under the terms and conditions of the BSD License
> which accompanies this distribution. The full text of the license may be found at
> @@ -2754,7 +2754,7 @@ GetMediaInfo (
> UINT8 *Ptr;
>
> if (!ScsiDiskDevice->Cdb16Byte) {
> - ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity10->LastLba3 << 24) |
> + ScsiDiskDevice->BlkIo.Media->LastBlock = ((UINT32) Capacity10->LastLba3 << 24) |
> (Capacity10->LastLba2 << 16) |
> (Capacity10->LastLba1 << 8) |
> Capacity10->LastLba0;
>
The patch looks okay to me, but I would like to comment on the commit
message. The commit message says "sign extension", which is an assembly
language / processor level concept; the C language doesn't know about
"sign extension".
Instead, what we have here is undefined behavior.
6.5.7 Bitwise shift operators
3 The integer promotions are performed on each of the operands. The
type of the result is that of the promoted left operand. If the
value of the right operand is negative or is greater than or equal
to the width of the promoted left operand, the behavior is
undefined.
4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated
bits are filled with zeros. If E1 has an unsigned type, the value
of the result is E1 × 2^E2 , reduced modulo one more than the
maximum value representable in the result type. If E1 has a signed
type and nonnegative value, and E1 × 2^E2 is representable in the
result type, then that is the resulting value; otherwise, the
behavior is undefined.
So, we have a left operand here that is promoted to "int". It means that
"E1" has signed type. Its value is nonnegative. However, E1 × 2^E2 is
not representable in the result type, hence the behavior is undefined.
The fact that this undefined shift *happens* to result in the sign bit
being set (resulting in a negative "int" value), which in turn is
converted to a 64-bit unsigned value as proscribed by the usual
arithmetic conversions (*), is just an implementation detail. The root
cause is that the signed left shift invokes undefined behavior.
(
(*)
6.3.1.8 Usual arithmetic conversions
1 [...] Otherwise, if the operand that has unsigned integer type has
rank greater or equal to the rank of the type of the other operand,
then the operand with signed integer type is converted to the type
of the operand with unsigned integer type.
6.3.1.3 Signed and unsigned integers
2 Otherwise, if the new type is unsigned, the value is converted by
repeatedly adding or subtracting one more than the maximum value
that can be represented in the new type until the value is in the
range of the new type.
)
So I suggest to reformulate the subject line and the commit message to
say something like:
MdeModulePkg/ScsiDiskDxe: fix undefined behavior in signed left shift
Thanks
Laszlo
next prev parent reply other threads:[~2017-04-10 15:46 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-10 7:43 [PATCH] MdeModulePkg/ScsiDiskDxe: Fix potential implicit sign extension Hao Wu
2017-04-10 15:46 ` Laszlo Ersek [this message]
2017-04-11 1:07 ` Wu, Hao A
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e8bfc036-e224-6bdf-ef4e-e30abd10a7a2@redhat.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox