Skip to content

Commit 4991a69

Browse files
committed
Floating-point normalization must not overflow
We need to extend the exponent to compute a new exponent without overflow; subsequent denormalization and rounding will ensure the exponent fits into the target format. Fixes: #7616
1 parent 5cd2d1b commit 4991a69

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE broken-z3-smt-backend
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
Z3 appears to suffer from a similar bug as we previously did.

src/solvers/floatbv/float_utils.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ bvt float_utilst::conversion(
195195
if(dest_spec.e > spec.e)
196196
{
197197
normalization_shift(result.fraction, result.exponent);
198+
result.exponent.resize(dest_spec.e);
198199
}
199200

200201
// the flags get copied
@@ -792,8 +793,9 @@ void float_utilst::normalization_shift(bvt &fraction, bvt &exponent)
792793
PRECONDITION(!fraction.empty());
793794
std::size_t depth = address_bits(fraction.size() - 1);
794795

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

798800
bvt exponent_delta=bv_utils.zeros(exponent.size());
799801

0 commit comments

Comments
 (0)