git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [BUGREPORT] git diff-tree --cc SEGFAUTs

From
Wink Saville <wink@saville.com>
Date
Jan 3, 2025, 23:34 UTC
Message-ID
<CAKk8isrz1NQ=3=2aZ3tANymo0eSsCy=r6W5yKgn6gxmOom54CA@mail.gmail.com>
In-Reply-To
<20250103204624.GE3212696@coredump.intra.peff.net>
On Fri, Jan 3, 2025 at 12:46 PM Jeff King <peff@peff.net> wrote:
Show 46 quoted lines
>
> On Fri, Jan 03, 2025 at 11:28:47AM -0800, Wink Saville wrote:
>
> > `git diff-tree --cc` SEGFAUTs after adding trace_printf to diff_tree_combined.
>
> Hmm, is it really a bug in Git if you had to add new code which contains
> the bug? :)
>
> > @@ -1595,8 +1597,16 @@ void diff_tree_combined(const struct object_id *oid,
> >       }
> >
> >       /* find out number of surviving paths */
> > -     for (num_paths = 0, p = paths; p; p = p->next)
> > +     trace_printf("Wink diff_tree_combined: find number of surviving paths num_parent=%d\n", num_parent);
> > +     for (num_paths = 0, p = paths; p; p = p->next) {
> > +             trace_printf("Wink diff_tree_combined: num_paths=%d &p=%p mode=%0x, oid=%s path=%s\n", num_paths, p, p->mode, oid_to_hex(&p->oid), p->path);
> > +             for (i = 0; i < num_parent; i++) {
> > +                     trace_printf("Wink diff_tree_combined:  &p->parent[%d]=%p status=%c mode=%x oid=%s path.buf=%p contents path.buf=%s\n",
> > +                              i, &p->parent[i], p->parent[i].status, p->parent[i].mode, oid_to_hex(&p->parent[i].oid), p->parent[i].path.buf, p->parent[i].path.buf);
> > +             }
>
> The parent "path" strbufs are only initialized in intersect_paths() if
> combined_all_paths is set, and if there was an actual path change (a
> copy or rename).
>
> So you'd probably need something like this:
>
> diff --git a/combine-diff.c b/combine-diff.c
> index 455bc19087..1e58809c4e 100644
> --- a/combine-diff.c
> +++ b/combine-diff.c
> @@ -1601,8 +1601,11 @@ void diff_tree_combined(const struct object_id *oid,
>         for (num_paths = 0, p = paths; p; p = p->next) {
>                 trace_printf("Wink diff_tree_combined: num_paths=%d &p=%p mode=%0x, oid=%s path=%s\n", num_paths, p, p->mode, oid_to_hex(&p->oid), p->path);
>                 for (i = 0; i < num_parent; i++) {
> +                       const char *path = rev->combine_all_paths &&
> +                                          filename_changed(p->parent[i].status) ?
> +                                          p->parent[i].path.buf : NULL;
>                         trace_printf("Wink diff_tree_combined:  &p->parent[%d]=%p status=%c mode=%x oid=%s path.buf=%p contents path.buf=%s\n",
> -                                i, &p->parent[i], p->parent[i].status, p->parent[i].mode, oid_to_hex(&p->parent[i].oid), p->parent[i].path.buf, p->parent[i].path.buf);
> +                                    i, &p->parent[i], p->parent[i].status, p->parent[i].mode, oid_to_hex(&p->parent[i].oid), path, path);
>                 }
>                 num_paths++;
>         }
>
> -Peff
TYVM!

That worked but changed the name and fixed a typo in `combined_all_paths`: ``` wink@3900x 25-01-03T23:06:08.344Z:~/data/prgs/forks/git (wink-segfault-with-minimal-changes) $ git diff

diff --git a/combine-diff.c b/combine-diff.c
index 455bc19087..70394c3350 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1601,8 +1601,9 @@ void diff_tree_combined(const struct object_id *oid,
        for (num_paths = 0, p = paths; p; p = p->next) {
                trace_printf("Wink diff_tree_combined: num_paths=%d
&p=%p mode=%0x, oid=%s path=%s\n", num_paths, p, p->mode,
oid_to_hex(&p->oid), p->path);
                for (i = 0; i < num_parent; i++) {
+                       const char *parent_path =
rev->combined_all_paths && filename_changed(p->parent[i].status) ?
p->parent[i].path.buf : NULL;
                        trace_printf("Wink diff_tree_combined:
&p->parent[%d]=%p status=%c mode=%x oid=%s path.buf=%p contents
path.buf=%s\n",
-                                i, &p->parent[i],
p->parent[i].status, p->parent[i].mode, oid_to_hex(&p->parent[i].oid),
p->parent[i].path.buf, p->parent[i].path.buf);
+                                i, &p->parent[i],
p->parent[i].status, p->parent[i].mode, oid_to_hex(&p->parent[i].oid),
parent_path, parent_path);
                }
                num_paths++;
        }
```

But having to protect yourself is unobvious and especially if it isn't necessary
when using the `fetch_paths_generic`.

In addition, from strbuf.h `buf` is never NULL:

"
* strbufs have some invariants that are very important to keep in mind:
 *
 *  - The `buf` member is never NULL, so it can be used in any usual C
 *    string operations safely. strbufs _have_ to be initialized either by
 *    `strbuf_init()` or by `= STRBUF_INIT` before the invariants, though.
 *
"

So I'd say this could be considered a bug in git at least in how
combine_diff_path
is being managed. I assume you agree that neither find_paths_generic or
find_paths_multitree are adhering to at least that strbuf invariant and I wonder
if the other strbuf invariants are being upheld.

So, should this bug be "closed" and a new one "created"?

Actually, using the mailing list to identify bugs and initially discuss
them, seems fine. But is there a place where there is a list of current bugs and
their state?

-- wink
Previous: Jeff KingNext: Jeff King
Message 3 of 38 in “[BUGREPORT] git diff-tree --cc SEGFAUTs”
  1. Wink SavilleJan 3, 2025
  2. Jeff KingJan 3, 2025
  3. Wink SavilleJan 3, 2025
  4. Jeff KingJan 4, 2025
  5. Junio C HamanoJan 4, 2025
  6. Jeff KingJan 4, 2025
  7. Wink SavilleJan 4, 2025
  8. Wink SavilleJan 5, 2025
  9. 0/14 combine-diff cleanupsJeff King, Jan 9, 2025
  10. 01/14 run_diff_files(): delay allocation of combine_diff_pathJeff King, Jan 9, 2025
  11. Junio C HamanoJan 9, 2025
  12. 02/14 combine-diff: add combine_diff_path_new()Jeff King, Jan 9, 2025
  13. Junio C HamanoJan 9, 2025
  14. Patrick SteinhardtJan 13, 2025
  15. Jeff KingJan 14, 2025
  16. 03/14 tree-diff: clear parent array in path_appendnew()Jeff King, Jan 9, 2025
  17. Junio C HamanoJan 9, 2025
  18. Jeff KingJan 10, 2025
  19. 04/14 combine-diff: use pointer for parent pathsJeff King, Jan 9, 2025
  20. Junio C HamanoJan 9, 2025
  21. 05/14 diff: add a comment about combine_diff_path.parent.pathJeff King, Jan 9, 2025
  22. Patrick SteinhardtJan 13, 2025
  23. 06/14 run_diff_files(): de-mystify the size of combine_diff_path structJeff King, Jan 9, 2025
  24. Junio C HamanoJan 10, 2025
  25. 07/14 tree-diff: drop path_appendnew() alloc optimizationJeff King, Jan 9, 2025
  26. Patrick SteinhardtJan 13, 2025
  27. Jeff KingJan 14, 2025
  28. 08/14 tree-diff: pass whole path string to path_appendnew()Jeff King, Jan 9, 2025
  29. Patrick SteinhardtJan 13, 2025
  30. Jeff KingJan 14, 2025
  31. 09/14 tree-diff: inline path_appendnew()Jeff King, Jan 9, 2025
  32. Junio C HamanoJan 11, 2025
  33. 10/14 combine-diff: drop public declaration of combine_diff_path_size()Jeff King, Jan 9, 2025
  34. 11/14 tree-diff: drop list-tail argument to diff_tree_paths()Jeff King, Jan 9, 2025
  35. Junio C HamanoJan 18, 2025
  36. 12/14 tree-diff: use the name "tail" to refer to list tailJeff King, Jan 9, 2025
  37. 13/14 tree-diff: simplify emit_path() list managementJeff King, Jan 9, 2025
  38. 14/14 tree-diff: make list tail-passing more explicitJeff King, Jan 9, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.