diff --git a/src/dehumanize_number.c b/src/dehumanize_number.c index 640f1fb..632bf1d 100644 --- a/src/dehumanize_number.c +++ b/src/dehumanize_number.c @@ -1,5 +1,5 @@ /* - * Copyright © 2012 Guillem Jover + * Copyright © 2012-2013 Guillem Jover * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,8 +35,8 @@ int dehumanize_number(const char *buf, int64_t *num) { - uint64_t rval; - int sign = 1; + uint64_t rval, rmax; + int sign = +1; int rc; /* The current expand_number() implementation uses bit shifts, so @@ -52,7 +52,13 @@ dehumanize_number(const char *buf, int64_t *num) rc = expand_number(buf, &rval); if (rc < 0) return rc; - if (rval == UINT64_MAX && sign == -1) { + + /* The sign has been stripped, so rval has the absolute value. + * Error out, regardless of the sign, if rval is greater than + * abs(INT64_MIN) (== INT64_MAX + 1), or if the sign is positive + * and the value has overflown by one (INT64_MAX + 1). */ + rmax = INT64_MAX + 1ULL; + if (rval > rmax || (rval == rmax && sign == +1)) { errno = ERANGE; return -1; } diff --git a/test/humanize.c b/test/humanize.c index 0e8f0cf..59e4cde 100644 --- a/test/humanize.c +++ b/test/humanize.c @@ -25,6 +25,7 @@ */ #include +#include #include int @@ -60,5 +61,17 @@ main(int argc, char **argv) assert(dehumanize_number("-3G", &val) == 0); assert(val == -3221225472LL); + assert(dehumanize_number("9223372036854775807", &val) == 0); + assert(val == INT64_MAX); + + assert(dehumanize_number("9223372036854775808", &val) == -1); + assert(errno == ERANGE); + + assert(dehumanize_number("-9223372036854775808", &val) == 0); + assert(val == INT64_MIN); + + assert(dehumanize_number("-9223372036854775809", &val) == -1); + assert(errno == ERANGE); + return 0; }