From 46208be836e6598b9879166612c7deeb8562d16d Mon Sep 17 00:00:00 2001 From: Chris Hoffman Date: Tue, 10 Feb 2026 16:56:20 +0800 Subject: [PATCH] futils: fix undefined behavior in O_FSYNC fallback definition The fallback definition of O_FSYNC uses `(1 << 31)`, which is undefined behavior in C. The literal `1` is a signed int, and left-shifting into the sign bit of a signed integer is undefined per the C standard. This causes crashes on arm64 Linux with musl libc (which doesn't define O_FSYNC), manifesting as: thread panic: left shift of 1 by 31 places cannot be represented in type 'int' Fall back to O_SYNC when available, since it is the POSIX standard name for the same flag. On platforms where neither is defined (e.g. Windows), use (1 << 30) as a sentinel value that avoids the sign bit. --- src/util/futils.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/util/futils.h b/src/util/futils.h index 7ae869be6..38894dafd 100644 --- a/src/util/futils.h +++ b/src/util/futils.h @@ -32,9 +32,17 @@ extern int git_futils_readbuffer_fd(git_str *obj, git_file fd, size_t len); /* Additional constants for `git_futils_writebuffer`'s `open_flags`. We * support these internally and they will be removed before the `open` call. + * + * Not all platforms define O_FSYNC. Fall back to O_SYNC (the POSIX + * standard name; O_FSYNC is a non-standard alias) when available, + * otherwise use a sentinel value that won't collide with real open + * flags. Avoid (1 << 31) since left-shifting into the sign bit of + * a signed int is undefined behavior. */ -#ifndef O_FSYNC -# define O_FSYNC (1 << 31) +#if !defined(O_FSYNC) && defined(O_SYNC) +# define O_FSYNC O_SYNC +#elif !defined(O_FSYNC) +# define O_FSYNC (1 << 30) #endif extern int git_futils_writebuffer(