db2b3d263a
- Fix remote code execution via buffer overflow (CVE-2016-2315, CVE-2016-2324, bsc#971328): 0012-http-push-stop-using-name_path.patch 0013-show_object_with_name-simplify-by-using-path_name.patch 0014-list-objects-convert-name_path-to-a-strbuf.patch 0015-list-objects-drop-name_path-entirely.patch 0016-list-objects-pass-full-pathname-to-callbacks.patch OBS-URL: https://build.opensuse.org/request/show/373839 OBS-URL: https://build.opensuse.org/package/show/devel:tools:scm/cgit?expand=0&rev=27
156 lines
4.7 KiB
Diff
156 lines
4.7 KiB
Diff
From 13528ab37cadb4d4f7384d0449489760912904b8 Mon Sep 17 00:00:00 2001
|
|
From: Jeff King <peff@peff.net>
|
|
Date: Thu, 11 Feb 2016 17:26:18 -0500
|
|
Subject: [PATCH 4/6] list-objects: convert name_path to a strbuf
|
|
|
|
The "struct name_path" data is examined in only two places:
|
|
we generate it in process_tree(), and we convert it to a
|
|
single string in path_name(). Everyone else just passes it
|
|
through to those functions.
|
|
|
|
We can further note that process_tree() already keeps a
|
|
single strbuf with the leading tree path, for use with
|
|
tree_entry_interesting().
|
|
|
|
Instead of building a separate name_path linked list, let's
|
|
just use the one we already build in "base". This reduces
|
|
the amount of code (especially tricky code in path_name()
|
|
which did not check for integer overflows caused by deep
|
|
or large pathnames).
|
|
|
|
It is also more efficient in some instances. Any time we
|
|
were using tree_entry_interesting, we were building up the
|
|
strbuf anyway, so this is an immediate and obvious win
|
|
there. In cases where we were not, we trade off storing
|
|
"pathname/" in a strbuf on the heap for each level of the
|
|
path, instead of two pointers and an int on the stack (with
|
|
one pointer into the tree object). On a 64-bit system, the
|
|
latter is 20 bytes; so if path components are less than that
|
|
on average, this has lower peak memory usage. In practice
|
|
it probably doesn't matter either way; we are already
|
|
holding in memory all of the tree objects leading up to each
|
|
pathname, and for normal-depth pathnames, we are only
|
|
talking about hundreds of bytes.
|
|
|
|
This patch leaves "struct name_path" as a thin wrapper
|
|
around the strbuf, to avoid disrupting callbacks. We should
|
|
fix them, but leaving it out makes this diff easier to view.
|
|
|
|
Signed-off-by: Jeff King <peff@peff.net>
|
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
---
|
|
list-objects.c | 22 +++++++++-------------
|
|
revision.c | 25 +++++--------------------
|
|
revision.h | 4 +---
|
|
3 files changed, 15 insertions(+), 36 deletions(-)
|
|
|
|
diff --git a/list-objects.c b/list-objects.c
|
|
index 11732d93883e..4f60a3ea2aa5 100644
|
|
--- a/list-objects.c
|
|
+++ b/list-objects.c
|
|
@@ -62,7 +62,6 @@ static void process_gitlink(struct rev_info *revs,
|
|
static void process_tree(struct rev_info *revs,
|
|
struct tree *tree,
|
|
show_object_fn show,
|
|
- struct name_path *path,
|
|
struct strbuf *base,
|
|
const char *name,
|
|
void *cb_data)
|
|
@@ -86,17 +85,14 @@ static void process_tree(struct rev_info *revs,
|
|
return;
|
|
die("bad tree object %s", oid_to_hex(&obj->oid));
|
|
}
|
|
+
|
|
obj->flags |= SEEN;
|
|
- show(obj, path, name, cb_data);
|
|
- me.up = path;
|
|
- me.elem = name;
|
|
- me.elem_len = strlen(name);
|
|
-
|
|
- if (!match) {
|
|
- strbuf_addstr(base, name);
|
|
- if (base->len)
|
|
- strbuf_addch(base, '/');
|
|
- }
|
|
+ me.base = base;
|
|
+ show(obj, &me, name, cb_data);
|
|
+
|
|
+ strbuf_addstr(base, name);
|
|
+ if (base->len)
|
|
+ strbuf_addch(base, '/');
|
|
|
|
init_tree_desc(&desc, tree->buffer, tree->size);
|
|
|
|
@@ -113,7 +109,7 @@ static void process_tree(struct rev_info *revs,
|
|
if (S_ISDIR(entry.mode))
|
|
process_tree(revs,
|
|
lookup_tree(entry.sha1),
|
|
- show, &me, base, entry.path,
|
|
+ show, base, entry.path,
|
|
cb_data);
|
|
else if (S_ISGITLINK(entry.mode))
|
|
process_gitlink(revs, entry.sha1,
|
|
@@ -220,7 +216,7 @@ void traverse_commit_list(struct rev_info *revs,
|
|
path = "";
|
|
if (obj->type == OBJ_TREE) {
|
|
process_tree(revs, (struct tree *)obj, show_object,
|
|
- NULL, &base, path, data);
|
|
+ &base, path, data);
|
|
continue;
|
|
}
|
|
if (obj->type == OBJ_BLOB) {
|
|
diff --git a/revision.c b/revision.c
|
|
index 6387068a5582..8dd09508ab88 100644
|
|
--- a/revision.c
|
|
+++ b/revision.c
|
|
@@ -27,26 +27,11 @@ static const char *term_good;
|
|
|
|
char *path_name(const struct name_path *path, const char *name)
|
|
{
|
|
- const struct name_path *p;
|
|
- char *n, *m;
|
|
- int nlen = strlen(name);
|
|
- int len = nlen + 1;
|
|
-
|
|
- for (p = path; p; p = p->up) {
|
|
- if (p->elem_len)
|
|
- len += p->elem_len + 1;
|
|
- }
|
|
- n = xmalloc(len);
|
|
- m = n + len - (nlen + 1);
|
|
- memcpy(m, name, nlen + 1);
|
|
- for (p = path; p; p = p->up) {
|
|
- if (p->elem_len) {
|
|
- m -= p->elem_len + 1;
|
|
- memcpy(m, p->elem, p->elem_len);
|
|
- m[p->elem_len] = '/';
|
|
- }
|
|
- }
|
|
- return n;
|
|
+ struct strbuf ret = STRBUF_INIT;
|
|
+ if (path)
|
|
+ strbuf_addbuf(&ret, path->base);
|
|
+ strbuf_addstr(&ret, name);
|
|
+ return strbuf_detach(&ret, NULL);
|
|
}
|
|
|
|
void show_object_with_name(FILE *out, struct object *obj,
|
|
diff --git a/revision.h b/revision.h
|
|
index 23857c0ed1d7..2a26310d6cc0 100644
|
|
--- a/revision.h
|
|
+++ b/revision.h
|
|
@@ -258,9 +258,7 @@ extern void mark_parents_uninteresting(struct commit *commit);
|
|
extern void mark_tree_uninteresting(struct tree *tree);
|
|
|
|
struct name_path {
|
|
- struct name_path *up;
|
|
- int elem_len;
|
|
- const char *elem;
|
|
+ struct strbuf *base;
|
|
};
|
|
|
|
char *path_name(const struct name_path *path, const char *name);
|
|
--
|
|
2.7.3
|
|
|