From 1c3903c2e644d55913708b6867e33aab1a076ac9 Mon Sep 17 00:00:00 2001 From: Grim Maple Date: Fri, 8 Jul 2022 21:28:11 +0300 Subject: [PATCH] Fix Issue 22637 - std.conv `to!double` and `parse!double` dont throw on under/overflow This happened because `parse` enforced on real. And provided number actually fits real. Changed to enforce on `Target` type instead --- std/conv.d | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/std/conv.d b/std/conv.d index 8f6c3bf56..9164e0798 100644 --- a/std/conv.d +++ b/std/conv.d @@ -3419,17 +3419,20 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum } } + Target result = cast(Target) (sign ? -ldval : ldval); + // if overflow occurred - enforce(ldval != real.infinity, new ConvException("Range error")); + import std.math : isFinite; + enforce(isFinite(result), new ConvException("Range error")); advanceSource(); static if (doCount) { - return tuple!("data", "count")(cast (Target) (sign ? -ldval : ldval), count); + return tuple!("data", "count")(result, count); } else { - return cast (Target) (sign ? -ldval : ldval); + return result; } } @@ -3785,6 +3788,16 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum assertThrown!ConvException(parse!double(s)); } +@safe unittest // https://issues.dlang.org/show_bug.cgi?id=22637 +{ + import std.exception : assertThrown, assertNotThrown; + auto src = "9991232549867999698999493543521458974414359998784641646846435132132543645435456345634541999999999999999" + ~ "9999999943321231321311999231345312413646846354354354399999934153465464654646464654134135354199999999996515734999" + ~ "9999999320135273486741354354731567431324134999999999999999999999999999999999999999999999135411.9"; + assertThrown!ConvException(parse!double(src)); + static if (real.max_10_exp > 310) assertNotThrown!ConvException(parse!real(src)); +} + /** Parsing one character off a range returns the first element and calls `popFront`.