authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-05-14 12:17:58+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-14 15:11:54-04:00
log5185b5619ac703755849da70d158b5a45e5673a7
tree431be66ad7f00906d2a288edf29f18bd18960d8c
parent00ebbe6df2249ba8201c0e5472d95022bf73e782

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

2 files changed, 20 insertions(+), 6 deletions(-)

lib/std/special/compiler_rt/mulXf3.zig+6-6
......@@ -98,8 +98,8 @@ fn mulXf3(comptime T: type, a: T, b: T) T {
9898 // one or both of a or b is denormal, the other (if applicable) is a
9999 // normal number. Renormalize one or both of a and b, and set scale to
100100 // include the necessary exponent adjustment.
101 if (aAbs < implicitBit) scale +%= normalize(T, &aSignificand);
102 if (bAbs < implicitBit) scale +%= normalize(T, &bSignificand);
101 if (aAbs < implicitBit) scale += normalize(T, &aSignificand);
102 if (bAbs < implicitBit) scale += normalize(T, &bSignificand);
103103 }
104104
105105 // 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
277277
278278 const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
279279 significand.* <<= @intCast(std.math.Log2Int(Z), shift);
280 return 1 - shift;
280 return @as(i32, 1) - shift;
281281}
282282
283283fn 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 {
285285 const typeWidth = @typeInfo(Z).Int.bits;
286286 const S = std.math.Log2Int(Z);
287287 if (count < typeWidth) {
288 const sticky = @truncate(u8, lo.* << @intCast(S, typeWidth -% count));
288 const sticky = @boolToInt((lo.* << @intCast(S, typeWidth -% count)) != 0);
289289 lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)) | sticky;
290290 hi.* = hi.* >> @intCast(S, count);
291291 } else if (count < 2 * typeWidth) {
292 const sticky = @truncate(u8, hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*);
292 const sticky = @boolToInt((hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0);
293293 lo.* = hi.* >> @intCast(S, count -% typeWidth) | sticky;
294294 hi.* = 0;
295295 } else {
296 const sticky = @truncate(u8, hi.* | lo.*);
296 const sticky = @boolToInt((hi.* | lo.*) != 0);
297297 lo.* = sticky;
298298 hi.* = 0;
299299 }
lib/std/special/compiler_rt/mulXf3_test.zig+14
......@@ -88,4 +88,18 @@ test "multf3" {
8888 );
8989
9090 try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0);
91
92 // Denormal operands.
93 try test__multf3(
94 0x0.0000000000000000000000000001p-16382,
95 0x1.p16383,
96 0x3f90000000000000,
97 0x0,
98 );
99 try test__multf3(
100 0x1.p16383,
101 0x0.0000000000000000000000000001p-16382,
102 0x3f90000000000000,
103 0x0,
104 );
91105}