diff --git a/Documentation/RelNotes/2.2.3.txt b/Documentation/RelNotes/2.2.3.txt new file mode 100644 index 0000000000..5bfffa4106 --- /dev/null +++ b/Documentation/RelNotes/2.2.3.txt @@ -0,0 +1,9 @@ +Git v2.2.3 Release Notes +======================== + +Fixes since v2.2.2 +------------------ + + * A handful of codepaths that used to use fixed-sized arrays to hold + pathnames have been corrected to use strbuf and other mechanisms to + allow longer pathnames without fearing overflows. diff --git a/Documentation/git.txt b/Documentation/git.txt index adff610f8b..9c46cabcb9 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -56,9 +56,10 @@ Documentation for older releases are available here: link:RelNotes/2.3.1.txt[2.3.1], link:RelNotes/2.3.0.txt[2.3]. -* link:v2.2.2/git.html[documentation for release 2.2.2] +* link:v2.2.3/git.html[documentation for release 2.2.3] * release notes for + link:RelNotes/2.2.3.txt[2.2.3], link:RelNotes/2.2.2.txt[2.2.2], link:RelNotes/2.2.1.txt[2.2.1], link:RelNotes/2.2.0.txt[2.2]. diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 365228aa8d..808225cddc 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -723,7 +723,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) if (reflog) { unsigned char sha1[20]; - char nth_desc[256]; char *ref; int base = 0; unsigned int flags = 0; @@ -762,6 +761,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) for (i = 0; i < reflog; i++) { char *logmsg; + char *nth_desc; const char *msg; unsigned long timestamp; int tz; @@ -780,8 +780,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) show_date(timestamp, tz, 1), msg); free(logmsg); - sprintf(nth_desc, "%s@{%d}", *av, base+i); + + nth_desc = xstrfmt("%s@{%d}", *av, base+i); append_ref(nth_desc, sha1, 1); + free(nth_desc); } free(ref); } diff --git a/notes.c b/notes.c index 2be4d7f3fd..d465200541 100644 --- a/notes.c +++ b/notes.c @@ -362,13 +362,14 @@ static int non_note_cmp(const struct non_note *a, const struct non_note *b) return strcmp(a->path, b->path); } -static void add_non_note(struct notes_tree *t, const char *path, +/* note: takes ownership of path string */ +static void add_non_note(struct notes_tree *t, char *path, unsigned int mode, const unsigned char *sha1) { struct non_note *p = t->prev_non_note, *n; n = (struct non_note *) xmalloc(sizeof(struct non_note)); n->next = NULL; - n->path = xstrdup(path); + n->path = path; n->mode = mode; hashcpy(n->sha1, sha1); t->prev_non_note = n; @@ -482,17 +483,17 @@ handle_non_note: * component. */ { - char non_note_path[PATH_MAX]; - char *p = non_note_path; + struct strbuf non_note_path = STRBUF_INIT; const char *q = sha1_to_hex(subtree->key_sha1); int i; for (i = 0; i < prefix_len; i++) { - *p++ = *q++; - *p++ = *q++; - *p++ = '/'; + strbuf_addch(&non_note_path, *q++); + strbuf_addch(&non_note_path, *q++); + strbuf_addch(&non_note_path, '/'); } - strcpy(p, entry.path); - add_non_note(t, non_note_path, entry.mode, entry.sha1); + strbuf_addstr(&non_note_path, entry.path); + add_non_note(t, strbuf_detach(&non_note_path, NULL), + entry.mode, entry.sha1); } } free(buf); diff --git a/sha1_file.c b/sha1_file.c index 88f06bac92..ec3adcaead 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -377,15 +377,12 @@ void read_info_alternates(const char * relative_base, int depth) char *map; size_t mapsz; struct stat st; - const char alt_file_name[] = "info/alternates"; - /* Given that relative_base is no longer than PATH_MAX, - ensure that "path" has enough space to append "/", the - file name, "info/alternates", and a trailing NUL. */ - char path[PATH_MAX + 1 + sizeof alt_file_name]; + char *path; int fd; - sprintf(path, "%s/%s", relative_base, alt_file_name); + path = xstrfmt("%s/info/alternates", relative_base); fd = git_open_noatime(path); + free(path); if (fd < 0) return; if (fstat(fd, &st) || (st.st_size == 0)) { diff --git a/unpack-trees.c b/unpack-trees.c index be84ba2607..17a5eeb6cd 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -1434,15 +1434,18 @@ static int verify_absent_1(const struct cache_entry *ce, if (!len) return 0; else if (len > 0) { - char path[PATH_MAX + 1]; - memcpy(path, ce->name, len); - path[len] = 0; - if (lstat(path, &st)) - return error("cannot stat '%s': %s", path, - strerror(errno)); + char *path; + int ret; - return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st, - error_type, o); + path = xmemdupz(ce->name, len); + if (lstat(path, &st)) + ret = error("cannot stat '%s': %s", path, + strerror(errno)); + else + ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL, + &st, error_type, o); + free(path); + return ret; } else if (lstat(ce->name, &st)) { if (errno != ENOENT) return error("cannot stat '%s': %s", ce->name,