Fix segfault in StoreAddressSearchMatch on GMime 3

Passing NULL for "use default options" to internet_address_list_parse()
and internet_address_list_to_string() relies on GMime's parser/format
options singleton accessors (g_mime_parser_options_get_default(),
g_mime_format_options_get_default()) always returning a valid object.
At least the GMime 3.2.15 build shipped on Debian Trixie has a broken
singleton that returns NULL instead, and the parser/formatter then
dereferences that NULL unconditionally rather than falling back to
safe defaults -- a reliable segfault on any input, not just malformed
ones. Reproduced live in a Debian Trixie container (gdb backtrace
through g_mime_parser_options_get_warning_callback() and
g_mime_format_options_get_newline()), fixed by allocating our own
short-lived options objects instead of relying on NULL, and confirmed
against both the real store-address-search CTest under GMime 3.2.15 in
that container and the full local suite under GMime 2.6.23.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mario Fetka
2026-08-01 11:43:47 +02:00
parent 3b133a825e
commit 57d38fc6fc
+21 -5
View File
@@ -57,15 +57,31 @@ StoreAddressSearchMatch(const char *header_value, const char *substring)
if (*substring == '\0') return TRUE;
#if GMIME_MAJOR_VERSION >= 3
addresses = internet_address_list_parse(NULL, header_value);
/* Do not pass NULL for "use default options": at least some packaged
* GMime 3 builds (observed with GMime 3.2.15 on Debian Trixie) have a
* broken g_mime_parser_options_get_default()/g_mime_format_options_
* get_default() singleton that returns NULL instead of a real default
* object, and the parser/formatter then dereferences that NULL
* unconditionally instead of falling back to safe defaults -- a
* reliable segfault on any input, confirmed live in a Debian Trixie
* container. Allocate our own options objects instead. */
{
GMimeParserOptions *parser_options = g_mime_parser_options_new();
GMimeFormatOptions *format_options = g_mime_format_options_new();
addresses = internet_address_list_parse(parser_options, header_value);
if (!addresses) {
g_mime_parser_options_free(parser_options);
g_mime_format_options_free(format_options);
return Utf8ContainsCasefolded(header_value, substring);
}
normalized = internet_address_list_to_string(addresses, format_options, FALSE);
g_mime_parser_options_free(parser_options);
g_mime_format_options_free(format_options);
}
#else
addresses = internet_address_list_parse_string(header_value);
#endif
if (!addresses)
return Utf8ContainsCasefolded(header_value, substring);
#if GMIME_MAJOR_VERSION >= 3
normalized = internet_address_list_to_string(addresses, NULL, FALSE);
#else
normalized = internet_address_list_to_string(addresses, FALSE);
#endif
found = Utf8ContainsCasefolded(normalized, substring);