Merge branch 'jk/fsck-gitmodules-gently'
Recent "security fix" to pay attention to contents of ".gitmodules" while accepting "git push" was a bit overly strict than necessary, which has been adjusted. * jk/fsck-gitmodules-gently: fsck: downgrade gitmodulesParse default to "info" fsck: split ".gitmodules too large" error from parse failure fsck: silence stderr when parsing .gitmodules config: add options parameter to git_config_from_mem config: add CONFIG_ERROR_SILENT handler config: turn die_on_error into caller-facing enum
This commit is contained in:
32
config.c
32
config.c
@ -32,7 +32,7 @@ struct config_source {
|
|||||||
enum config_origin_type origin_type;
|
enum config_origin_type origin_type;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *path;
|
const char *path;
|
||||||
int die_on_error;
|
enum config_error_action default_error_action;
|
||||||
int linenr;
|
int linenr;
|
||||||
int eof;
|
int eof;
|
||||||
struct strbuf value;
|
struct strbuf value;
|
||||||
@ -810,10 +810,21 @@ static int git_parse_source(config_fn_t fn, void *data,
|
|||||||
cf->linenr, cf->name);
|
cf->linenr, cf->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cf->die_on_error)
|
switch (opts && opts->error_action ?
|
||||||
|
opts->error_action :
|
||||||
|
cf->default_error_action) {
|
||||||
|
case CONFIG_ERROR_DIE:
|
||||||
die("%s", error_msg);
|
die("%s", error_msg);
|
||||||
else
|
break;
|
||||||
|
case CONFIG_ERROR_ERROR:
|
||||||
error_return = error("%s", error_msg);
|
error_return = error("%s", error_msg);
|
||||||
|
break;
|
||||||
|
case CONFIG_ERROR_SILENT:
|
||||||
|
error_return = -1;
|
||||||
|
break;
|
||||||
|
case CONFIG_ERROR_UNSET:
|
||||||
|
BUG("config error action unset");
|
||||||
|
}
|
||||||
|
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
return error_return;
|
return error_return;
|
||||||
@ -1521,7 +1532,7 @@ static int do_config_from_file(config_fn_t fn,
|
|||||||
top.origin_type = origin_type;
|
top.origin_type = origin_type;
|
||||||
top.name = name;
|
top.name = name;
|
||||||
top.path = path;
|
top.path = path;
|
||||||
top.die_on_error = 1;
|
top.default_error_action = CONFIG_ERROR_DIE;
|
||||||
top.do_fgetc = config_file_fgetc;
|
top.do_fgetc = config_file_fgetc;
|
||||||
top.do_ungetc = config_file_ungetc;
|
top.do_ungetc = config_file_ungetc;
|
||||||
top.do_ftell = config_file_ftell;
|
top.do_ftell = config_file_ftell;
|
||||||
@ -1559,8 +1570,10 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
|
|||||||
return git_config_from_file_with_options(fn, filename, data, NULL);
|
return git_config_from_file_with_options(fn, filename, data, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_from_mem(config_fn_t fn, const enum config_origin_type origin_type,
|
int git_config_from_mem(config_fn_t fn,
|
||||||
const char *name, const char *buf, size_t len, void *data)
|
const enum config_origin_type origin_type,
|
||||||
|
const char *name, const char *buf, size_t len,
|
||||||
|
void *data, const struct config_options *opts)
|
||||||
{
|
{
|
||||||
struct config_source top;
|
struct config_source top;
|
||||||
|
|
||||||
@ -1570,12 +1583,12 @@ int git_config_from_mem(config_fn_t fn, const enum config_origin_type origin_typ
|
|||||||
top.origin_type = origin_type;
|
top.origin_type = origin_type;
|
||||||
top.name = name;
|
top.name = name;
|
||||||
top.path = NULL;
|
top.path = NULL;
|
||||||
top.die_on_error = 0;
|
top.default_error_action = CONFIG_ERROR_ERROR;
|
||||||
top.do_fgetc = config_buf_fgetc;
|
top.do_fgetc = config_buf_fgetc;
|
||||||
top.do_ungetc = config_buf_ungetc;
|
top.do_ungetc = config_buf_ungetc;
|
||||||
top.do_ftell = config_buf_ftell;
|
top.do_ftell = config_buf_ftell;
|
||||||
|
|
||||||
return do_config_from(&top, fn, data, NULL);
|
return do_config_from(&top, fn, data, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_from_blob_oid(config_fn_t fn,
|
int git_config_from_blob_oid(config_fn_t fn,
|
||||||
@ -1596,7 +1609,8 @@ int git_config_from_blob_oid(config_fn_t fn,
|
|||||||
return error("reference '%s' does not point to a blob", name);
|
return error("reference '%s' does not point to a blob", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size, data);
|
ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size,
|
||||||
|
data, NULL);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
13
config.h
13
config.h
@ -54,6 +54,12 @@ struct config_options {
|
|||||||
const char *git_dir;
|
const char *git_dir;
|
||||||
config_parser_event_fn_t event_fn;
|
config_parser_event_fn_t event_fn;
|
||||||
void *event_fn_data;
|
void *event_fn_data;
|
||||||
|
enum config_error_action {
|
||||||
|
CONFIG_ERROR_UNSET = 0, /* use source-specific default */
|
||||||
|
CONFIG_ERROR_DIE, /* die() on error */
|
||||||
|
CONFIG_ERROR_ERROR, /* error() on error, return -1 */
|
||||||
|
CONFIG_ERROR_SILENT, /* return -1 */
|
||||||
|
} error_action;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int (*config_fn_t)(const char *, const char *, void *);
|
typedef int (*config_fn_t)(const char *, const char *, void *);
|
||||||
@ -62,8 +68,11 @@ extern int git_config_from_file(config_fn_t fn, const char *, void *);
|
|||||||
extern int git_config_from_file_with_options(config_fn_t fn, const char *,
|
extern int git_config_from_file_with_options(config_fn_t fn, const char *,
|
||||||
void *,
|
void *,
|
||||||
const struct config_options *);
|
const struct config_options *);
|
||||||
extern int git_config_from_mem(config_fn_t fn, const enum config_origin_type,
|
extern int git_config_from_mem(config_fn_t fn,
|
||||||
const char *name, const char *buf, size_t len, void *data);
|
const enum config_origin_type,
|
||||||
|
const char *name,
|
||||||
|
const char *buf, size_t len,
|
||||||
|
void *data, const struct config_options *opts);
|
||||||
extern int git_config_from_blob_oid(config_fn_t fn, const char *name,
|
extern int git_config_from_blob_oid(config_fn_t fn, const char *name,
|
||||||
const struct object_id *oid, void *data);
|
const struct object_id *oid, void *data);
|
||||||
extern void git_config_push_parameter(const char *text);
|
extern void git_config_push_parameter(const char *text);
|
||||||
|
9
fsck.c
9
fsck.c
@ -63,7 +63,7 @@ static struct oidset gitmodules_done = OIDSET_INIT;
|
|||||||
FUNC(ZERO_PADDED_DATE, ERROR) \
|
FUNC(ZERO_PADDED_DATE, ERROR) \
|
||||||
FUNC(GITMODULES_MISSING, ERROR) \
|
FUNC(GITMODULES_MISSING, ERROR) \
|
||||||
FUNC(GITMODULES_BLOB, ERROR) \
|
FUNC(GITMODULES_BLOB, ERROR) \
|
||||||
FUNC(GITMODULES_PARSE, ERROR) \
|
FUNC(GITMODULES_LARGE, ERROR) \
|
||||||
FUNC(GITMODULES_NAME, ERROR) \
|
FUNC(GITMODULES_NAME, ERROR) \
|
||||||
FUNC(GITMODULES_SYMLINK, ERROR) \
|
FUNC(GITMODULES_SYMLINK, ERROR) \
|
||||||
/* warnings */ \
|
/* warnings */ \
|
||||||
@ -77,6 +77,7 @@ static struct oidset gitmodules_done = OIDSET_INIT;
|
|||||||
FUNC(ZERO_PADDED_FILEMODE, WARN) \
|
FUNC(ZERO_PADDED_FILEMODE, WARN) \
|
||||||
FUNC(NUL_IN_COMMIT, WARN) \
|
FUNC(NUL_IN_COMMIT, WARN) \
|
||||||
/* infos (reported as warnings, but ignored by default) */ \
|
/* infos (reported as warnings, but ignored by default) */ \
|
||||||
|
FUNC(GITMODULES_PARSE, INFO) \
|
||||||
FUNC(BAD_TAG_NAME, INFO) \
|
FUNC(BAD_TAG_NAME, INFO) \
|
||||||
FUNC(MISSING_TAGGER_ENTRY, INFO)
|
FUNC(MISSING_TAGGER_ENTRY, INFO)
|
||||||
|
|
||||||
@ -999,6 +1000,7 @@ static int fsck_blob(struct blob *blob, const char *buf,
|
|||||||
unsigned long size, struct fsck_options *options)
|
unsigned long size, struct fsck_options *options)
|
||||||
{
|
{
|
||||||
struct fsck_gitmodules_data data;
|
struct fsck_gitmodules_data data;
|
||||||
|
struct config_options config_opts = { 0 };
|
||||||
|
|
||||||
if (!oidset_contains(&gitmodules_found, &blob->object.oid))
|
if (!oidset_contains(&gitmodules_found, &blob->object.oid))
|
||||||
return 0;
|
return 0;
|
||||||
@ -1014,15 +1016,16 @@ static int fsck_blob(struct blob *blob, const char *buf,
|
|||||||
* that an error.
|
* that an error.
|
||||||
*/
|
*/
|
||||||
return report(options, &blob->object,
|
return report(options, &blob->object,
|
||||||
FSCK_MSG_GITMODULES_PARSE,
|
FSCK_MSG_GITMODULES_LARGE,
|
||||||
".gitmodules too large to parse");
|
".gitmodules too large to parse");
|
||||||
}
|
}
|
||||||
|
|
||||||
data.obj = &blob->object;
|
data.obj = &blob->object;
|
||||||
data.options = options;
|
data.options = options;
|
||||||
data.ret = 0;
|
data.ret = 0;
|
||||||
|
config_opts.error_action = CONFIG_ERROR_SILENT;
|
||||||
if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
|
if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
|
||||||
".gitmodules", buf, size, &data))
|
".gitmodules", buf, size, &data, &config_opts))
|
||||||
data.ret |= report(options, &blob->object,
|
data.ret |= report(options, &blob->object,
|
||||||
FSCK_MSG_GITMODULES_PARSE,
|
FSCK_MSG_GITMODULES_PARSE,
|
||||||
"could not parse gitmodules blob");
|
"could not parse gitmodules blob");
|
||||||
|
@ -562,7 +562,7 @@ static const struct submodule *config_from(struct submodule_cache *cache,
|
|||||||
parameter.gitmodules_oid = &oid;
|
parameter.gitmodules_oid = &oid;
|
||||||
parameter.overwrite = 0;
|
parameter.overwrite = 0;
|
||||||
git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
|
git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
|
||||||
config, config_size, ¶meter);
|
config, config_size, ¶meter, NULL);
|
||||||
strbuf_release(&rev);
|
strbuf_release(&rev);
|
||||||
free(config);
|
free(config);
|
||||||
|
|
||||||
|
@ -176,4 +176,19 @@ test_expect_success 'fsck detects non-blob .gitmodules' '
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fsck detects corrupt .gitmodules' '
|
||||||
|
git init corrupt &&
|
||||||
|
(
|
||||||
|
cd corrupt &&
|
||||||
|
|
||||||
|
echo "[broken" >.gitmodules &&
|
||||||
|
git add .gitmodules &&
|
||||||
|
git commit -m "broken gitmodules" &&
|
||||||
|
|
||||||
|
git fsck 2>output &&
|
||||||
|
grep gitmodulesParse output &&
|
||||||
|
test_i18ngrep ! "bad config" output
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user