Skip to content

Commit 6066b34

Browse files
authored
Merge pull request #7617 from tautschnig/bugfixes/7616-float-conversion
Floating-point normalization must not overflow
2 parents dd427f9 + 5c7c154 commit 6066b34

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
#if 0
6+
// examples of constants that previously exhibited wrong behaviour
7+
union U
8+
{
9+
double d;
10+
uint64_t b;
11+
};
12+
union U u = {
13+
.b = 0b0000000000000011111111111111111111111110000001000000000000000000};
14+
union U u2 = {
15+
.b = 0b0000000000000000000000000000001111111111111111111111111000000000};
16+
double d = u.d;
17+
#else
18+
double d;
19+
#endif
20+
float f;
21+
if(d > 0.0 && d < 1.0)
22+
{
23+
f = d;
24+
assert(f <= 1.0f);
25+
}
26+
return 0;
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/solvers/floatbv/float_bv.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,14 @@ exprt float_bvt::conversion(
458458
// if the number was denormal and is normal in the new format,
459459
// normalise it!
460460
if(dest_spec.e > src_spec.e)
461+
{
461462
normalization_shift(result.fraction, result.exponent);
463+
// normalization_shift unconditionally extends the exponent size to avoid
464+
// arithmetic overflow, but this cannot have happened here as the exponent
465+
// had already been extended to dest_spec's size
466+
result.exponent =
467+
typecast_exprt(result.exponent, signedbv_typet(dest_spec.e));
468+
}
462469

463470
// the flags get copied
464471
result.sign=unpacked_src.sign;
@@ -954,8 +961,8 @@ void float_bvt::normalization_shift(
954961

955962
std::size_t depth = address_bits(fraction_bits - 1);
956963

957-
if(exponent_bits<depth)
958-
exponent=typecast_exprt(exponent, signedbv_typet(depth));
964+
exponent = typecast_exprt(
965+
exponent, signedbv_typet(std::max(depth, exponent_bits + 1)));
959966

960967
exprt exponent_delta=from_integer(0, exponent.type());
961968

src/solvers/floatbv/float_utils.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ bvt float_utilst::conversion(
195195
if(dest_spec.e > spec.e)
196196
{
197197
normalization_shift(result.fraction, result.exponent);
198+
// normalization_shift unconditionally extends the exponent size to avoid
199+
// arithmetic overflow, but this cannot have happened here as the exponent
200+
// had already been extended to dest_spec's size
201+
result.exponent.resize(dest_spec.e);
198202
}
199203

200204
// the flags get copied
@@ -792,8 +796,9 @@ void float_utilst::normalization_shift(bvt &fraction, bvt &exponent)
792796
PRECONDITION(!fraction.empty());
793797
std::size_t depth = address_bits(fraction.size() - 1);
794798

795-
if(exponent.size()<depth)
796-
exponent=bv_utils.sign_extension(exponent, depth);
799+
// sign-extend to ensure the arithmetic below cannot result in overflow/underflow
800+
exponent =
801+
bv_utils.sign_extension(exponent, std::max(depth, exponent.size() + 1));
797802

798803
bvt exponent_delta=bv_utils.zeros(exponent.size());
799804

0 commit comments

Comments
 (0)