[compiler-rt] Avoid signed overflow in floatdidf.c and floatdisf.c
authorKarl-Johan Karlsson <karl-johan.karlsson@ericsson.com>
Fri, 17 Mar 2023 06:28:38 +0000 (07:28 +0100)
committerKarl-Johan Karlsson <karl-johan.karlsson@ericsson.com>
Fri, 17 Mar 2023 07:14:57 +0000 (08:14 +0100)
When compiling compiler-rt with -fsanitize=undefined and running testcases you
end up with the following warning:

UBSan: floatdisf.c:27:15: signed integer overflow: 9223372036854775807 - -1 cannot be represented in type 'di_int' (aka 'long long')

This can be avoided by doing the subtraction in a matching unsigned variant of
the type, given that the overflow is the expected result of the subtraction.

The same kind of pattern exists in floatdidf.c

This was found in an out of tree target.

Reviewed By: phosek

Differential Revision: https://reviews.llvm.org/D146135

compiler-rt/lib/builtins/floatdidf.c
compiler-rt/lib/builtins/floatdisf.c

index d37c43b..c994aad 100644 (file)
@@ -50,7 +50,7 @@ COMPILER_RT_ABI double __floatdidf(di_int a) {
     return 0.0;
   const unsigned N = sizeof(di_int) * CHAR_BIT;
   const di_int s = a >> (N - 1);
-  a = (a ^ s) - s;
+  a = (du_int)(a ^ s) - s;
   int sd = N - __builtin_clzll(a); // number of significant digits
   int e = sd - 1;                  // exponent
   if (sd > DBL_MANT_DIG) {
index 5c63164..0b62ed8 100644 (file)
@@ -24,7 +24,7 @@ COMPILER_RT_ABI float __floatdisf(di_int a) {
     return 0.0F;
   const unsigned N = sizeof(di_int) * CHAR_BIT;
   const di_int s = a >> (N - 1);
-  a = (a ^ s) - s;
+  a = (du_int)(a ^ s) - s;
   int sd = N - __builtin_clzll(a); // number of significant digits
   si_int e = sd - 1;               // exponent
   if (sd > FLT_MANT_DIG) {