Commit Graph

6 Commits

Author SHA1 Message Date
Dandan Bi dc9b2a5740 MdePkg/BaseSafeIntLib: Fix VS2015 IA32 NOOPT build failure
v2: Add [LibraryClasses] section in INF file and refine coding style.

There are VS2015 NOOPT IA32 build failure like below in BaseSafeIntLib.
XXX.lib(XXX.obj): error LNK2001: unresolved external symbol __allmul
XXX.lib(XXX.obj): error LNK2001: unresolved external symbol __allshl
XXX.lib(XXX.obj): error LNK2001: unresolved external symbol __aullshr

This patch replaces direct shift/multiplication of 64-bit integer
with related function call to fix these failure.

Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
2018-02-28 11:44:14 +08:00
Laszlo Ersek 75505d1611 MdePkg/BaseSafeIntLib: fix undefined behavior in SafeInt64Mult()
If we have to negate UnsignedResult (due to exactly one of Multiplicand
and Multiplier being negative), and UnsignedResult is exactly
MIN_INT64_MAGNITUDE (value 2^63), then the statement

        *Result = - ((INT64)UnsignedResult);

invokes both implementation-defined behavior and undefined behavior.

First, MIN_INT64_MAGNITUDE is not representable as INT64, therefore the
result of the (inner) conversion

  (INT64)MIN_INT64_MAGNITUDE

is implementation-defined, or an implementation-defined signal is raised,
according to ISO C99 6.3.1.3p3.

Second, if we assume that the C language implementation defines the
conversion to INT64 simply as reinterpreting the bit pattern
0x8000_0000_0000_0000 as a signed integer in two's complement
representation, then the conversion immediately produces the negative
value MIN_INT64 (value -(2^63)). In turn, the (outer) negation

  -(MIN_INT64)

invokes undefined behavior, because the mathematical result of the
negation, namely 2^63, cannot be represented in an INT64 object. (Not even
mentioning the fact that the mathematical result would be incorrect.) In
practice, the undefined negation of MIN_INT64 happens to produce an
unchanged, valid-looking result on x86, i.e. (-(MIN_INT64)) == MIN_INT64.

We can summarize this as the undefined -- effectless -- negation canceling
out the botched -- auto-negating -- implementation-defined conversion.
Instead of relying on such behavior, dedicate a branch to this situation:
assign MIN_INT64 directly. The branch can be triggered e.g. by multiplying
(2^62) by (-2).

Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Michael D Kinney <michael.d.kinney@intel.com>
2018-02-21 11:57:39 +01:00
Laszlo Ersek 8c33cc0ec9 MdePkg/BaseSafeIntLib: clean up parentheses in MIN_INT64_MAGNITUDE
The definition of the MIN_INT64_MAGNITUDE macro is correct, but it's
harder to read than necessary: the sub-expression

      (( (UINT64) - (MIN_INT64 + 1) ))

is doubly parenthesized. Reusing one pair of the outer parens, rewrite the
sub-expression (without change in meaning) so that the minus sign cannot
be mistaken for subtraction:

      ( (UINT64)(- (MIN_INT64 + 1)) )

The resultant macro definition matches the following expressions in
SafeInt64Mult():

>     //
>     // Avoid negating the most negative number.
>     //
>     UnsignedMultiplicand = ((UINT64)(- (Multiplicand + 1))) + 1;

and

>     //
>     // Avoid negating the most negative number.
>     //
>     UnsignedMultiplier = ((UINT64)(- (Multiplier + 1))) + 1;

Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Michael D Kinney <michael.d.kinney@intel.com>
2018-02-21 11:57:36 +01:00
Laszlo Ersek 41bfaffd13 MdePkg/BaseSafeIntLib: fix undefined behavior in SafeInt64Add()
The addition in the assignment

  SignedResult = Augend + Addend;

is performed with unchecked INT64 operands. According to ISO C, if the
mathematical result of signed integer addition cannot be represented in
the result type, the behavior is undefined. (Refer to ISO C99 6.5p5.
6.2.5p9 only exempts unsigned integers, and 6.3.1.3p3 does not apply
because it treats the conversion of integers that have been successfully
evaluated first.)

Replace the after-the-fact result checking with checks on the operands,
and only perform the addition if it is safe.

Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Michael D Kinney <michael.d.kinney@intel.com>
2018-02-21 11:57:33 +01:00
Laszlo Ersek 54c7728a04 MdePkg/BaseSafeIntLib: fix undefined behavior in SafeInt64Sub()
The subtraction in the assignment

  SignedResult = Minuend - Subtrahend;

is performed with unchecked INT64 operands. According to ISO C, if the
mathematical result of signed integer subtraction cannot be represented in
the result type, the behavior is undefined. (Refer to ISO C99 6.5p5.
6.2.5p9 only exempts unsigned integers, and 6.3.1.3p3 does not apply
because it treats the conversion of integers that have been successfully
evaluated first.)

Replace the after-the-fact result checking with checks on the operands,
and only perform the subtraction if it is safe.

Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Michael D Kinney <michael.d.kinney@intel.com>
2018-02-21 11:57:30 +01:00
Sean Brogan d7a09cb86a MdePkg/BaseSafeIntLib: Add SafeIntLib class and instance
https://bugzilla.tianocore.org/show_bug.cgi?id=798

SafeIntLib provides helper functions to prevent integer overflow
during type conversion, addition, subtraction, and multiplication.

Conversion Functions
====================
* Converting from a signed type to an unsigned type of the same
  size, or vice-versa.
* Converting to a smaller type that could possibly overflow.
* Converting from a signed type to a larger unsigned type.

Unsigned Addition, Subtraction, Multiplication
===============================================
* Unsigned integer math functions protect from overflow and
  underflow (in case of subtraction).

Signed Addition, Subtraction, Multiplication
============================================
* Strongly consider using unsigned numbers.
* Signed numbers are often used where unsigned numbers should
  be used. For example file sizes and array indices should always
  be unsigned. Subtracting a larger positive signed number from a
  smaller positive signed number with SafeInt32Sub() will succeed,
  producing a negative number, that then must not be used as an
  array index (but can occasionally be used as a pointer index.)
  Similarly for adding a larger magnitude negative number to a
  smaller magnitude positive number.
* SafeIntLib does not protect you from such errors. It tells you
  if your integer operations overflowed, not if you are doing the
  right thing with your non-overflowed integers.
* Likewise you can overflow a buffer with a non-overflowed
  unsigned index.

Based on content from the following branch/commits:
https://github.com/Microsoft/MS_UEFI/tree/share/MsCapsuleSupport
21ef3a321c
ca516b1a61
33bab4031a

Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Sean Brogan <sean.brogan@microsoft.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
2018-01-25 09:42:20 -08:00