From: Collin Funk <collin.funk1@gmail.com>
To: Jeff King <peff@peff.net>
Cc: git@vger.kernel.org, "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
"Junio C Hamano" <gitster@pobox.com>,
"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
"Phillip Wood" <phillip.wood@dunelm.org.uk>,
"Matthew John Cheetham" <mjcheetham@outlook.com>,
"Victoria Dye" <vdye@github.com>,
"Derrick Stolee" <stolee@gmail.com>
Subject: Re: [PATCH] git-compat-util: make git_find_last_dir_sep return a const pointer
Date: Tue, 03 Feb 2026 19:15:10 -0800 [thread overview]
Message-ID: <87ecn18aip.fsf@gmail.com> (raw)
In-Reply-To: <20260203062537.GA286409@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
> On Mon, Feb 02, 2026 at 09:19:01PM -0800, Collin Funk wrote:
>
>> Unsure if this should be tagged [RFC], but this patch clears up lots
>> of warning spam with glibc 2.43 because of a change mentioned in the
>> commit message.
>
> Thanks for the heads-up. I can reproduce here by installing glibc 2.43
> via "apt install -t experimental libc6" on my debian unstable machine.
>
>> I plan to handle the rest of them and try to organize the changes by
>> subsystem, for lack of a better term. But I figured it was best to
>> submit just this one for review first.
>
> Wow, there's...a lot of spots. Looks like ~65 of them based on my hacky
> first-pass. Many of them are quite obvious "s/char/const char/" fixes in
> variable declarations, that should have been const all along. I think
> those can all go together in one patch, as the compiler can verify that
> we never try to write to the result.
Yep, it is quite noisy.
And that plan makes sense to me. I'll create a seperate patch handling
the obvious 's/char/const char/' conversions that make sense regardless
of this glibc change.
> And then, yeah, I'd do the tricky ones system by system. Some of the
> ones that do write to the resulting pointers are rather nasty, and seem
> to fall into one of two camps:
>
> 1. Some function interface takes a const pointer, even though we try
> to write to it under the hood (after laundering it through strchr()
> or similar). I think it would be worth refactoring these interfaces
> when we can, though some of them are pretty questionable. For
> instance, all of the rev-parse/revision.c "dotdot" parsing works on
> a "const char *arg". Surely we feed this from command line options
> in some cases? I guess argv is guaranteed to be writable by the
> standard, though we tend to treat is as const everywhere.
Yes, I see. I think the "arg" there is from the command line or from a
buffer read using fgets() in get_object_list from
builtin/pack-objects.c, so it is safe to write to there.
It's also called like this though:
handle_revision_arg("HEAD", &revs, 0, 0);
We can't write to the string "HEAD", but it doesn't have a "dotdot" so
we don't. It could probably be cleaned up a bit.
FYI, that code would also be made much clearer if not all of the
declarations were at the top of the function. I guess it just hasn't
been touched in a long while.
> 2. We know we have a non-const pointer, but it is passed through a
> const pointer that is used as an out-parameter to a function like
> skip_prefix(). For instance, in http.c's redact_sensitive_header()
> we have something like this:
>
> const char *sensitive_header;
> if (skip_iprefix(header->buf, "Cookie:", &sensitive_header)) {
> const char *cookie = sensitive_header;
> char *semicolon = strchr(cookie, "; ");
> *semicolon = 0;
> ...
>
> Our header->buf here is a strbuf, so we know we are working with a
> non-const buffer. We launder away constness with the strchr()
> assignment to "semicolon", which glibc now complains about. We
> should make "cookie" non-const, which is easy. But now we'll get a
> complaint about assigning the const "sensitive_header" to it. And
> that one should _also_ be non-const, because it comes from
> header->buf. But switching it will cause the compiler to complain
> about passing it to skip_iprefix().
>
> So we have the problem in reverse (instead of laundering a const
> string to a non-const, we've accidentally added constness where it
> is not needed). If we drop the const from skip_iprefix(), then that
> has fallout in all the other spots that do pass in a const haystack
> parameter.
>
> I don't know what the right solution is here. I guess the best we
> can do is probably adding casts with comments like "this is OK
> because it comes from...". But I'm not sure if we are better to
> cast away the constness in one spot, or to make all of the
> variables non-const and cast the out-parameter to skip_iprefix().
Makes sense, I'll try to handle the non-obviously ones separately.
>
>> #ifndef find_last_dir_sep
>> -static inline char *git_find_last_dir_sep(const char *path)
>> +static inline const char *git_find_last_dir_sep(const char *path)
>> {
>> return strrchr(path, '/');
>> }
>
> This kind of recreates that reverse problem again, though: any caller
> who really does have a non-const "path" will get "const" added back into
> it. And that leads to casts like...
I figured it was okay since only one place casted the qualifier away.
But I agree it is probably worth cleaning that up later.
>> static int chop_last_dir(char **remoteurl, int is_relative)
>> {
>> - char *rfind = find_last_dir_sep(*remoteurl);
>> + char *rfind = (char *) find_last_dir_sep(*remoteurl);
>> if (rfind) {
>> *rfind = '\0';
>> return 0;
>
> ...this one. Can we implement it as a macro? That lets the compiler do
> the right thing, because we do not declare any type then. It used to be
> a macro, but switched in bf7283465b (turn path macros into inline
> function, 2014-08-16). There's also a level of macro indirection; on
> Windows this expands to win32_find_last_dir_sep(), which of course casts
> away the constness manually. ;)
>
> I also wonder if we could do some gcc/glibc-specific magic to get the
> best of both worlds. That is, could we get the same "the return value is
> const if the input parameter was" type-checking that is happening with
> strchr()?
>
> Looking at strchr()'s declaration in string.h, which is defined like:
>
> # define strchr(S, C) \
> __glibc_const_generic (S, const char *, strchr (S, C))
>
> I think the answer is probably "yes". But it also doesn't quite solve
> our problem. That would give us type-checking of callers of our
> function, but we still have to convince the compiler not to complain
> about its implementation. For that we'd need to either cast away const
> manually, I guess.
That macro depends on Generic selections from C11 [1]. I wasn't sure if
Git would like that, given it is conservative with other C features.
> Yuck. What a mess. I do think that fixing these warnings will improve
> most of the call-sites I looked at, but some of them get a bit hairy.
Thanks to C23. :)
Collin
[1] https://en.cppreference.com/w/c/language/generic.html
next prev parent reply other threads:[~2026-02-04 3:15 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-03 5:19 [PATCH] git-compat-util: make git_find_last_dir_sep return a const pointer Collin Funk
2026-02-03 6:25 ` Jeff King
2026-02-04 3:15 ` Collin Funk [this message]
2026-02-04 5:32 ` Jeff King
2026-03-19 11:06 ` Toon Claes
2026-03-20 4:39 ` Jeff King
2026-03-20 5:20 ` Collin Funk
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=87ecn18aip.fsf@gmail.com \
--to=collin.funk1@gmail.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=mjcheetham@outlook.com \
--cc=peff@peff.net \
--cc=phillip.wood@dunelm.org.uk \
--cc=stolee@gmail.com \
--cc=vdye@github.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox