mirror of
https://github.com/git/git.git
synced 2024-10-28 12:59:41 +01:00
unique_path: fix unlikely heap overflow
When merge-recursive creates a unique filename, it uses a template like: path~branch_%d where the final "_%d" is filled by an incrementing counter until we find a unique name. We allocate 8 characters for the counter, but there is no logic to limit the size of the integer. Of course, this is extremely unlikely, as you would need a hundred million collisions to trigger the problem. Even if an attacker constructed a specialized repo, it is unlikely that the victim would have the patience to run the merge. However, we can make it trivially correct (and hopefully more readable) by using a strbuf. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
f33206992d
commit
45bc131dd3
1 changed files with 25 additions and 14 deletions
|
@ -601,25 +601,36 @@ static int remove_file(struct merge_options *o, int clean,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add a string to a strbuf, but converting "/" to "_" */
|
||||||
|
static void add_flattened_path(struct strbuf *out, const char *s)
|
||||||
|
{
|
||||||
|
size_t i = out->len;
|
||||||
|
strbuf_addstr(out, s);
|
||||||
|
for (; i < out->len; i++)
|
||||||
|
if (out->buf[i] == '/')
|
||||||
|
out->buf[i] = '_';
|
||||||
|
}
|
||||||
|
|
||||||
static char *unique_path(struct merge_options *o, const char *path, const char *branch)
|
static char *unique_path(struct merge_options *o, const char *path, const char *branch)
|
||||||
{
|
{
|
||||||
char *newpath = xmalloc(strlen(path) + 1 + strlen(branch) + 8 + 1);
|
struct strbuf newpath = STRBUF_INIT;
|
||||||
int suffix = 0;
|
int suffix = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *p = newpath + strlen(path);
|
size_t base_len;
|
||||||
strcpy(newpath, path);
|
|
||||||
*(p++) = '~';
|
|
||||||
strcpy(p, branch);
|
|
||||||
for (; *p; ++p)
|
|
||||||
if ('/' == *p)
|
|
||||||
*p = '_';
|
|
||||||
while (string_list_has_string(&o->current_file_set, newpath) ||
|
|
||||||
string_list_has_string(&o->current_directory_set, newpath) ||
|
|
||||||
lstat(newpath, &st) == 0)
|
|
||||||
sprintf(p, "_%d", suffix++);
|
|
||||||
|
|
||||||
string_list_insert(&o->current_file_set, newpath);
|
strbuf_addf(&newpath, "%s~", path);
|
||||||
return newpath;
|
add_flattened_path(&newpath, branch);
|
||||||
|
|
||||||
|
base_len = newpath.len;
|
||||||
|
while (string_list_has_string(&o->current_file_set, newpath.buf) ||
|
||||||
|
string_list_has_string(&o->current_directory_set, newpath.buf) ||
|
||||||
|
lstat(newpath.buf, &st) == 0) {
|
||||||
|
strbuf_setlen(&newpath, base_len);
|
||||||
|
strbuf_addf(&newpath, "_%d", suffix++);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_list_insert(&o->current_file_set, newpath.buf);
|
||||||
|
return strbuf_detach(&newpath, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dir_in_way(const char *path, int check_working_copy)
|
static int dir_in_way(const char *path, int check_working_copy)
|
||||||
|
|
Loading…
Reference in a new issue