From: Bret Barkelew <Bret.Barkelew@microsoft.com>
To: "Kinney, Michael D" <michael.d.kinney@intel.com>,
Laszlo Ersek <lersek@redhat.com>,
Sean Brogan <sean.brogan@microsoft.com>
Cc: "edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
"Gao, Liming" <liming.gao@intel.com>
Subject: Re: [Patch] MdePkg/BaseSafeIntLib: Add SafeIntLib class and instance
Date: Tue, 13 Feb 2018 16:56:07 +0000 [thread overview]
Message-ID: <DM5PR2101MB093655672D809EC195855A4BEFF60@DM5PR2101MB0936.namprd21.prod.outlook.com> (raw)
In-Reply-To: <E92EE9817A31E24EB0585FDF735412F5B89665C5@ORSMSX113.amr.corp.intel.com>
In response to the original question, I would content that our goal should be "a". We should be allowing universal detection of errors without the caller having to carry this detection code itself.
The analog would be the safe string functions: if a buffer overflow occurs, they don't find a way to "fix" the operation, but they faithfully report an error.
As such, I believe from my review that these functions work as intended.
- Bret
________________________________
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Tuesday, February 13, 2018 8:17:48 AM
To: Laszlo Ersek; Sean Brogan; Bret Barkelew
Cc: edk2-devel@lists.01.org; Gao, Liming
Subject: RE: [edk2] [Patch] MdePkg/BaseSafeIntLib: Add SafeIntLib class and instance
+Bret
Mike
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org]
> On Behalf Of Laszlo Ersek
> Sent: Tuesday, February 13, 2018 4:24 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; Sean
> Brogan <sean.brogan@microsoft.com>
> Cc: edk2-devel@lists.01.org; Gao, Liming
> <liming.gao@intel.com>
> Subject: Re: [edk2] [Patch] MdePkg/BaseSafeIntLib: Add
> SafeIntLib class and instance
>
> Sean, Michael,
>
> can you please follow up on this?
>
> To clarify, I think this is a serious bug in SafeIntLib,
> dependent on
> what we want to use this library for. As far as I
> understand, SafeIntLib
> intends to centralize integer manipulation / arithmetic,
> so that client
> code need not concern itself with overflow checking and
> such (on the C
> expression level -- it still has to check return
> statuses, of course).
> In other words, undefined behavior related to integer
> arithmetic is
> supposed to be prevented in various modules by moving all
> such
> operations into SafeIntLib, and letting client code use
> SafeIntLib APIs.
>
> However, for this to work, SafeIntLib itself must be 100%
> free of
> undefined behavior. And that's not the case (unless we
> define additional
> guarantees -- on top of ISO C -- for edk2 target
> architectures). Should
> I file a TianoCore BZ? Or is someone already (re)auditing
> the library?
> Or else, is my concern unjustified? Please comment.
>
> Thanks,
> Laszlo
>
> On 02/08/18 01:45, Laszlo Ersek wrote:
> > On 02/08/18 01:32, Laszlo Ersek wrote:
> >> On 12/19/17 20:36, Kinney, Michael D wrote:
> >>> From: Sean Brogan <sean.brogan@microsoft.com>
> >>>
> >>> SafeIntLib provides helper functions to prevent
> integer overflow
> >>> during type conversion, addition, subtraction, and
> multiplication.
> >>
> >> I clearly cannot review such a huge patch, but I've
> noticed something
> >> and would like to ask for clarification:
> >>
> >>> +/**
> >>> + INT64 Subtraction
> >>> +
> >>> + Performs the requested operation using the input
> parameters into a value
> >>> + specified by Result type and stores the converted
> value into the caller
> >>> + allocated output buffer specified by Result. The
> caller must pass in a
> >>> + Result buffer that is at least as large as the
> Result type.
> >>> +
> >>> + If Result is NULL, RETURN_INVALID_PARAMETER is
> returned.
> >>> +
> >>> + If the requested operation results in an overflow
> or an underflow condition,
> >>> + then Result is set to INT64_ERROR and
> RETURN_BUFFER_TOO_SMALL is returned.
> >>> +
> >>> + @param[in] Minuend A number from which
> another is to be subtracted.
> >>> + @param[in] Subtrahend A number to be subtracted
> from another
> >>> + @param[out] Result Pointer to the result of
> subtraction
> >>> +
> >>> + @retval RETURN_SUCCESS Successful
> subtraction
> >>> + @retval RETURN_BUFFER_TOO_SMALL Underflow
> >>> + @retval RETURN_INVALID_PARAMETER Result is NULL
> >>> +**/
> >>> +RETURN_STATUS
> >>> +EFIAPI
> >>> +SafeInt64Sub (
> >>> + IN INT64 Minuend,
> >>> + IN INT64 Subtrahend,
> >>> + OUT INT64 *Result
> >>> + )
> >>> +{
> >>> + RETURN_STATUS Status;
> >>> + INT64 SignedResult;
> >>> +
> >>> + if (Result == NULL) {
> >>> + return RETURN_INVALID_PARAMETER;
> >>> + }
> >>> +
> >>> + SignedResult = Minuend - Subtrahend;
> >>> +
> >>> + //
> >>> + // Subtracting a positive number from a positive
> number never overflows.
> >>> + // Subtracting a negative number from a negative
> number never overflows.
> >>> + // If you subtract a negative number from a
> positive number, you expect a positive result.
> >>> + // If you subtract a positive number from a
> negative number, you expect a negative result.
> >>> + // Overflow if inputs vary in sign and the output
> does not have the same sign as the first input.
> >>> + //
> >>> + if (((Minuend < 0) != (Subtrahend < 0)) &&
> >>> + ((Minuend < 0) != (SignedResult < 0))) {
> >>> + *Result = INT64_ERROR;
> >>> + Status = RETURN_BUFFER_TOO_SMALL;
> >>> + } else {
> >>> + *Result = SignedResult;
> >>> + Status = RETURN_SUCCESS;
> >>> + }
> >>> +
> >>> + return Status;
> >>> +}
> >>
> >> Is our goal to
> >>
> >> (a) catch overflows before the caller goes wrong due
> to them, or
> >> (b) completely prevent undefined behavior from
> happening, even inside
> >> SafeInt64Sub()?
> >>
> >> The above implementation may be good for (a), but it's
> not correct for
> >> (b). The
> >>
> >> SignedResult = Minuend - Subtrahend;
> >>
> >> subtraction invokes undefined behavior if the result
> cannot be
> >> represented [*]; the rest of the code cannot help.
> >>
> >> Now if we say that such subtractions always occur
> according to the
> >> "usual two's complement definition", on all
> architectures that edk2
> >> targets, and we're sure that no compiler or analysis
> tool will flag --
> >> or exploit -- the UB either, then the code is fine;
> meaning our choice
> >> is (a).
> >>
> >> But, if (b) is our goal, I would replace the current
> error condition with:
> >>
> >> (((Subtrahend > 0) && (Minuend < MIN_INT64 +
> Subtrahend)) ||
> >> ((Subtrahend < 0) && (Minuend > MAX_INT64 +
> Subtrahend)))
> >
> > To clarify, I wouldn't just replace the error
> condition. In addition to
> > that, I would remove the SignedResult helper variable
> (together with the
> > current subtraction), and calculate & assign
> >
> > *Result = Minuend - Subtrahend;
> >
> > only after the error condition fails (i.e. the
> subtraction is safe).
> >
> > Thanks,
> > Laszlo
> >
> >
> >> Justification:
> >>
> >> * Subtrahend==0 can never cause overflow
> >>
> >> * Subtrahend>0 can only cause overflow at the negative
> end, so check
> >> that: (Minuend - Subtrahend < MIN_INT64),
> mathematically speaking.
> >> In order to write that down in C, add Subtrahend (a
> positive value)
> >> to both sides, yielding (Minuend < MIN_INT64 +
> Subtrahend). Here,
> >> (MIN_INT64 + Subtrahend) will never go out of range,
> because
> >> Subtrahend is positive, and (MIN_INT64 + MAX_INT64)
> is representable.
> >>
> >> * Subtrahend<0 can only cause overflow at the positive
> end, so check
> >> that: (Minuend - Subtrahend > MAX_INT64),
> mathematically speaking.
> >> In order to write that down in C, add Subtrahend (a
> negative value)
> >> to both sides, yielding (Minuend > MAX_INT64 +
> Subtrahend). Here,
> >> (MAX_INT64 + Subtrahend) will never go out of range,
> because
> >> Subtrahend is negative, and (MAX_INT64 + MIN_INT64)
> is representable.
> >>
> >> (
> >>
> >> [*] ISO C99 section 6.5 Expressions, p5: "If an
> exceptional condition
> >> occurs during the evaluation of an expression (that
> is, if the result is
> >> not mathematically defined or not in the range of
> representable values
> >> for its type), the behavior is undefined."
> >>
> >> Section 6.2.5 Types, p9 only exempts unsigned
> integers, "A computation
> >> involving unsigned operands can never overflow,
> because a result that
> >> cannot be represented by the resulting unsigned
> integer type is reduced
> >> modulo the number that is one greater than the largest
> value that can be
> >> represented by the resulting type."
> >>
> >> Note that this is different from conversion, where the
> computation first
> >> succeeds (= we have a value), and then the value is
> converted to a type
> >> that causes truncation: section 6.3.1.3 Signed and
> unsigned integers,
> >> p3: "Otherwise, the new type is signed and the value
> cannot be
> >> represented in it; either the result is
> implementation-defined or an
> >> implementation-defined signal is raised."
> >>
> >> In the code above, the expression (Minuend -
> Subtrahend) can invoke
> >> undefined behavior, there is no conversion (not even
> as part of the
> >> assignment to SignedResult).
> >>
> >> )
> >>
> >> Thanks,
> >> Laszlo
> >> _______________________________________________
> >> edk2-devel mailing list
> >> edk2-devel@lists.01.org
> >> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fmailman%2Flistinfo%2Fedk2-devel&data=04%7C01%7CBret.Barkelew%40microsoft.com%7C87f15d7947fe45fee17a08d572fd542d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636541354724483642%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwifQ%3D%3D%7C-1&sdata=rFfax%2BkpyDxZt9UPmIT9tdBFC1KOeq3Xhfudm00XcC0%3D&reserved=0
> >>
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fmailman%2Flistinfo%2Fedk2-devel&data=04%7C01%7CBret.Barkelew%40microsoft.com%7C87f15d7947fe45fee17a08d572fd542d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636541354724483642%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwifQ%3D%3D%7C-1&sdata=rFfax%2BkpyDxZt9UPmIT9tdBFC1KOeq3Xhfudm00XcC0%3D&reserved=0
> >
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fmailman%2Flistinfo%2Fedk2-devel&data=04%7C01%7CBret.Barkelew%40microsoft.com%7C87f15d7947fe45fee17a08d572fd542d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636541354724483642%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwifQ%3D%3D%7C-1&sdata=rFfax%2BkpyDxZt9UPmIT9tdBFC1KOeq3Xhfudm00XcC0%3D&reserved=0
next prev parent reply other threads:[~2018-02-13 16:50 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-12-19 19:36 [Patch] MdePkg/BaseSafeIntLib: Add SafeIntLib class and instance Kinney, Michael D
2018-01-18 8:09 ` Sean Brogan
2018-01-19 7:48 ` Gao, Liming
2018-02-08 0:32 ` Laszlo Ersek
2018-02-08 0:45 ` Laszlo Ersek
2018-02-13 12:23 ` Laszlo Ersek
2018-02-13 16:17 ` Kinney, Michael D
2018-02-13 16:56 ` Bret Barkelew [this message]
2018-02-13 17:15 ` Andrew Fish
2018-02-13 17:55 ` Laszlo Ersek
2018-02-13 17:29 ` Laszlo Ersek
2018-02-13 18:19 ` Bret Barkelew
2018-02-13 17:18 ` Ard Biesheuvel
2018-02-13 17:51 ` Laszlo Ersek
2018-02-13 17:55 ` Ard Biesheuvel
2018-02-13 18:03 ` Laszlo Ersek
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=DM5PR2101MB093655672D809EC195855A4BEFF60@DM5PR2101MB0936.namprd21.prod.outlook.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