Merge branch 'jk/config-use-size-t'

The config API made mixed uses of int and size_t types to represent
length of various pieces of text it parsed, which has been updated
to use the correct type (i.e. size_t) throughout.

* jk/config-use-size-t:
  config: reject parsing of files over INT_MAX
  config: use size_t to store parsed variable baselen
  git_config_parse_key(): return baselen as size_t
  config: drop useless length variable in write_pair()
  parse_config_key(): return subsection len as size_t
  remote: drop auto-strlen behavior of make_branch() and make_rewrite()
This commit is contained in:
Junio C Hamano 2020-04-28 15:49:58 -07:00
Родитель 2abd648b17 348482dede
Коммит 342bc9e29f
12 изменённых файлов: 56 добавлений и 50 удалений

Просмотреть файл

@ -364,7 +364,7 @@ static struct archiver **tar_filters;
static int nr_tar_filters; static int nr_tar_filters;
static int alloc_tar_filters; static int alloc_tar_filters;
static struct archiver *find_tar_filter(const char *name, int len) static struct archiver *find_tar_filter(const char *name, size_t len)
{ {
int i; int i;
for (i = 0; i < nr_tar_filters; i++) { for (i = 0; i < nr_tar_filters; i++) {
@ -380,7 +380,7 @@ static int tar_filter_config(const char *var, const char *value, void *data)
struct archiver *ar; struct archiver *ar;
const char *name; const char *name;
const char *type; const char *type;
int namelen; size_t namelen;
if (parse_config_key(var, "tar", &name, &namelen, &type) < 0 || !name) if (parse_config_key(var, "tar", &name, &namelen, &type) < 0 || !name)
return 0; return 0;

Просмотреть файл

@ -242,7 +242,7 @@ static int add_man_viewer_cmd(const char *name,
static int add_man_viewer_info(const char *var, const char *value) static int add_man_viewer_info(const char *var, const char *value)
{ {
const char *name, *subkey; const char *name, *subkey;
int namelen; size_t namelen;
if (parse_config_key(var, "man", &name, &namelen, &subkey) < 0 || !name) if (parse_config_key(var, "man", &name, &namelen, &subkey) < 0 || !name)
return 0; return 0;

Просмотреть файл

@ -459,7 +459,7 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)
static int reflog_expire_config(const char *var, const char *value, void *cb) static int reflog_expire_config(const char *var, const char *value, void *cb)
{ {
const char *pattern, *key; const char *pattern, *key;
int pattern_len; size_t pattern_len;
timestamp_t expire; timestamp_t expire;
int slot; int slot;
struct reflog_expire_cfg *ent; struct reflog_expire_cfg *ent;

Просмотреть файл

@ -37,6 +37,7 @@ struct config_source {
enum config_error_action default_error_action; enum config_error_action default_error_action;
int linenr; int linenr;
int eof; int eof;
size_t total_len;
struct strbuf value; struct strbuf value;
struct strbuf var; struct strbuf var;
unsigned subsection_case_sensitive : 1; unsigned subsection_case_sensitive : 1;
@ -309,7 +310,7 @@ int git_config_include(const char *var, const char *value, void *data)
{ {
struct config_include_data *inc = data; struct config_include_data *inc = data;
const char *cond, *key; const char *cond, *key;
int cond_len; size_t cond_len;
int ret; int ret;
/* /*
@ -358,12 +359,13 @@ static inline int iskeychar(int c)
* *
* store_key - pointer to char* which will hold a copy of the key with * store_key - pointer to char* which will hold a copy of the key with
* lowercase section and variable name * lowercase section and variable name
* baselen - pointer to int which will hold the length of the * baselen - pointer to size_t which will hold the length of the
* section + subsection part, can be NULL * section + subsection part, can be NULL
*/ */
static int git_config_parse_key_1(const char *key, char **store_key, int *baselen_, int quiet) static int git_config_parse_key_1(const char *key, char **store_key, size_t *baselen_, int quiet)
{ {
int i, dot, baselen; size_t i, baselen;
int dot;
const char *last_dot = strrchr(key, '.'); const char *last_dot = strrchr(key, '.');
/* /*
@ -425,7 +427,7 @@ out_free_ret_1:
return -CONFIG_INVALID_KEY; return -CONFIG_INVALID_KEY;
} }
int git_config_parse_key(const char *key, char **store_key, int *baselen) int git_config_parse_key(const char *key, char **store_key, size_t *baselen)
{ {
return git_config_parse_key_1(key, store_key, baselen, 0); return git_config_parse_key_1(key, store_key, baselen, 0);
} }
@ -523,6 +525,19 @@ static int get_next_char(void)
c = '\r'; c = '\r';
} }
} }
if (c != EOF && ++cf->total_len > INT_MAX) {
/*
* This is an absurdly long config file; refuse to parse
* further in order to protect downstream code from integer
* overflows. Note that we can't return an error specifically,
* but we can mark EOF and put trash in the return value,
* which will trigger a parse error.
*/
cf->eof = 1;
return 0;
}
if (c == '\n') if (c == '\n')
cf->linenr++; cf->linenr++;
if (c == EOF) { if (c == EOF) {
@ -728,7 +743,7 @@ static int git_parse_source(config_fn_t fn, void *data,
const struct config_options *opts) const struct config_options *opts)
{ {
int comment = 0; int comment = 0;
int baselen = 0; size_t baselen = 0;
struct strbuf *var = &cf->var; struct strbuf *var = &cf->var;
int error_return = 0; int error_return = 0;
char *error_msg = NULL; char *error_msg = NULL;
@ -1539,6 +1554,7 @@ static int do_config_from(struct config_source *top, config_fn_t fn, void *data,
top->prev = cf; top->prev = cf;
top->linenr = 1; top->linenr = 1;
top->eof = 0; top->eof = 0;
top->total_len = 0;
strbuf_init(&top->value, 1024); strbuf_init(&top->value, 1024);
strbuf_init(&top->var, 1024); strbuf_init(&top->var, 1024);
cf = top; cf = top;
@ -2383,7 +2399,7 @@ void git_die_config(const char *key, const char *err, ...)
*/ */
struct config_store_data { struct config_store_data {
int baselen; size_t baselen;
char *key; char *key;
int do_not_match; int do_not_match;
regex_t *value_regex; regex_t *value_regex;
@ -2509,7 +2525,7 @@ static struct strbuf store_create_section(const char *key,
const struct config_store_data *store) const struct config_store_data *store)
{ {
const char *dot; const char *dot;
int i; size_t i;
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
dot = memchr(key, '.', store->baselen); dot = memchr(key, '.', store->baselen);
@ -2522,7 +2538,9 @@ static struct strbuf store_create_section(const char *key,
} }
strbuf_addstr(&sb, "\"]\n"); strbuf_addstr(&sb, "\"]\n");
} else { } else {
strbuf_addf(&sb, "[%.*s]\n", store->baselen, key); strbuf_addch(&sb, '[');
strbuf_add(&sb, key, store->baselen);
strbuf_addstr(&sb, "]\n");
} }
return sb; return sb;
@ -2545,7 +2563,6 @@ static ssize_t write_pair(int fd, const char *key, const char *value,
{ {
int i; int i;
ssize_t ret; ssize_t ret;
int length = strlen(key + store->baselen + 1);
const char *quote = ""; const char *quote = "";
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
@ -2564,8 +2581,7 @@ static ssize_t write_pair(int fd, const char *key, const char *value,
if (i && value[i - 1] == ' ') if (i && value[i - 1] == ' ')
quote = "\""; quote = "\"";
strbuf_addf(&sb, "\t%.*s = %s", strbuf_addf(&sb, "\t%s = %s", key + store->baselen + 1, quote);
length, key + store->baselen + 1, quote);
for (i = 0; value[i]; i++) for (i = 0; value[i]; i++)
switch (value[i]) { switch (value[i]) {
@ -3238,7 +3254,7 @@ int config_error_nonbool(const char *var)
int parse_config_key(const char *var, int parse_config_key(const char *var,
const char *section, const char *section,
const char **subsection, int *subsection_len, const char **subsection, size_t *subsection_len,
const char **key) const char **key)
{ {
const char *dot; const char *dot;

Просмотреть файл

@ -254,7 +254,7 @@ int git_config_set_gently(const char *, const char *);
*/ */
void git_config_set(const char *, const char *); void git_config_set(const char *, const char *);
int git_config_parse_key(const char *, char **, int *); int git_config_parse_key(const char *, char **, size_t *);
int git_config_key_is_valid(const char *key); int git_config_key_is_valid(const char *key);
int git_config_set_multivar_gently(const char *, const char *, const char *, int); int git_config_set_multivar_gently(const char *, const char *, const char *, int);
void git_config_set_multivar(const char *, const char *, const char *, int); void git_config_set_multivar(const char *, const char *, const char *, int);
@ -359,7 +359,7 @@ int git_config_include(const char *name, const char *value, void *data);
*/ */
int parse_config_key(const char *var, int parse_config_key(const char *var,
const char *section, const char *section,
const char **subsection, int *subsection_len, const char **subsection, size_t *subsection_len,
const char **key); const char **key);
/** /**

Просмотреть файл

@ -1018,7 +1018,7 @@ static int apply_filter(const char *path, const char *src, size_t len,
static int read_convert_config(const char *var, const char *value, void *cb) static int read_convert_config(const char *var, const char *value, void *cb)
{ {
const char *key, *name; const char *key, *name;
int namelen; size_t namelen;
struct convert_driver *drv; struct convert_driver *drv;
/* /*

2
fsck.c
Просмотреть файл

@ -1065,7 +1065,7 @@ static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
{ {
struct fsck_gitmodules_data *data = vdata; struct fsck_gitmodules_data *data = vdata;
const char *subsection, *key; const char *subsection, *key;
int subsection_len; size_t subsection_len;
char *name; char *name;
if (parse_config_key(var, "submodule", &subsection, &subsection_len, &key) < 0 || if (parse_config_key(var, "submodule", &subsection, &subsection_len, &key) < 0 ||

Просмотреть файл

@ -247,7 +247,7 @@ static int read_merge_config(const char *var, const char *value, void *cb)
{ {
struct ll_merge_driver *fn; struct ll_merge_driver *fn;
const char *key, *name; const char *key, *name;
int namelen; size_t namelen;
if (!strcmp(var, "merge.default")) if (!strcmp(var, "merge.default"))
return git_config_string(&default_ll_merge, var, value); return git_config_string(&default_ll_merge, var, value);

Просмотреть файл

@ -101,7 +101,7 @@ static void promisor_remote_move_to_tail(struct promisor_remote *r,
static int promisor_remote_config(const char *var, const char *value, void *data) static int promisor_remote_config(const char *var, const char *value, void *data)
{ {
const char *name; const char *name;
int namelen; size_t namelen;
const char *subkey; const char *subkey;
if (!strcmp(var, "core.partialclonefilter")) if (!strcmp(var, "core.partialclonefilter"))

Просмотреть файл

@ -174,54 +174,43 @@ static void add_merge(struct branch *branch, const char *name)
branch->merge_name[branch->merge_nr++] = name; branch->merge_name[branch->merge_nr++] = name;
} }
static struct branch *make_branch(const char *name, int len) static struct branch *make_branch(const char *name, size_t len)
{ {
struct branch *ret; struct branch *ret;
int i; int i;
for (i = 0; i < branches_nr; i++) { for (i = 0; i < branches_nr; i++) {
if (len ? (!strncmp(name, branches[i]->name, len) && if (!strncmp(name, branches[i]->name, len) &&
!branches[i]->name[len]) : !branches[i]->name[len])
!strcmp(name, branches[i]->name))
return branches[i]; return branches[i];
} }
ALLOC_GROW(branches, branches_nr + 1, branches_alloc); ALLOC_GROW(branches, branches_nr + 1, branches_alloc);
ret = xcalloc(1, sizeof(struct branch)); ret = xcalloc(1, sizeof(struct branch));
branches[branches_nr++] = ret; branches[branches_nr++] = ret;
if (len) ret->name = xstrndup(name, len);
ret->name = xstrndup(name, len);
else
ret->name = xstrdup(name);
ret->refname = xstrfmt("refs/heads/%s", ret->name); ret->refname = xstrfmt("refs/heads/%s", ret->name);
return ret; return ret;
} }
static struct rewrite *make_rewrite(struct rewrites *r, const char *base, int len) static struct rewrite *make_rewrite(struct rewrites *r,
const char *base, size_t len)
{ {
struct rewrite *ret; struct rewrite *ret;
int i; int i;
for (i = 0; i < r->rewrite_nr; i++) { for (i = 0; i < r->rewrite_nr; i++) {
if (len if (len == r->rewrite[i]->baselen &&
? (len == r->rewrite[i]->baselen && !strncmp(base, r->rewrite[i]->base, len))
!strncmp(base, r->rewrite[i]->base, len))
: !strcmp(base, r->rewrite[i]->base))
return r->rewrite[i]; return r->rewrite[i];
} }
ALLOC_GROW(r->rewrite, r->rewrite_nr + 1, r->rewrite_alloc); ALLOC_GROW(r->rewrite, r->rewrite_nr + 1, r->rewrite_alloc);
ret = xcalloc(1, sizeof(struct rewrite)); ret = xcalloc(1, sizeof(struct rewrite));
r->rewrite[r->rewrite_nr++] = ret; r->rewrite[r->rewrite_nr++] = ret;
if (len) { ret->base = xstrndup(base, len);
ret->base = xstrndup(base, len); ret->baselen = len;
ret->baselen = len;
}
else {
ret->base = xstrdup(base);
ret->baselen = strlen(base);
}
return ret; return ret;
} }
@ -316,7 +305,7 @@ static void read_branches_file(struct remote *remote)
static int handle_config(const char *key, const char *value, void *cb) static int handle_config(const char *key, const char *value, void *cb)
{ {
const char *name; const char *name;
int namelen; size_t namelen;
const char *subkey; const char *subkey;
struct remote *remote; struct remote *remote;
struct branch *branch; struct branch *branch;
@ -470,7 +459,7 @@ static void read_config(void)
const char *head_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flag); const char *head_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flag);
if (head_ref && (flag & REF_ISSYMREF) && if (head_ref && (flag & REF_ISSYMREF) &&
skip_prefix(head_ref, "refs/heads/", &head_ref)) { skip_prefix(head_ref, "refs/heads/", &head_ref)) {
current_branch = make_branch(head_ref, 0); current_branch = make_branch(head_ref, strlen(head_ref));
} }
} }
git_config(handle_config, NULL); git_config(handle_config, NULL);
@ -1584,7 +1573,7 @@ struct branch *branch_get(const char *name)
if (!name || !*name || !strcmp(name, "HEAD")) if (!name || !*name || !strcmp(name, "HEAD"))
ret = current_branch; ret = current_branch;
else else
ret = make_branch(name, 0); ret = make_branch(name, strlen(name));
set_merge(ret); set_merge(ret);
return ret; return ret;
} }

Просмотреть файл

@ -225,7 +225,8 @@ static int name_and_item_from_var(const char *var, struct strbuf *name,
struct strbuf *item) struct strbuf *item)
{ {
const char *subsection, *key; const char *subsection, *key;
int subsection_len, parse; size_t subsection_len;
int parse;
parse = parse_config_key(var, "submodule", &subsection, parse = parse_config_key(var, "submodule", &subsection,
&subsection_len, &key); &subsection_len, &key);
if (parse < 0 || !subsection) if (parse < 0 || !subsection)

Просмотреть файл

@ -222,7 +222,7 @@ static struct userdiff_driver driver_false = {
{ NULL, 0 } { NULL, 0 }
}; };
static struct userdiff_driver *userdiff_find_by_namelen(const char *k, int len) static struct userdiff_driver *userdiff_find_by_namelen(const char *k, size_t len)
{ {
int i; int i;
for (i = 0; i < ndrivers; i++) { for (i = 0; i < ndrivers; i++) {
@ -266,7 +266,7 @@ int userdiff_config(const char *k, const char *v)
{ {
struct userdiff_driver *drv; struct userdiff_driver *drv;
const char *name, *type; const char *name, *type;
int namelen; size_t namelen;
if (parse_config_key(k, "diff", &name, &namelen, &type) || !name) if (parse_config_key(k, "diff", &name, &namelen, &type) || !name)
return 0; return 0;