Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.

Commit c939390

Browse files
committed
Remove UB from int-to-float conversion for INT_MIN.
1 parent 8598065 commit c939390

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

lib/builtins/floatsidf.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,32 @@
2121
ARM_EABI_FNALIAS(i2d, floatsidf)
2222

2323
COMPILER_RT_ABI fp_t
24-
__floatsidf(int a) {
24+
__floatsidf(int a_orig) {
2525

26-
const int aWidth = sizeof a * CHAR_BIT;
26+
const int aWidth = sizeof a_orig * CHAR_BIT;
27+
28+
// unsigned int representation is necessary to avoid
29+
// undefined behavior for the input INT_MIN.
30+
unsigned int a = (unsigned int) a_orig;
2731

2832
// Handle zero as a special case to protect clz
2933
if (a == 0)
3034
return fromRep(0);
3135

3236
// All other cases begin by extracting the sign and absolute value of a
3337
rep_t sign = 0;
34-
if (a < 0) {
38+
if (a_orig < 0) {
3539
sign = signBit;
36-
a = -a;
40+
a = ~a + 1; // same as (unsigned int)-a_orig, but defined for INT_MIN
3741
}
3842

3943
// Exponent of (fp_t)a is the width of abs(a).
4044
const int exponent = (aWidth - 1) - __builtin_clz(a);
4145
rep_t result;
4246

43-
// Shift a into the significand field and clear the implicit bit. Extra
44-
// cast to unsigned int is necessary to get the correct behavior for
45-
// the input INT_MIN.
47+
// Shift a into the significand field and clear the implicit bit.
4648
const int shift = significandBits - exponent;
47-
result = (rep_t)(unsigned int)a << shift ^ implicitBit;
49+
result = (rep_t)a << shift ^ implicitBit;
4850

4951
// Insert the exponent
5052
result += (rep_t)(exponent + exponentBias) << significandBits;

lib/builtins/floatsisf.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,23 @@
2121
ARM_EABI_FNALIAS(i2f, floatsisf)
2222

2323
COMPILER_RT_ABI fp_t
24-
__floatsisf(int a) {
24+
__floatsisf(int a_orig) {
2525

2626
const int aWidth = sizeof a * CHAR_BIT;
27+
28+
// unsigned int representation is necessary to avoid
29+
// undefined behavior for the input INT_MIN.
30+
unsigned int a = (unsigned int) a_orig;
2731

2832
// Handle zero as a special case to protect clz
2933
if (a == 0)
3034
return fromRep(0);
3135

3236
// All other cases begin by extracting the sign and absolute value of a
3337
rep_t sign = 0;
34-
if (a < 0) {
38+
if (a_orig < 0) {
3539
sign = signBit;
36-
a = -a;
40+
a = ~a + 1; // same as (unsigned int)-a_orig, but defined for INT_MIN
3741
}
3842

3943
// Exponent of (fp_t)a is the width of abs(a).

0 commit comments

Comments
 (0)