Merge branch 'rs/config-unit-parsing'
authorJunio C Hamano <gitster@pobox.com>
Tue, 9 Jul 2019 22:25:41 +0000 (15:25 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 9 Jul 2019 22:25:41 +0000 (15:25 -0700)
The code to parse scaled numbers out of configuration files has
been made more robust and also easier to follow.

* rs/config-unit-parsing:
config: simplify parsing of unit factors
config: don't multiply in parse_unit_factor()
config: use unsigned_mult_overflows to check for overflows

1  2 
config.c
diff --combined config.c
index 972d3c10335bcf918e8393099031769b263e5b77,26196bdccfbc268d7ee669546d39a15e14703494..faa57e436cf4fc6d84580f3940bafdb4896c7658
+++ b/config.c
@@@ -19,7 -19,6 +19,7 @@@
  #include "utf8.h"
  #include "dir.h"
  #include "color.h"
 +#include "refs.h"
  
  struct config_source {
        struct config_source *prev;
@@@ -171,12 -170,6 +171,12 @@@ static int handle_path_include(const ch
        return ret;
  }
  
 +static void add_trailing_starstar_for_dir(struct strbuf *pat)
 +{
 +      if (pat->len && is_dir_sep(pat->buf[pat->len - 1]))
 +              strbuf_addstr(pat, "**");
 +}
 +
  static int prepare_include_condition_pattern(struct strbuf *pat)
  {
        struct strbuf path = STRBUF_INIT;
        } else if (!is_absolute_path(pat->buf))
                strbuf_insert(pat, 0, "**/", 3);
  
 -      if (pat->len && is_dir_sep(pat->buf[pat->len - 1]))
 -              strbuf_addstr(pat, "**");
 +      add_trailing_starstar_for_dir(pat);
  
        strbuf_release(&path);
        return prefix;
@@@ -270,25 -264,6 +270,25 @@@ done
        return ret;
  }
  
 +static int include_by_branch(const char *cond, size_t cond_len)
 +{
 +      int flags;
 +      int ret;
 +      struct strbuf pattern = STRBUF_INIT;
 +      const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
 +      const char *shortname;
 +
 +      if (!refname || !(flags & REF_ISSYMREF) ||
 +                      !skip_prefix(refname, "refs/heads/", &shortname))
 +              return 0;
 +
 +      strbuf_add(&pattern, cond, cond_len);
 +      add_trailing_starstar_for_dir(&pattern);
 +      ret = !wildmatch(pattern.buf, shortname, WM_PATHNAME);
 +      strbuf_release(&pattern);
 +      return ret;
 +}
 +
  static int include_condition_is_true(const struct config_options *opts,
                                     const char *cond, size_t cond_len)
  {
                return include_by_gitdir(opts, cond, cond_len, 0);
        else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len))
                return include_by_gitdir(opts, cond, cond_len, 1);
 +      else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len))
 +              return include_by_branch(cond, cond_len);
  
        /* unknown conditionals are always false */
        return 0;
@@@ -861,22 -834,16 +861,16 @@@ static int git_parse_source(config_fn_
        return error_return;
  }
  
- static int parse_unit_factor(const char *end, uintmax_t *val)
+ static uintmax_t get_unit_factor(const char *end)
  {
        if (!*end)
                return 1;
-       else if (!strcasecmp(end, "k")) {
-               *val *= 1024;
-               return 1;
-       }
-       else if (!strcasecmp(end, "m")) {
-               *val *= 1024 * 1024;
-               return 1;
-       }
-       else if (!strcasecmp(end, "g")) {
-               *val *= 1024 * 1024 * 1024;
-               return 1;
-       }
+       else if (!strcasecmp(end, "k"))
+               return 1024;
+       else if (!strcasecmp(end, "m"))
+               return 1024 * 1024;
+       else if (!strcasecmp(end, "g"))
+               return 1024 * 1024 * 1024;
        return 0;
  }
  
@@@ -886,19 -853,20 +880,20 @@@ static int git_parse_signed(const char 
                char *end;
                intmax_t val;
                uintmax_t uval;
-               uintmax_t factor = 1;
+               uintmax_t factor;
  
                errno = 0;
                val = strtoimax(value, &end, 0);
                if (errno == ERANGE)
                        return 0;
-               if (!parse_unit_factor(end, &factor)) {
+               factor = get_unit_factor(end);
+               if (!factor) {
                        errno = EINVAL;
                        return 0;
                }
                uval = val < 0 ? -val : val;
-               uval *= factor;
-               if (uval > max || (val < 0 ? -val : val) > uval) {
+               if (unsigned_mult_overflows(factor, uval) ||
+                   factor * uval > max) {
                        errno = ERANGE;
                        return 0;
                }
@@@ -915,21 -883,23 +910,23 @@@ static int git_parse_unsigned(const cha
        if (value && *value) {
                char *end;
                uintmax_t val;
-               uintmax_t oldval;
+               uintmax_t factor;
  
                errno = 0;
                val = strtoumax(value, &end, 0);
                if (errno == ERANGE)
                        return 0;
-               oldval = val;
-               if (!parse_unit_factor(end, &val)) {
+               factor = get_unit_factor(end);
+               if (!factor) {
                        errno = EINVAL;
                        return 0;
                }
-               if (val > max || oldval > val) {
+               if (unsigned_mult_overflows(factor, val) ||
+                   factor * val > max) {
                        errno = ERANGE;
                        return 0;
                }
+               val *= factor;
                *ret = val;
                return 1;
        }