From: Patrick Steinhardt <ps@pks.im>
To: shejialuo <shejialuo@gmail.com>
Cc: git@vger.kernel.org, Karthik Nayak <karthik.188@gmail.com>,
John Cai <johncai86@gmail.com>,
Junio C Hamano <gitster@pobox.com>
Subject: Re: [PATCH] ref-cache: fix invalid free operation in `free_ref_entry`
Date: Wed, 27 Nov 2024 06:50:11 +0100 [thread overview]
Message-ID: <Z0azEzigqr6DlitP@pks.im> (raw)
In-Reply-To: <Z0Xd-cYPNNrxwuAB@ArchLinux>
On Tue, Nov 26, 2024 at 10:40:57PM +0800, shejialuo wrote:
> In cfd971520e (refs: keep track of unresolved reference value in
> iterators, 2024-08-09), we added a new field "referent" into the "struct
> ref" structure. In order to free the "referent", we unconditionally
> freed the "referent" by simply adding a "free" statement.
>
> However, this is a bad usage. Because when ref entry is either directory
> or loose ref, we will always execute the following statement:
>
> free(entry->u.value.referent);
>
> This does not make sense. We should never access the "entry->u.value"
> field when "entry" is a directory. However, the change obviously doesn't
> break the tests. Let's analysis why.
>
> The anonymous union in the "ref_entry" has two members: one is "struct
> ref_value", another is "struct ref_dir". On a 64-bit machine, the size
> of "struct ref_dir" is 32 bytes, which is smaller than the 48-byte size
> of "struct ref_value". And the offset of "referent" field in "struct
> ref_value" is 40 bytes. So, whenever we create a new "ref_entry" for a
> directory, we will leave the offset from 40 bytes to 48 bytes untouched,
> which means the value for this memory is zero (NULL). It's OK to free a
> NULL pointer, but this is merely a coincidence of memory layout.
Makes sense.
> To fix this issue, we now ensure that "free(entry->u.value.referent)" is
> only called when "entry->flag" indicates that it represents a loose
> reference and not a directory to avoid the invalid memory operation.
>
> Signed-off-by: shejialuo <shejialuo@gmail.com>
> ---
> refs/ref-cache.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/refs/ref-cache.c b/refs/ref-cache.c
> index 35bae7e05d..02f09e4df8 100644
> --- a/refs/ref-cache.c
> +++ b/refs/ref-cache.c
> @@ -68,8 +68,9 @@ static void free_ref_entry(struct ref_entry *entry)
> * trigger the reading of loose refs.
> */
> clear_ref_dir(&entry->u.subdir);
> + } else {
> + free(entry->u.value.referent);
> }
> - free(entry->u.value.referent);
> free(entry);
> }
And the fix looks obviously good to me.
Thanks for catching this!
Patrick
prev parent reply other threads:[~2024-11-27 5:50 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-26 14:40 [PATCH] ref-cache: fix invalid free operation in `free_ref_entry` shejialuo
2024-11-27 5:50 ` Patrick Steinhardt [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z0azEzigqr6DlitP@pks.im \
--to=ps@pks.im \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=johncai86@gmail.com \
--cc=karthik.188@gmail.com \
--cc=shejialuo@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.