notes: use a strbuf in add_non_note
authorJeff King <peff@peff.net>
Wed, 19 Aug 2015 18:12:41 +0000 (14:12 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 4 Sep 2015 16:36:28 +0000 (09:36 -0700)
When we are loading a notes tree into our internal hash
table, we also collect any files that are clearly non-notes.
We format the name of the file into a PATH_MAX buffer, but
unlike true notes (which cannot be larger than a fanned-out
sha1 hash), these tree entries can be arbitrarily long,
overflowing our buffer.

We can fix this by switching to a strbuf. It doesn't even
cost us an extra allocation, as we can simply hand ownership
of the buffer over to the non-note struct.

This is of moderate security interest, as you might fetch
notes trees from an untrusted remote. However, we do not do
so by default, so you would have to manually fetch into the
notes namespace.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
notes.c
diff --git a/notes.c b/notes.c
index 5fe691dbcdfb9e3f9fa3c768f243234d5bb2e816..6a9cc6295b2e200cf35ebee1c3cc25913e20c02d 100644 (file)
--- 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 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                 * 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);