diff options
author | Jeff King <peff@peff.net> | 2017-03-28 15:46:44 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-03-30 14:59:50 -0700 |
commit | 903fc7da44b091a87c4bc00a892930786c71a709 (patch) | |
tree | cb93269a3d5c51e35ae92ec046f91c7e9d672ce7 | |
parent | cddac45219b70f121d30468811a9fbee78fa24f2 (diff) | |
download | git-903fc7da44b091a87c4bc00a892930786c71a709.tar.gz |
name-rev: replace static buffer with strbuf
When name-rev needs to format an actual name, we do so into
a fixed-size buffer. That includes the actual ref tip, as
well as any traversal information. Since refs can exceed
1024 bytes, this means you can get a bogus result. E.g.,
doing:
git tag $(perl -e 'print join("/", 1..1024)')
git describe --contains HEAD^
results in ".../282/283", when it should be
".../1023/1024~1".
We can solve this by using a heap buffer. We'll use a
strbuf, which lets us write into the same buffer from our
loop without having to reallocate.
Signed-off-by: Jeff King <peff@peff.net>
-rw-r--r-- | builtin/name-rev.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 8bdc3eaa6f..92a5d8a5d2 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -238,10 +238,9 @@ static const char *get_exact_ref_match(const struct object *o) return NULL; } -/* returns a static buffer */ -static const char *get_rev_name(const struct object *o) +/* may return a constant string or use "buf" as scratch space */ +static const char *get_rev_name(const struct object *o, struct strbuf *buf) { - static char buffer[1024]; struct rev_name *n; struct commit *c; @@ -258,10 +257,9 @@ static const char *get_rev_name(const struct object *o) int len = strlen(n->tip_name); if (len > 2 && !strcmp(n->tip_name + len - 2, "^0")) len -= 2; - snprintf(buffer, sizeof(buffer), "%.*s~%d", len, n->tip_name, - n->generation); - - return buffer; + strbuf_reset(buf); + strbuf_addf(buf, "%.*s~%d", len, n->tip_name, n->generation); + return buf->buf; } } @@ -271,10 +269,11 @@ static void show_name(const struct object *obj, { const char *name; const struct object_id *oid = &obj->oid; + struct strbuf buf = STRBUF_INIT; if (!name_only) printf("%s ", caller_name ? caller_name : oid_to_hex(oid)); - name = get_rev_name(obj); + name = get_rev_name(obj, &buf); if (name) printf("%s\n", name); else if (allow_undefined) @@ -283,6 +282,7 @@ static void show_name(const struct object *obj, printf("%s\n", find_unique_abbrev(oid->hash, DEFAULT_ABBREV)); else die("cannot describe '%s'", oid_to_hex(oid)); + strbuf_release(&buf); } static char const * const name_rev_usage[] = { @@ -294,6 +294,7 @@ static char const * const name_rev_usage[] = { static void name_rev_line(char *p, struct name_ref_data *data) { + struct strbuf buf = STRBUF_INIT; int forty = 0; char *p_start; for (p_start = p; *p; p++) { @@ -314,7 +315,7 @@ static void name_rev_line(char *p, struct name_ref_data *data) struct object *o = lookup_object(sha1); if (o) - name = get_rev_name(o); + name = get_rev_name(o, &buf); } *(p+1) = c; @@ -332,6 +333,8 @@ static void name_rev_line(char *p, struct name_ref_data *data) /* flush */ if (p_start != p) fwrite(p_start, p - p_start, 1, stdout); + + strbuf_release(&buf); } int cmd_name_rev(int argc, const char **argv, const char *prefix) |