summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2015-11-06 18:54:16 -0500
committerSteve Hay <steve.m.hay@googlemail.com>2015-11-15 12:02:07 +0000
commitfff4a2c9645dffe498ae699ff5d35c1a74670f94 (patch)
tree85aa204fdb93e3ddd7b7a4cd8d564d3e9d65c51c
parent9a8b9949c11e771441d869f5fee53bfc5c006253 (diff)
downloadperl-fff4a2c9645dffe498ae699ff5d35c1a74670f94.tar.gz
perl #126582 hexfp overflow drops hi-order bits
(cherry picked from commit 0c8adad77d308bd7d386922521a57b894a2bf959)
-rw-r--r--t/op/hexfp.t22
-rw-r--r--toke.c16
2 files changed, 28 insertions, 10 deletions
diff --git a/t/op/hexfp.t b/t/op/hexfp.t
index 30aaf1160c..e83050e348 100644
--- a/t/op/hexfp.t
+++ b/t/op/hexfp.t
@@ -10,7 +10,7 @@ use strict;
use Config;
-plan(tests => 79);
+plan(tests => 85);
# Test hexfloat literals.
@@ -169,9 +169,27 @@ SKIP:
eval '0x1.fffffffffffffp+1024';
like(get_warn(), qr/^Hexadecimal float: exponent overflow/);
+
+ undef $a;
+ eval '$a = 0x111.0000000000000p+0'; # 12 zeros.
+ like(get_warn(), qr/^Hexadecimal float: mantissa overflow/);
+ is($a, 273);
+
+ # The 13 zeros would be enough to push the hi-order digits
+ # off the high-end.
+
+ undef $a;
+ eval '$a = 0x111.0000000000000p+0'; # 13 zeros.
+ like(get_warn(), qr/^Hexadecimal float: mantissa overflow/);
+ is($a, 273);
+
+ undef $a;
+ eval '$a = 0x111.00000000000000p+0'; # 14 zeros.
+ like(get_warn(), qr/^Hexadecimal float: mantissa overflow/);
+ is($a, 273);
} else {
print "# skipping warning tests\n";
- skip "nv_preserves_uv_bits is $Config{nv_preserves_uv_bits} not 53", 8;
+ skip "nv_preserves_uv_bits is $Config{nv_preserves_uv_bits} not 53", 14;
}
}
diff --git a/toke.c b/toke.c
index 4073d256aa..ecd2812f54 100644
--- a/toke.c
+++ b/toke.c
@@ -10232,21 +10232,21 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
#ifdef HEXFP_NV
NV mult = 1 / 16.0;
#endif
- h++;
- while (isXDIGIT(*h) || *h == '_') {
+ for (h++; (isXDIGIT(*h) || *h == '_'); h++) {
if (isXDIGIT(*h)) {
U8 b = XDIGIT_VALUE(*h);
total_bits += shift;
+ if (total_bits < NV_MANT_DIG) {
#ifdef HEXFP_UQUAD
- hexfp_uquad <<= shift;
- hexfp_uquad |= b;
- hexfp_frac_bits += shift;
+ hexfp_uquad <<= shift;
+ hexfp_uquad |= b;
+ hexfp_frac_bits += shift;
#else /* HEXFP_NV */
- hexfp_nv += b * mult;
- mult /= 16.0;
+ hexfp_nv += b * mult;
+ mult /= 16.0;
#endif
+ }
}
- h++;
}
}