mirror of
https://github.com/git/git.git
synced 2024-11-01 14:57:52 +01:00
5096d4909f
We sometimes sprintf into fixed-size buffers when we know that the buffer is large enough to fit the input (either because it's a constant, or because it's numeric input that is bounded in size). Likewise with strcpy of constant strings. However, these sites make it hard to audit sprintf and strcpy calls for buffer overflows, as a reader has to cross-reference the size of the array with the input. Let's use xsnprintf instead, which communicates to a reader that we don't expect this to overflow (and catches the mistake in case we do). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
110 lines
2.2 KiB
C
110 lines
2.2 KiB
C
#include "builtin.h"
|
|
#include "run-command.h"
|
|
|
|
static const char *pgm;
|
|
static int one_shot, quiet;
|
|
static int err;
|
|
|
|
static int merge_entry(int pos, const char *path)
|
|
{
|
|
int found;
|
|
const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
|
|
char hexbuf[4][60];
|
|
char ownbuf[4][60];
|
|
|
|
if (pos >= active_nr)
|
|
die("git merge-index: %s not in the cache", path);
|
|
found = 0;
|
|
do {
|
|
const struct cache_entry *ce = active_cache[pos];
|
|
int stage = ce_stage(ce);
|
|
|
|
if (strcmp(ce->name, path))
|
|
break;
|
|
found++;
|
|
strcpy(hexbuf[stage], sha1_to_hex(ce->sha1));
|
|
xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
|
|
arguments[stage] = hexbuf[stage];
|
|
arguments[stage + 4] = ownbuf[stage];
|
|
} while (++pos < active_nr);
|
|
if (!found)
|
|
die("git merge-index: %s not in the cache", path);
|
|
|
|
if (run_command_v_opt(arguments, 0)) {
|
|
if (one_shot)
|
|
err++;
|
|
else {
|
|
if (!quiet)
|
|
die("merge program failed");
|
|
exit(1);
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
static void merge_one_path(const char *path)
|
|
{
|
|
int pos = cache_name_pos(path, strlen(path));
|
|
|
|
/*
|
|
* If it already exists in the cache as stage0, it's
|
|
* already merged and there is nothing to do.
|
|
*/
|
|
if (pos < 0)
|
|
merge_entry(-pos-1, path);
|
|
}
|
|
|
|
static void merge_all(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < active_nr; i++) {
|
|
const struct cache_entry *ce = active_cache[i];
|
|
if (!ce_stage(ce))
|
|
continue;
|
|
i += merge_entry(i, ce->name)-1;
|
|
}
|
|
}
|
|
|
|
int cmd_merge_index(int argc, const char **argv, const char *prefix)
|
|
{
|
|
int i, force_file = 0;
|
|
|
|
/* Without this we cannot rely on waitpid() to tell
|
|
* what happened to our children.
|
|
*/
|
|
signal(SIGCHLD, SIG_DFL);
|
|
|
|
if (argc < 3)
|
|
usage("git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])");
|
|
|
|
read_cache();
|
|
|
|
i = 1;
|
|
if (!strcmp(argv[i], "-o")) {
|
|
one_shot = 1;
|
|
i++;
|
|
}
|
|
if (!strcmp(argv[i], "-q")) {
|
|
quiet = 1;
|
|
i++;
|
|
}
|
|
pgm = argv[i++];
|
|
for (; i < argc; i++) {
|
|
const char *arg = argv[i];
|
|
if (!force_file && *arg == '-') {
|
|
if (!strcmp(arg, "--")) {
|
|
force_file = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(arg, "-a")) {
|
|
merge_all();
|
|
continue;
|
|
}
|
|
die("git merge-index: unknown option %s", arg);
|
|
}
|
|
merge_one_path(arg);
|
|
}
|
|
if (err && !quiet)
|
|
die("merge program failed");
|
|
return err;
|
|
}
|