Skip to content

Commit 82ecc53

Browse files
committed
liblzma: Fix false Valgrind error report with GCC.
With GCC and a certain combination of flags, Valgrind will falsely trigger an invalid write. This appears to be due to the omission of instructions to properly save, set up, and restore the frame pointer. The IFUNC resolver is a leaf function since it only calls a function that is inlined. So sometimes GCC omits the frame pointer instructions in the resolver unless this optimization is explictly disabled. This fixes https://bugzilla.redhat.com/show_bug.cgi?id=2267598.
1 parent 3007e74 commit 82ecc53

File tree

3 files changed

+31
-10
lines changed

3 files changed

+31
-10
lines changed

src/liblzma/check/crc32_fast.c

+3-6
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,12 @@ typedef uint32_t (*crc32_func_type)(
135135
// This resolver is shared between all three dispatch methods. It serves as
136136
// the ifunc resolver if ifunc is supported, otherwise it is called as a
137137
// regular function by the constructor or first call resolution methods.
138-
// The __no_profile_instrument_function__ attribute support is checked when
139-
// determining if ifunc can be used, so it is safe to use here.
140-
#ifdef CRC_USE_IFUNC
141-
__attribute__((__no_profile_instrument_function__))
142-
#endif
138+
// The funcion attributes are needed for safe IFUNC resolver usage with GCC.
139+
lzma_resolver_attributes
143140
static crc32_func_type
144141
crc32_resolve(void)
145142
{
146-
return is_arch_extension_supported()
143+
return is_arch_extension_supported()
147144
? &crc32_arch_optimized : &crc32_generic;
148145
}
149146

src/liblzma/check/crc64_fast.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,12 @@ typedef uint64_t (*crc64_func_type)(
9898
# pragma GCC diagnostic ignored "-Wunused-function"
9999
#endif
100100

101-
#ifdef CRC_USE_IFUNC
102-
__attribute__((__no_profile_instrument_function__))
103-
#endif
101+
// The funcion attributes are needed for safe IFUNC resolver usage with GCC.
102+
lzma_resolver_attributes
104103
static crc64_func_type
105104
crc64_resolve(void)
106105
{
107-
return is_arch_extension_supported()
106+
return is_arch_extension_supported()
108107
? &crc64_arch_optimized : &crc64_generic;
109108
}
110109

src/liblzma/check/crc_common.h

+25
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,31 @@
128128
# endif
129129
#endif
130130

131+
#ifdef CRC_USE_IFUNC
132+
// Two function attributes are needed to make IFUNC safe with GCC.
133+
//
134+
// no-omit-frame-pointer prevents false Valgrind issues when combined with
135+
// a few other compiler flags. The optimize attribute is supported on
136+
// GCC >= 4.4 and is not supported with Clang.
137+
# if TUKLIB_GNUC_REQ(4,4) && !defined(__clang__)
138+
# define no_omit_frame_pointer \
139+
__attribute__((optimize("no-omit-frame-pointer")))
140+
# else
141+
# define no_omit_frame_pointer
142+
# endif
143+
144+
// The __no_profile_instrument_function__ attribute support is checked when
145+
// determining if ifunc can be used, so it is safe to use unconditionally.
146+
// This attribute is needed because GCC can add profiling to the IFUNC
147+
// resolver, which calls functions that have not yet been relocated leading
148+
// to a crash on liblzma start up.
149+
# define lzma_resolver_attributes \
150+
__attribute__((__no_profile_instrument_function__)) \
151+
no_omit_frame_pointer
152+
#else
153+
# define lzma_resolver_attributes
154+
#endif
155+
131156
// For CRC32 use the generic slice-by-eight implementation if no optimized
132157
// version is available.
133158
#if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC)

0 commit comments

Comments
 (0)