diff options
| author | Jeff King <peff@peff.net> | 2022-09-08 00:57:29 -0400 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2022-09-08 11:06:14 -0700 |
| commit | 3f0e86a158e85de20537e8b2c8531d09802433ba (patch) | |
| tree | 27b6945f7f1d494579947173e521c47ba974acd3 | |
| parent | 3fbfbbb7e3c21515a2863702734fe31bf50672fd (diff) | |
| download | git-3f0e86a158e85de20537e8b2c8531d09802433ba.tar.xz | |
transport: deep-copy object-filter struct for fetch-pack
When the transport code for the git protocol calls into fetch_pack(), it
has to fill out a fetch_pack_args struct that is mostly taken from the
transport options. We pass along any object-filter data by doing a
struct assignment of the list_objects_filter_options struct. But doing
so isn't safe; it contains allocated pointers in its filter_spec
string_list, which could lead to a double-free if one side mutates or
frees the string_list.
And indeed, the fetch-pack code does clear and rewrite the list via
expand_list_objects_filter_spec(), leaving the transport code with
dangling pointers.
This hasn't been a problem so far, though, because the transport code
doesn't look further at the filter struct. But it should, because in
some cases (when fetch-pack doesn't rewrite the list), it ends up
leaking the string_list.
So let's start by turning this shallow copy into a deep one, which
should let us fix the transport leak in a subsequent patch. Likewise,
we'll free the deep copy we made here when we're done with it (to avoid
leaking).
Note that it would also work to pass fetch-pack a pointer to our filter
struct, rather than a copy. But it's awkward for fetch-pack to take a
pointer in its arg struct; the actual git-fetch-pack command allocates a
fetch_pack_args struct on the stack and expects it to contain the filter
options. It could be rewritten to avoid this, but a deep copy serves our
purposes just as well.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
| -rw-r--r-- | transport.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/transport.c b/transport.c index b51e991e44..24540f642a 100644 --- a/transport.c +++ b/transport.c @@ -386,7 +386,8 @@ static int fetch_refs_via_pack(struct transport *transport, args.cloning = transport->cloning; args.update_shallow = data->options.update_shallow; args.from_promisor = data->options.from_promisor; - args.filter_options = data->options.filter_options; + list_objects_filter_copy(&args.filter_options, + &data->options.filter_options); args.refetch = data->options.refetch; args.stateless_rpc = transport->stateless_rpc; args.server_options = transport->server_options; @@ -453,6 +454,7 @@ cleanup: free_refs(refs_tmp); free_refs(refs); + list_objects_filter_release(&args.filter_options); return ret; } |
