@ -468,7 +468,7 @@ static int parse_unit_factor(const char *end, uintmax_t *val)
@@ -468,7 +468,7 @@ static int parse_unit_factor(const char *end, uintmax_t *val)
return 0;
}
static int git_parse_long(const char *value, long *ret)
static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
{
if (value && *value) {
char *end;
@ -480,21 +480,25 @@ static int git_parse_long(const char *value, long *ret)
@@ -480,21 +480,25 @@ static int git_parse_long(const char *value, long *ret)
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 > maximum_signed_value_of_type(long)) ||
(abs(val) > uval))
if (uval > max || abs(val) > uval) {
errno = ERANGE;
return 0;
}
val *= factor;
*ret = val;
return 1;
}
errno = EINVAL;
return 0;
}
int git_parse_ulong(const char *value, unsigned long *ret)
int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
{
if (value && *value) {
char *end;
@ -506,29 +510,75 @@ int git_parse_ulong(const char *value, unsigned long *ret)
@@ -506,29 +510,75 @@ int git_parse_ulong(const char *value, unsigned long *ret)
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 > maximum_unsigned_value_of_type(long)) ||
(oldval > val))
}
if (val > max || oldval > val) {
errno = ERANGE;
return 0;
}
*ret = val;
return 1;
}
errno = EINVAL;
return 0;
}
static void die_bad_config(const char *name)
static int git_parse_int(const char *value, int *ret)
{
intmax_t tmp;
if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int)))
return 0;
*ret = tmp;
return 1;
}
static int git_parse_int64(const char *value, int64_t *ret)
{
intmax_t tmp;
if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int64_t)))
return 0;
*ret = tmp;
return 1;
}
int git_parse_ulong(const char *value, unsigned long *ret)
{
uintmax_t tmp;
if (!git_parse_unsigned(value, &tmp, maximum_unsigned_value_of_type(long)))
return 0;
*ret = tmp;
return 1;
}
static void die_bad_number(const char *name, const char *value)
{
const char *reason = errno == ERANGE ?
"out of range" :
"invalid unit";
if (!value)
value = "";
if (cf && cf->name)
die("bad config value for '%s' in %s", name, cf->name);
die("bad config value for '%s'", name);
die("bad numeric config value '%s' for '%s' in %s: %s",
value, name, cf->name, reason);
die("bad numeric config value '%s' for '%s': %s", value, name, reason);
}
int git_config_int(const char *name, const char *value)
{
long ret = 0;
if (!git_parse_long(value, &ret))
die_bad_config(name);
int ret;
if (!git_parse_int(value, &ret))
die_bad_number(name, value);
return ret;
}
int64_t git_config_int64(const char *name, const char *value)
{
int64_t ret;
if (!git_parse_int64(value, &ret))
die_bad_number(name, value);
return ret;
}
@ -536,7 +586,7 @@ unsigned long git_config_ulong(const char *name, const char *value)
@@ -536,7 +586,7 @@ unsigned long git_config_ulong(const char *name, const char *value)
{
unsigned long ret;
if (!git_parse_ulong(value, &ret))
die_bad_config(name);
die_bad_number(name, value);
return ret;
}
@ -559,10 +609,10 @@ static int git_config_maybe_bool_text(const char *name, const char *value)
@@ -559,10 +609,10 @@ static int git_config_maybe_bool_text(const char *name, const char *value)
int git_config_maybe_bool(const char *name, const char *value)
{
long v = git_config_maybe_bool_text(name, value);
int v = git_config_maybe_bool_text(name, value);
if (0 <= v)
return v;
if (git_parse_long(value, &v))
if (git_parse_int(value, &v))
return !!v;
return -1;
}