]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
MdePkg/BaseSafeIntLib: fix undefined behavior in SafeInt64Add()
[mirror_edk2.git] / MdePkg / Library / BaseSafeIntLib / SafeIntLib.c
index 8e857927b0672e1b022ed9430ce1fe2dd07619c3..56d97cf65601835aacd0d1e79cf2318368f3e9cf 100644 (file)
@@ -3631,26 +3631,62 @@ SafeInt64Add (
   )\r
 {\r
   RETURN_STATUS  Status;\r
-  INT64          SignedResult;\r
 \r
   if (Result == NULL) {\r
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
-  SignedResult = Augend + Addend;\r
-\r
   //\r
-  // Adding positive to negative never overflows.\r
-  // If you add two positive numbers, you expect a positive result.\r
-  // If you add two negative numbers, you expect a negative result.\r
-  // Overflow if inputs are the same sign and output is not that sign.\r
+  // * An Addend of zero can never cause underflow or overflow.\r
+  //\r
+  // * A positive Addend can only cause overflow. The overflow condition is\r
+  //\r
+  //     (Augend + Addend) > MAX_INT64\r
+  //\r
+  //   Subtracting Addend from both sides yields\r
+  //\r
+  //     Augend > (MAX_INT64 - Addend)\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 < Addend <= MAX_INT64\r
+  //\r
+  //   Multiplying all three sides by (-1) yields\r
+  //\r
+  //     0 > (-Addend) >= (-MAX_INT64)\r
+  //\r
+  //   Adding MAX_INT64 to all three sides yields\r
+  //\r
+  //     MAX_INT64 > (MAX_INT64 - Addend) >= 0\r
+  //\r
+  // * A negative Addend can only cause underflow. The underflow condition is\r
+  //\r
+  //     (Augend + Addend) < MIN_INT64\r
+  //\r
+  //   Subtracting Addend from both sides yields\r
+  //\r
+  //     Augend < (MIN_INT64 - Addend)\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 <= Addend < 0\r
+  //\r
+  //   Multiplying all three sides by (-1) yields\r
+  //\r
+  //     (-MIN_INT64) >= (-Addend) > 0\r
+  //\r
+  //   Adding MIN_INT64 to all three sides yields\r
+  //\r
+  //     0 >= (MIN_INT64 - Addend) > MIN_INT64\r
   //\r
-  if (((Augend < 0) == (Addend < 0))  &&\r
-      ((Augend < 0) != (SignedResult < 0))) {\r
+  if (((Addend > 0) && (Augend > (MAX_INT64 - Addend))) ||\r
+      ((Addend < 0) && (Augend < (MIN_INT64 - Addend)))) {\r
     *Result = INT64_ERROR;\r
     Status = RETURN_BUFFER_TOO_SMALL;\r
   } else {\r
-    *Result = SignedResult;\r
+    *Result = Augend + Addend;\r
     Status = RETURN_SUCCESS;\r
   }\r
 \r