From 9cd5c63771a21c5769366e058d1d8bf1cea89970 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 12 May 2018 14:29:33 -0700 Subject: [PATCH] cli: control numeric argument overflow exit on overflow backported from paramgrill added associated test case --- programs/zstdcli.c | 22 ++++++++++++++++++---- tests/playTests.sh | 2 ++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 24488191..28bfdc53 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -219,20 +219,34 @@ static int exeNameMatch(const char* exeName, const char* test) (exeName[strlen(test)] == '\0' || exeName[strlen(test)] == '.'); } +static void errorOut(const char* msg) +{ + DISPLAY("%s \n", msg); exit(1); +} + /*! readU32FromChar() : * @return : unsigned integer value read from input in `char` format. * allows and interprets K, KB, KiB, M, MB and MiB suffix. * Will also modify `*stringPtr`, advancing it to position where it stopped reading. - * Note : function result can overflow if digit string > MAX_UINT */ + * Note : function will exit() program if digit sequence overflows */ static unsigned readU32FromChar(const char** stringPtr) { + const char errorMsg[] = "error: numeric value too large"; unsigned result = 0; - while ((**stringPtr >='0') && (**stringPtr <='9')) + while ((**stringPtr >='0') && (**stringPtr <='9')) { + unsigned const max = (((unsigned)(-1)) / 10) - 1; + if (result > max) errorOut(errorMsg); result *= 10, result += **stringPtr - '0', (*stringPtr)++ ; + } if ((**stringPtr=='K') || (**stringPtr=='M')) { + unsigned const maxK = ((unsigned)(-1)) >> 10; + if (result > maxK) errorOut(errorMsg); result <<= 10; - if (**stringPtr=='M') result <<= 10; - (*stringPtr)++ ; + if (**stringPtr=='M') { + if (result > maxK) errorOut(errorMsg); + result <<= 10; + } + (*stringPtr)++; /* skip `K` or `M` */ if (**stringPtr=='i') (*stringPtr)++; if (**stringPtr=='B') (*stringPtr)++; } diff --git a/tests/playTests.sh b/tests/playTests.sh index c8e27f23..200de4bd 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -108,6 +108,8 @@ $ECHO "test : --fast aka negative compression levels" $ZSTD --fast -f tmp # == -1 $ZSTD --fast=3 -f tmp # == -3 $ZSTD --fast=200000 -f tmp # == no compression +$ECHO "test : too large numeric argument" +$ZSTD --fast=9999999999 -f tmp && die "should have refused numeric value" $ECHO "test : compress to stdout" $ZSTD tmp -c > tmpCompressed $ZSTD tmp --stdout > tmpCompressed # long command format