When we are parsing an integer or unsigned long, we use the strto*max functions, which properly set errno to ERANGE if we get a large value. However, we also do further range checks after applying our multiplication factor, but do not set ERANGE. This means that a caller cannot tell if an error was caused by ERANGE or if the input was simply not a valid number. This patch teaches git_parse_signed and git_parse_unsigned reliably set ERANGE for range errors, and EINVAL for other errors. Signed-off-by: Jeff King <peff@xxxxxxxx> --- I'm a little iffy on using errno like this. The "normal" way in git would be to return an enum like: enum config_parse_error { CONFIG_PARSE_SUCCESS = 0, CONFIG_PARSE_RANGE = -1, CONFIG_PARSE_INVALID_UNIT = -2 }; But that would be changing the return semantics of git_parse_ulong (which currently is "0" for fail, "1" for success) without changing its signature. I figured this was the path of least resistance since we already get ERANGE out of strtoimax, but I'm happy to switch it, too. config.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/config.c b/config.c index 0a65ac2..7332b06 100644 --- a/config.c +++ b/config.c @@ -480,16 +480,21 @@ static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max) val = strtoimax(value, &end, 0); if (errno == ERANGE) return 0; - if (!parse_unit_factor(end, &factor)) + if (!parse_unit_factor(end, &factor)) { + errno = EINVAL; return 0; + } uval = abs(val); uval *= factor; - if (uval > max || abs(val) > uval) + if (uval > max || abs(val) > uval) { + errno = ERANGE; return 0; + } val *= factor; *ret = val; return 1; } + errno = EINVAL; return 0; } @@ -505,13 +510,18 @@ int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max) if (errno == ERANGE) return 0; oldval = val; - if (!parse_unit_factor(end, &val)) + if (!parse_unit_factor(end, &val)) { + errno = EINVAL; return 0; - if (val > max || oldval > val) + } + if (val > max || oldval > val) { + errno = ERANGE; return 0; + } *ret = val; return 1; } + errno = EINVAL; return 0; } -- 1.8.4.2.g87d4a77 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html