From 1b203507f6d7b4ab167f6e575fd7c206bba24d1c Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 17 Jul 2018 16:03:05 +0200 Subject: [PATCH] conv: Fix overflow hanndling in readIntegral --- source/tanya/conv.d | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/source/tanya/conv.d b/source/tanya/conv.d index 61935f6..a244841 100644 --- a/source/tanya/conv.d +++ b/source/tanya/conv.d @@ -282,8 +282,8 @@ final class ConvException : Exception * * The function doesn't handle the sign (+ or -) or number prefixes (like 0x). */ -package T readIntegral(T, R)(ref R range, ubyte base = 10) -if (isForwardRange!R +package T readIntegral(T, R)(ref R range, const ubyte base = 10) +if (isInputRange!R && isSomeChar!(ElementType!R) && isIntegral!T && isUnsigned!T) @@ -301,9 +301,9 @@ do } T n; - while (n <= boundary) + int digit; + do { - int digit; if (range.front >= 'a') { digit = range.front - 'W'; @@ -332,17 +332,30 @@ do return n; } } - if (range.length > 1) + while (n < boundary); + + if (range.front >= 'a') + { + digit = range.front - 'W'; + } + else if (range.front >= 'A') + { + digit = range.front - '7'; + } + else if (range.front >= '0') + { + digit = range.front - '0'; + } + else { return n; } - - int digit = range.front - '0'; if (n > cast(T) ((T.max - digit) / base)) { return n; } n = cast(T) (n * base + digit); + range.popFront(); return n; } @@ -410,6 +423,14 @@ do assert(number.empty); } +// Handles small overflows +@nogc nothrow pure @safe unittest +{ + string number = "256"; + assert(readIntegral!ubyte(number, 10) == 25); + assert(number.front == '6'); +} + /** * If the source type $(D_PARAM From) and the target type $(D_PARAM To) are * equal, does nothing. If $(D_PARAM From) can be implicitly converted to