This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
fix undefined float behaviour in pack('f')
authorDavid Mitchell <davem@iabyn.com>
Mon, 22 Dec 2014 09:34:40 +0000 (09:34 +0000)
committerDavid Mitchell <davem@iabyn.com>
Wed, 31 Dec 2014 11:28:51 +0000 (11:28 +0000)
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.

pp_pack.c

index ad4f186..9ed8c59 100644 (file)
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -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);
            }