]> git.ipfire.org Git - thirdparty/git.git/commitdiff
traverse_trees(): use stack array for name entries
authorJeff King <peff@peff.net>
Thu, 30 Jan 2020 09:53:38 +0000 (04:53 -0500)
committerJunio C Hamano <gitster@pobox.com>
Thu, 30 Jan 2020 21:55:30 +0000 (13:55 -0800)
We heap-allocate our arrays of name_entry structs, etc, with one entry
per tree we're asked to traverse. The code does a raw multiplication in
the xmalloc() call, which I find when auditing for integer overflows
during allocation.

We could "fix" this by using ALLOC_ARRAY() instead. But as it turns out,
the maximum size of these arrays is limited at compile time:

  - merge_trees() always passes in 3 trees

  - unpack_trees() and its brethren never pass in more than
    MAX_UNPACK_TREES

So we can simplify even further by just using a stack array and bounding
it with MAX_UNPACK_TREES. There should be no concern with overflowing
the stack, since MAX_UNPACK_TREES is only 8 and the structs themselves
are small.

Note that since we're replacing xcalloc(), we have to move one of the
NULL initializations into a loop.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
tree-walk.c

index d5a8e096a6065209daab04e3ec77dda2515d3562..3093cf7098ba6ec8e3c10098484845fc7e6e12b9 100644 (file)
@@ -410,15 +410,20 @@ int traverse_trees(struct index_state *istate,
                   struct traverse_info *info)
 {
        int error = 0;
-       struct name_entry *entry = xmalloc(n*sizeof(*entry));
+       struct name_entry entry[MAX_UNPACK_TREES];
        int i;
-       struct tree_desc_x *tx = xcalloc(n, sizeof(*tx));
+       struct tree_desc_x tx[ARRAY_SIZE(entry)];
        struct strbuf base = STRBUF_INIT;
        int interesting = 1;
        char *traverse_path;
 
-       for (i = 0; i < n; i++)
+       if (n >= ARRAY_SIZE(entry))
+               BUG("traverse_trees() called with too many trees (%d)", n);
+
+       for (i = 0; i < n; i++) {
                tx[i].d = t[i];
+               tx[i].skip = NULL;
+       }
 
        if (info->prev) {
                strbuf_make_traverse_path(&base, info->prev,
@@ -506,10 +511,8 @@ int traverse_trees(struct index_state *istate,
                        if (mask & (1ul << i))
                                update_extended_entry(tx + i, entry + i);
        }
-       free(entry);
        for (i = 0; i < n; i++)
                free_extended_entry(tx + i);
-       free(tx);
        free(traverse_path);
        info->traverse_path = NULL;
        strbuf_release(&base);