From e3eed7f8d238e895922851315447f5df9c475f11 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 2 Nov 2011 15:46:22 +0000 Subject: Add strtoimax() compatibility function. Since systems that omit strtoumax() will likely omit strtomax() too, and likewise for strtoull() and strtoll(), we arrange for the make variables NO_STRTOUMAX and NO_STRTOULL to cover both the signed and unsigned functions, and define compatibility implementations for them. Signed-off-by: Nick Alcock Signed-off-by: Junio C Hamano --- Makefile | 6 +++--- compat/strtoimax.c | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 compat/strtoimax.c diff --git a/Makefile b/Makefile index e40ac0c7f5..c5c1fd7ab0 100644 --- a/Makefile +++ b/Makefile @@ -57,8 +57,8 @@ all:: # # Define NO_STRLCPY if you don't have strlcpy. # -# Define NO_STRTOUMAX if you don't have strtoumax in the C library. -# If your compiler also does not support long long or does not have +# Define NO_STRTOUMAX if you don't have both strtoimax and strtoumax in the +# C library. If your compiler also does not support long long or does not have # strtoull, define NO_STRTOULL. # # Define NO_SETENV if you don't have setenv in the C library. @@ -1402,7 +1402,7 @@ ifdef NO_STRLCPY endif ifdef NO_STRTOUMAX COMPAT_CFLAGS += -DNO_STRTOUMAX - COMPAT_OBJS += compat/strtoumax.o + COMPAT_OBJS += compat/strtoumax.o compat/strtoimax.o endif ifdef NO_STRTOULL COMPAT_CFLAGS += -DNO_STRTOULL diff --git a/compat/strtoimax.c b/compat/strtoimax.c new file mode 100644 index 0000000000..ac09ed89e7 --- /dev/null +++ b/compat/strtoimax.c @@ -0,0 +1,10 @@ +#include "../git-compat-util.h" + +intmax_t gitstrtoimax (const char *nptr, char **endptr, int base) +{ +#if defined(NO_STRTOULL) + return strtol(nptr, endptr, base); +#else + return strtoll(nptr, endptr, base); +#endif +} -- cgit v1.2.3 From 97000ba6e21d25581222e11c36db4bb88c05adcd Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sat, 5 Nov 2011 16:37:34 +0100 Subject: Compatibility: declare strtoimax() under NO_STRTOUMAX The previous one introduced an implementation of the function, but forgot to add a declaration. Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- git-compat-util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/git-compat-util.h b/git-compat-util.h index e0bb81ed8d..23f760331f 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -345,6 +345,8 @@ extern size_t gitstrlcpy(char *, const char *, size_t); #ifdef NO_STRTOUMAX #define strtoumax gitstrtoumax extern uintmax_t gitstrtoumax(const char *, char **, int); +#define strtoimax gitstrtoimax +extern intmax_t gitstrtoimax(const char *, char **, int); #endif #ifdef NO_STRTOK_R -- cgit v1.2.3 From ebaa1bd407745c4b4c1c0f20c322929fc4371467 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 2 Nov 2011 15:46:23 +0000 Subject: Support sizes >=2G in various config options accepting 'g' sizes. The config options core.packedGitWindowSize, core.packedGitLimit, core.deltaBaseCacheLimit, core.bigFileThreshold, pack.windowMemory and pack.packSizeLimit all claim to support suffixes up to and including 'g'. This implies that they should accept sizes >=2G on 64-bit systems: certainly, specifying a size of 3g should not silently be translated to zero or transformed into a large negative value due to integer overflow. However, due to use of git_config_int() rather than git_config_ulong(), that is exactly what happens: % git config core.bigFileThreshold 2g % git gc --aggressive # with extra debugging code to print out # core.bigfilethreshold after parsing bigfilethreshold: -2147483648 [...] This is probably irrelevant for core.deltaBaseCacheLimit, but is problematic for the other values. (It is particularly problematic for core.packedGitLimit, which can't even be set to its default value in the config file due to this bug.) This fixes things for 32-bit platforms as well. They get the usual bad config error if an overlarge value is specified, e.g.: fatal: bad config value for 'core.bigfilethreshold' in /home/nix/.gitconfig This is detected in all cases, even if the 32-bit platform has no size larger than 'long'. For signed integral configuration values, we also detect the case where the value is too large for the signed type but not the unsigned type. Signed-off-by: Nick Alcock Signed-off-by: Junio C Hamano --- config.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/config.c b/config.c index e0b3b80d92..43aa456be1 100644 --- a/config.c +++ b/config.c @@ -326,7 +326,7 @@ static int git_parse_file(config_fn_t fn, void *data) die("bad config file line %d in %s", config_linenr, config_file_name); } -static int parse_unit_factor(const char *end, unsigned long *val) +static int parse_unit_factor(const char *end, uintmax_t *val) { if (!*end) return 1; @@ -349,11 +349,23 @@ static int git_parse_long(const char *value, long *ret) { if (value && *value) { char *end; - long val = strtol(value, &end, 0); - unsigned long factor = 1; + intmax_t val; + uintmax_t uval; + uintmax_t factor = 1; + + errno = 0; + val = strtoimax(value, &end, 0); + if (errno == ERANGE) + return 0; if (!parse_unit_factor(end, &factor)) return 0; - *ret = val * factor; + uval = abs(val); + uval *= factor; + if ((uval > maximum_signed_value_of_type(long)) || + (abs(val) > uval)) + return 0; + val *= factor; + *ret = val; return 1; } return 0; @@ -363,9 +375,19 @@ int git_parse_ulong(const char *value, unsigned long *ret) { if (value && *value) { char *end; - unsigned long val = strtoul(value, &end, 0); + uintmax_t val; + uintmax_t oldval; + + errno = 0; + val = strtoumax(value, &end, 0); + if (errno == ERANGE) + return 0; + oldval = val; if (!parse_unit_factor(end, &val)) return 0; + if ((val > maximum_unsigned_value_of_type(long)) || + (oldval > val)) + return 0; *ret = val; return 1; } @@ -543,7 +565,7 @@ static int git_default_core_config(const char *var, const char *value) if (!strcmp(var, "core.packedgitwindowsize")) { int pgsz_x2 = getpagesize() * 2; - packed_git_window_size = git_config_int(var, value); + packed_git_window_size = git_config_ulong(var, value); /* This value must be multiple of (pagesize * 2) */ packed_git_window_size /= pgsz_x2; @@ -554,18 +576,17 @@ static int git_default_core_config(const char *var, const char *value) } if (!strcmp(var, "core.bigfilethreshold")) { - long n = git_config_int(var, value); - big_file_threshold = 0 < n ? n : 0; + big_file_threshold = git_config_ulong(var, value); return 0; } if (!strcmp(var, "core.packedgitlimit")) { - packed_git_limit = git_config_int(var, value); + packed_git_limit = git_config_ulong(var, value); return 0; } if (!strcmp(var, "core.deltabasecachelimit")) { - delta_base_cache_limit = git_config_int(var, value); + delta_base_cache_limit = git_config_ulong(var, value); return 0; } -- cgit v1.2.3