From: Patrick Steinhardt <ps@pks.im>
To: Ihar Hrachyshka <ihar.hrachyshka@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] precompose_utf8: use a flex array for d_name
Date: Fri, 3 Jul 2026 10:40:59 +0200 [thread overview]
Message-ID: <akd1m6KoUh7N8yyE@pks.im> (raw)
In-Reply-To: <20260703023554.36577-1-ihar.hrachyshka@gmail.com>
On Thu, Jul 02, 2026 at 10:35:54PM -0400, Ihar Hrachyshka wrote:
> On macOS, git status may abort while reading a directory entry
> whose UTF-8 name grows past NAME_MAX bytes:
>
> __chk_fail_overflow
> __strlcpy_chk
> precompose_utf8_readdir
> read_directory_recursive
> wt_status_collect
> cmd_status
>
> The precompose wrapper already reallocates dirent_prec_psx for
> long names, but d_name is declared as char[NAME_MAX + 1]. A
> fortified libc can still see that declared object size and reject a
> larger strlcpy bound, even though the allocation was grown.
>
> Make d_name a FLEX_ARRAY and size allocations from offsetof(). That
> matches the actual object layout with the dynamic allocation, so the
> fortified copy sees a destination whose size can grow with max_name_len.
>
> Add a regression test that creates a 261-byte non-ASCII basename and
> runs status with core.precomposeunicode enabled.
Hm. Why does macOS even allow you to create a file that has a basename
longer than NAME_MAX? Does macOS count unicode characters specially?
> diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
> index 1711794..8077f62 100644
> --- a/compat/precompose_utf8.c
> +++ b/compat/precompose_utf8.c
> @@ -19,6 +19,11 @@ typedef char *iconv_ibp;
> static const char *repo_encoding = "UTF-8";
> static const char *path_encoding = "UTF-8-MAC";
>
> +static size_t dirent_prec_psx_size(size_t max_name_len)
> +{
> + return st_add(offsetof(dirent_prec_psx, d_name), max_name_len);
> +}
> +
> static size_t has_non_ascii(const char *s, size_t maxlen, size_t *strlen_c)
> {
> const uint8_t *ptr = (const uint8_t *)s;
> @@ -114,8 +119,8 @@ const char *precompose_argv_prefix(int argc, const char **argv, const char *pref
> PREC_DIR *precompose_utf8_opendir(const char *dirname)
> {
> PREC_DIR *prec_dir = xmalloc(sizeof(PREC_DIR));
> - prec_dir->dirent_nfc = xmalloc(sizeof(dirent_prec_psx));
> - prec_dir->dirent_nfc->max_name_len = sizeof(prec_dir->dirent_nfc->d_name);
> + prec_dir->dirent_nfc = xmalloc(dirent_prec_psx_size(NAME_MAX + 1));
> + prec_dir->dirent_nfc->max_name_len = NAME_MAX + 1;
We have the `FLEX_ALLOC_MEM()` macro that would probably be a better fit
compared to introducing `dirent_prec_psx_size()`.
Also, when converting this to a flex array, can't we do better here and
allocate the structures with the right size? Otherwise, I expect that we
overallocate most of the entrise.
> @@ -145,8 +150,7 @@ struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
> int ret_errno = errno;
>
> if (new_maxlen > prec_dir->dirent_nfc->max_name_len) {
> - size_t new_len = sizeof(dirent_prec_psx) + new_maxlen -
> - sizeof(prec_dir->dirent_nfc->d_name);
> + size_t new_len = dirent_prec_psx_size(new_maxlen);
>
> prec_dir->dirent_nfc = xrealloc(prec_dir->dirent_nfc, new_len);
> prec_dir->dirent_nfc->max_name_len = new_maxlen;
Okay, here we indeed have to realloc though, and thus we can't quite
avoid `dirent_prec_psx_size()`. Too bad.
Thanks!
Patrick
next prev parent reply other threads:[~2026-07-03 8:41 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-03 2:35 [PATCH] precompose_utf8: use a flex array for d_name Ihar Hrachyshka
2026-07-03 5:08 ` Torsten Bögershausen
2026-07-03 8:39 ` Junio C Hamano
2026-07-03 8:40 ` Patrick Steinhardt [this message]
2026-07-03 20:20 ` Ihar Hrachyshka
2026-07-04 23:37 ` [PATCH v2] " Ihar Hrachyshka
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=akd1m6KoUh7N8yyE@pks.im \
--to=ps@pks.im \
--cc=git@vger.kernel.org \
--cc=ihar.hrachyshka@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.