Mercurial > dovecot > core-2.2
changeset 17552:1d873182d5a8
lib: strnum - harden str_to_uintmax against overflows
The invalid number "20496382304121724020" (2^64*10/9) will be parsed as valid.
2049638230412172402 * 10 does not noticably wrap, it becomes 2049638230412172404
Do not perform operations which might wrap, and then try to detect the issue,
just compare with the known fixed bounds before doing the multiplication.
Signed-off-by: Phil Carmody <phil@dovecot.fi>
author | Phil Carmody <phil@dovecot.fi> |
---|---|
date | Wed, 02 Jul 2014 18:21:24 +0300 |
parents | 6c1e44033e60 |
children | 59b6893fbf65 |
files | src/lib/strnum.c |
diffstat | 1 files changed, 7 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/strnum.c Wed Jul 02 18:21:24 2014 +0300 +++ b/src/lib/strnum.c Wed Jul 02 18:21:24 2014 +0300 @@ -84,18 +84,19 @@ int str_to_uintmax(const char *str, uintmax_t *num_r) { - uintmax_t next, n = 0; + uintmax_t n = 0; if (*str < '0' || *str > '9') return -1; for (; *str >= '0' && *str <= '9'; str++) { - next = n*10; - if (next < n) { - /* overflow */ - return -1; + if (n >= ((uintmax_t)-1 / 10)) { + if (n > (uintmax_t)-1 / 10) + return -1; + if ((uintmax_t)(*str - '0') > ((uintmax_t)-1 % 10)) + return -1; } - n = next + (*str - '0'); + n = n * 10 + (*str - '0'); } if (*str != '\0') return -1;