Commit 5185b5619a

LemonBoy <thatlemon@gmail.com>
2021-05-14 12:17:58
compiler-rt: Fix signedness mismatch in f128 mul impl
The `1 - shift` expression was computed using small unsigned types and then casted to i32, producing either an underflow error or an incorrect result. Reported by `@notviri` in #8733
1 parent 00ebbe6
Changed files (2)
lib
std
special
lib/std/special/compiler_rt/mulXf3.zig
@@ -98,8 +98,8 @@ fn mulXf3(comptime T: type, a: T, b: T) T {
         // one or both of a or b is denormal, the other (if applicable) is a
         // normal number.  Renormalize one or both of a and b, and set scale to
         // include the necessary exponent adjustment.
-        if (aAbs < implicitBit) scale +%= normalize(T, &aSignificand);
-        if (bAbs < implicitBit) scale +%= normalize(T, &bSignificand);
+        if (aAbs < implicitBit) scale += normalize(T, &aSignificand);
+        if (bAbs < implicitBit) scale += normalize(T, &bSignificand);
     }
 
     // Or in the implicit significand bit.  (If we fell through from the
@@ -277,7 +277,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T
 
     const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
     significand.* <<= @intCast(std.math.Log2Int(Z), shift);
-    return 1 - shift;
+    return @as(i32, 1) - shift;
 }
 
 fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void {
@@ -285,15 +285,15 @@ fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void {
     const typeWidth = @typeInfo(Z).Int.bits;
     const S = std.math.Log2Int(Z);
     if (count < typeWidth) {
-        const sticky = @truncate(u8, lo.* << @intCast(S, typeWidth -% count));
+        const sticky = @boolToInt((lo.* << @intCast(S, typeWidth -% count)) != 0);
         lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)) | sticky;
         hi.* = hi.* >> @intCast(S, count);
     } else if (count < 2 * typeWidth) {
-        const sticky = @truncate(u8, hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*);
+        const sticky = @boolToInt((hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0);
         lo.* = hi.* >> @intCast(S, count -% typeWidth) | sticky;
         hi.* = 0;
     } else {
-        const sticky = @truncate(u8, hi.* | lo.*);
+        const sticky = @boolToInt((hi.* | lo.*) != 0);
         lo.* = sticky;
         hi.* = 0;
     }
lib/std/special/compiler_rt/mulXf3_test.zig
@@ -88,4 +88,18 @@ test "multf3" {
     );
 
     try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0);
+
+    // Denormal operands.
+    try test__multf3(
+        0x0.0000000000000000000000000001p-16382,
+        0x1.p16383,
+        0x3f90000000000000,
+        0x0,
+    );
+    try test__multf3(
+        0x1.p16383,
+        0x0.0000000000000000000000000001p-16382,
+        0x3f90000000000000,
+        0x0,
+    );
 }