@@ -764,27 +764,40 @@ std::enable_if_t<std::is_signed_v<T>, T> MulOverflow(T X, T Y, T &Result) {
764764#if __has_builtin(__builtin_mul_overflow)
765765 return __builtin_mul_overflow (X, Y, &Result);
766766#else
767- // Perform the unsigned multiplication on absolute values.
768767 using U = std::make_unsigned_t <T>;
769- const U UX = X < 0 ? (0 - static_cast <U>(X)) : static_cast <U>(X);
770- const U UY = Y < 0 ? (0 - static_cast <U>(Y)) : static_cast <U>(Y);
771- const U UResult = UX * UY;
772768
773- // Convert to signed.
774- const bool IsNegative = (X < 0 ) ^ (Y < 0 );
775- Result = IsNegative ? (0 - UResult) : UResult;
776-
777- // If any of the args was 0, result is 0 and no overflow occurs.
778- if (UX == 0 || UY == 0 )
769+ // Handle zero case
770+ if (X == 0 || Y == 0 ) {
771+ Result = 0 ;
779772 return false ;
773+ }
780774
781- // UX and UY are in [1, 2^n], where n is the number of digits.
782- // Check how the max allowed absolute value (2^n for negative, 2^(n-1) for
783- // positive) divided by an argument compares to the other.
784- if (IsNegative)
785- return UX > (static_cast <U>(std::numeric_limits<T>::max ()) + U (1 )) / UY;
786- else
787- return UX > (static_cast <U>(std::numeric_limits<T>::max ())) / UY;
775+ bool IsNegative = (X < 0 ) ^ (Y < 0 );
776+
777+ // Safely compute absolute values
778+ const U AbsX = X < 0 ? (0 - static_cast <U>(X+1 ))+1 : static_cast <U>(X);
779+ const U AbsY = Y < 0 ? (0 - static_cast <U>(Y+1 ))+1 : static_cast <U>(Y);
780+
781+ // Overflow check before actual multiplication
782+ constexpr U MaxPositive = static_cast <U>(std::numeric_limits<T>::max ());
783+ constexpr U MaxNegative = static_cast <U>(std::numeric_limits<T>::max ()) + 1 ;
784+
785+ // Safe to multiply
786+ U AbsResult = AbsX * AbsY;
787+ Result = IsNegative ? static_cast <T>(0 -AbsResult) : static_cast <T>(AbsResult);
788+
789+ // Handle INT_MIN * -1 overflow case explicitly
790+ if ((X == std::numeric_limits<T>::min () && Y == -1 ) ||
791+ (Y == std::numeric_limits<T>::min () && X == -1 )) {
792+ return true ; // overflow
793+ }
794+
795+ U Limit = IsNegative ? MaxNegative : MaxPositive;
796+
797+ if (AbsX > Limit / AbsY)
798+ return true ;
799+
800+ return false ;
788801#endif
789802}
790803
0 commit comments