]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
MdePkg/BaseSafeIntLib: fix undefined behavior in SafeInt64Sub()
[mirror_edk2.git] / MdePkg / Library / BaseSafeIntLib / SafeIntLib.c
index d846160ba0d10550a9deba795bee9502632ef920..8e857927b0672e1b022ed9430ce1fe2dd07619c3 100644 (file)
@@ -3837,27 +3837,55 @@ SafeInt64Sub (
   )\r
 {\r
   RETURN_STATUS  Status;\r
-  INT64          SignedResult;\r
 \r
   if (Result == NULL) {\r
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
-  SignedResult = Minuend - Subtrahend;\r
-\r
   //\r
-  // Subtracting a positive number from a positive number never overflows.\r
-  // Subtracting a negative number from a negative number never overflows.\r
-  // If you subtract a negative number from a positive number, you expect a positive result.\r
-  // If you subtract a positive number from a negative number, you expect a negative result.\r
-  // Overflow if inputs vary in sign and the output does not have the same sign as the first input.\r
+  // * A Subtrahend of zero can never cause underflow or overflow.\r
+  //\r
+  // * A positive Subtrahend can only cause underflow. The underflow condition\r
+  //   is:\r
+  //\r
+  //     (Minuend - Subtrahend) < MIN_INT64\r
+  //\r
+  //   Adding Subtrahend to both sides yields\r
+  //\r
+  //     Minuend < (MIN_INT64 + Subtrahend)\r
+  //\r
+  //   This condition can be coded directly in C because the RHS will neither\r
+  //   underflow nor overflow. That is due to the starting condition:\r
+  //\r
+  //     0 < Subtrahend <= MAX_INT64\r
+  //\r
+  //   Adding MIN_INT64 to all three sides yields\r
+  //\r
+  //     MIN_INT64 < (MIN_INT64 + Subtrahend) <= (MIN_INT64 + MAX_INT64) = -1\r
   //\r
-  if (((Minuend < 0) != (Subtrahend < 0)) &&\r
-      ((Minuend < 0) != (SignedResult < 0))) {\r
+  // * A negative Subtrahend can only cause overflow. The overflow condition is\r
+  //\r
+  //     (Minuend - Subtrahend) > MAX_INT64\r
+  //\r
+  //   Adding Subtrahend to both sides yields\r
+  //\r
+  //     Minuend > (MAX_INT64 + Subtrahend)\r
+  //\r
+  //   This condition can be coded directly in C because the RHS will neither\r
+  //   underflow nor overflow. That is due to the starting condition:\r
+  //\r
+  //     MIN_INT64 <= Subtrahend < 0\r
+  //\r
+  //   Adding MAX_INT64 to all three sides yields\r
+  //\r
+  //     -1 = (MAX_INT64 + MIN_INT64) <= (MAX_INT64 + Subtrahend) < MAX_INT64\r
+  //\r
+  if (((Subtrahend > 0) && (Minuend < (MIN_INT64 + Subtrahend))) ||\r
+      ((Subtrahend < 0) && (Minuend > (MAX_INT64 + Subtrahend)))) {\r
     *Result = INT64_ERROR;\r
     Status = RETURN_BUFFER_TOO_SMALL;\r
   } else {\r
-    *Result = SignedResult;\r
+    *Result = Minuend - Subtrahend;\r
     Status = RETURN_SUCCESS;\r
   }\r
 \r