config: factor out integer parsing from range checks

When we are parsing integers for config, we use an intmax_t (or uintmax_t) internally, and then check against the size of our result type at the end. We can parameterize the maximum representable value, which will let us re-use the parsing code for a variety of range checks. Unfortunately, we cannot combine the signed and unsigned parsing functions easily, as we have to rely on the signed and unsigned C types internally. 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:29 UTC 7192777d226c5b8653c65112a309c2ebd3d6d5c5
1 file changed +22 -6
config.c
+22 -6
@@ -468,7 +468,7 @@ static int parse_unit_factor(const char *end, uintmax_t *val)
468 return 0;
469 }
470
471 -static int git_parse_long(const char *value, long *ret)
471 +static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
472 {
473 if (value && *value) {
474 char *end;
@@ -484,8 +484,7 @@ static int git_parse_long(const char *value, long *ret)
484 return 0;
485 uval = abs(val);
486 uval *= factor;
487 - if ((uval > maximum_signed_value_of_type(long)) ||
488 - (abs(val) > uval))
487 + if (uval > max || abs(val) > uval)
488 return 0;
489 val *= factor;
490 *ret = val;
@@ -494,7 +493,7 @@ static int git_parse_long(const char *value, long *ret)
493 return 0;
494 }
495
497 -int git_parse_ulong(const char *value, unsigned long *ret)
496 +int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
497 {
498 if (value && *value) {
499 char *end;
@@ -508,8 +507,7 @@ int git_parse_ulong(const char *value, unsigned long *ret)
507 oldval = val;
508 if (!parse_unit_factor(end, &val))
509 return 0;
511 - if ((val > maximum_unsigned_value_of_type(long)) ||
512 - (oldval > val))
510 + if (val > max || oldval > val)
511 return 0;
512 *ret = val;
513 return 1;
@@ -517,6 +515,24 @@ int git_parse_ulong(const char *value, unsigned long *ret)
515 return 0;
516 }
517
518 +static int git_parse_long(const char *value, long *ret)
519 +{
520 + intmax_t tmp;
521 + if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(long)))
522 + return 0;
523 + *ret = tmp;
524 + return 1;
525 +}
526 +
527 +int git_parse_ulong(const char *value, unsigned long *ret)
528 +{
529 + uintmax_t tmp;
530 + if (!git_parse_unsigned(value, &tmp, maximum_unsigned_value_of_type(long)))
531 + return 0;
532 + *ret = tmp;
533 + return 1;
534 +}
535 +
536 static void die_bad_config(const char *name)
537 {
538 if (cf && cf->name)