diff options
author | David Mitchell <davem@iabyn.com> | 2014-12-22 09:34:40 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2014-12-31 11:28:51 +0000 |
commit | 919894b775f42c5afd2195b1a5240e66205560d1 (patch) | |
tree | 32a0976a5df5f608512c5840bdf109ac299c8039 /pp_pack.c | |
parent | 2afa5dd07629c20c6931b8c5e4c1671520787a9d (diff) | |
download | perl-919894b775f42c5afd2195b1a5240e66205560d1.tar.gz |
fix undefined float behaviour in pack('f')
The C standard says that the value of the expression (float)double_var is
undefined if 'the value being converted is outside the range of values
that can be represented'.
So to shut up -fsanitize=undefined:
my $p = pack 'f', 1.36514538e67;
giving
runtime error: value 1.36515e+67 is outside the range of representable values of type 'float'
explicitly handle the out of range values.
Something similar is already done under defined(VMS) && !defined(_IEEE_FP),
except that there it floors to +/- FLT_MAX rather than +/- (float)NV_INF.
I don't know which branch is best, and whether they should be merged.
This fix was suggested by Aaron Crane.
Diffstat (limited to 'pp_pack.c')
-rw-r--r-- | pp_pack.c | 5 |
1 files changed, 4 insertions, 1 deletions
@@ -2719,7 +2719,10 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist ) afloat = -FLT_MAX; else afloat = (float)anv; # else - afloat = (float)anv; + /* a simple cast to float is undefined if outside + * the range of values that can be represented */ + afloat = (float)(anv > FLT_MAX ? NV_INF : + anv < -FLT_MAX ? -NV_INF : anv); # endif PUSH_VAR(utf8, cur, afloat, needs_swap); } |