config: set errno in numeric git_parse_* functions

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 to set ERANGE for range errors, and EINVAL for other errors, so that the caller can reliably tell these cases apart. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Sep 8, 2013 at 04:36 UTC 33fdd77e2b8ece3490982f9a35c8669d16879ba8
1 file changed +14 -4
config.c
+14 -4
@@ -480,16 +480,21 @@ static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
480 val = strtoimax(value, &end, 0);
481 if (errno == ERANGE)
482 return 0;
483 - if (!parse_unit_factor(end, &factor))
483 + if (!parse_unit_factor(end, &factor)) {
484 + errno = EINVAL;
485 return 0;
486 + }
487 uval = abs(val);
488 uval *= factor;
487 - if (uval > max || abs(val) > uval)
489 + if (uval > max || abs(val) > uval) {
490 + errno = ERANGE;
491 return 0;
492 + }
493 val *= factor;
494 *ret = val;
495 return 1;
496 }
497 + errno = EINVAL;
498 return 0;
499 }
500
@@ -505,13 +510,18 @@ int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
510 if (errno == ERANGE)
511 return 0;
512 oldval = val;
508 - if (!parse_unit_factor(end, &val))
513 + if (!parse_unit_factor(end, &val)) {
514 + errno = EINVAL;
515 return 0;
510 - if (val > max || oldval > val)
516 + }
517 + if (val > max || oldval > val) {
518 + errno = ERANGE;
519 return 0;
520 + }
521 *ret = val;
522 return 1;
523 }
524 + errno = EINVAL;
525 return 0;
526 }
527