From 84998f9d052d49839a3bba75a91c3419acd87a86 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 2 Nov 2017 17:40:14 +0100 Subject: [PATCH] fix #5167 --- ChangeLog | 3 +++ src/util/amount.c | 49 +++++++++++++++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80697eed5..2948a76c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +Thu Nov 2 17:39:40 CET 2017 + Limit amount values to 2^53 as we always wanted (#5167). -CG + Thu Nov 2 16:50:46 CET 2017 Fixing serious bug in reserve balance calculations, as fees were not always properly included in the summation. -CG diff --git a/src/util/amount.c b/src/util/amount.c index 33ba9a2f7..d52a32cf6 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -29,6 +29,25 @@ #endif #include +/** + * Maximum legal 'value' for an amount, based on IEEE double (for JavaScript compatibility). + */ +#define MAX_AMOUNT_VALUE (1LLU << 53) + + +/** + * Set @a a to "invalid". + * + * @param a amount to set to invalid + */ +static void +invalidate (struct TALER_Amount *a) +{ + memset (a, + 0, + sizeof (struct TALER_Amount)); +} + /** * Parse money amount description, in the format "A:B.C". @@ -48,9 +67,7 @@ TALER_string_to_amount (const char *str, const char *colon; const char *value; - memset (denom, - 0, - sizeof (struct TALER_Amount)); + invalidate (denom); /* skip leading whitespace */ while (isspace( (unsigned char) str[0])) str++; @@ -139,6 +156,12 @@ TALER_string_to_amount (const char *str, b /= 10; i++; } + if (denom->value > MAX_AMOUNT_VALUE) + { + /* too large to be legal */ + invalidate (denom); + return GNUNET_SYSERR; + } return GNUNET_OK; fail: @@ -237,20 +260,6 @@ TALER_amount_get_zero (const char *cur, } -/** - * Set @a a to "invalid". - * - * @param a amount to set to invalid - */ -static void -invalidate (struct TALER_Amount *a) -{ - memset (a, - 0, - sizeof (struct TALER_Amount)); -} - - /** * Test if the given amount is valid. * @@ -472,6 +481,12 @@ TALER_amount_add (struct TALER_Amount *sum, invalidate (sum); return GNUNET_SYSERR; } + if (res.value > MAX_AMOUNT_VALUE) + { + /* too large to be legal */ + invalidate (sum); + return GNUNET_SYSERR; + } res.fraction = n1.fraction + n2.fraction; if (GNUNET_SYSERR == TALER_amount_normalize (&res))