summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2017-05-28 21:19:11 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2017-05-28 21:19:11 +0000
commit27686683b4dc9bc7469b0b74c29958f1b8c6135d (patch)
treec43676610d6cb1d48e770c70bd764f51758cf089
parentb724807daf09b51c6ee6e1fec1ad93efcc337474 (diff)
downloadmpfr-27686683b4dc9bc7469b0b74c29958f1b8c6135d.tar.gz
[src/vasprintf.c] Fixed overflow checking in partition_number().
In details: * The computation of the number of characters to be written could be incorrect by 1 when the thousands separator was not empty. However, in the 3.1 branch (without additional patches), this value is currently only used for overflow checking, so that this bug could have only very little effect (contrary to the trunk). * When the int and long types have the same size, the code assumed "wrapping behavior in two's complement". But this is actually undefined behavior in ISO C; in practice, a smart compiler may have ignored "total < 0" tests, because total is computed with sums of non-negative integers. (merged changesets r11513,11515-11516 from the trunk) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/3.1@11538 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--src/vasprintf.c48
1 files changed, 24 insertions, 24 deletions
diff --git a/src/vasprintf.c b/src/vasprintf.c
index e4c4ba612..1aebd6950 100644
--- a/src/vasprintf.c
+++ b/src/vasprintf.c
@@ -1452,7 +1452,7 @@ partition_number (struct number_parts *np, mpfr_srcptr p,
struct printf_spec spec)
{
char *str;
- long total;
+ unsigned int total; /* can hold the sum of two non-negative int's + 1 */
int uppercase;
/* WARNING: left justification means right space padding */
@@ -1645,43 +1645,43 @@ partition_number (struct number_parts *np, mpfr_srcptr p,
/* compute the number of characters to be written verifying it is not too
much */
+
+#define INCR_TOTAL(V) \
+ do { \
+ MPFR_ASSERTD ((V) >= 0); \
+ if (MPFR_UNLIKELY ((V) > INT_MAX)) \
+ goto error; \
+ total += (V); \
+ if (MPFR_UNLIKELY (total > INT_MAX)) \
+ goto error; \
+ } while (0)
+
total = np->sign ? 1 : 0;
- total += np->prefix_size;
- total += np->ip_size;
- if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
- goto error;
- total += np->ip_trailing_zeros;
- if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
- goto error;
+ INCR_TOTAL (np->prefix_size);
+ INCR_TOTAL (np->ip_size);
+ INCR_TOTAL (np->ip_trailing_zeros);
+ MPFR_ASSERTD (np->ip_size + np->ip_trailing_zeros >= 1);
if (np->thousands_sep)
/* ' flag, style f and the thousands separator in current locale is not
reduced to the null character */
- total += (np->ip_size + np->ip_trailing_zeros) / 3;
- if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
- goto error;
+ INCR_TOTAL ((np->ip_size + np->ip_trailing_zeros - 1) / 3);
if (np->point)
++total;
- total += np->fp_leading_zeros;
- if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
- goto error;
- total += np->fp_size;
- if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
- goto error;
- total += np->fp_trailing_zeros;
- if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
- goto error;
- total += np->exp_size;
- if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
- goto error;
+ INCR_TOTAL (np->fp_leading_zeros);
+ INCR_TOTAL (np->fp_size);
+ INCR_TOTAL (np->fp_trailing_zeros);
+ INCR_TOTAL (np->exp_size);
if (spec.width > total)
/* pad with spaces or zeros depending on np->pad_type */
{
np->pad_size = spec.width - total;
total += np->pad_size; /* here total == spec.width,
- so 0 < total < INT_MAX */
+ so 0 < total <= INT_MAX */
+ MPFR_ASSERTD (total == spec.width);
}
+ MPFR_ASSERTD (total > 0 && total <= INT_MAX);
return total;
error: