[Bug 3191] New: Segmentation fault in string.c
Exim Bugzilla via Exim-dev <[email protected]> Thu, 22 Jan 2026 16:02:54 +0000
| Newsgroups | gmane.mail.exim.devel |
|---|---|
| Message-ID | <[email protected]/> |
https://bugs.exim.org/show_bug.cgi?id=3191
Bug ID: 3191
Summary: Segmentation fault in string.c
Product: Exim
Version: 4.99
Hardware: x86-64
OS: Linux
Status: NEW
Severity: bug
Priority: medium
Component: General execution
Assignee: [email protected]
Reporter: [email protected]
CC: [email protected]
Created attachment 1530
--> https://bugs.exim.org/attachment.cgi?id=1530&action=edit
File with crash input
I have found segmentation fault in string.c:1887 in string_vformat_trc()
function:
g->ptr += sprintf(gp, l_align ? "%-*.*s" : "%*.*s", width, precision, s);
The error happens when *gp pointer is NULL and is transferred to sprintf()
function.
The real reason of this error is place here (log_vwrite in log.c) on line 855:
gstring gs = { .size = LOG_BUFFER_SIZE-2, .ptr = 0, .s = log_buffer };
Since log_buffer is NULL, the gs.s member is NULL too.
Then on line 878 log_buffer is checked for NULL and memory is allocated for
log_buffer. But gs.s is still NULL:
if (!log_buffer)
{
if (!(log_buffer = US malloc(LOG_BUFFER_SIZE)))
In string_vformat_trc() gs.s becomes *gp pointer:
gp = CS g->s + g->ptr;
This is ASAN report:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1670813==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc
0x7bd75fc875fe bp 0x000000000032 sp 0x7ffc25d959f0 T0)
==1670813==The signal is caused by a WRITE memory access.
==1670813==Hint: address points to the zero page.
#0 0x7bd75fc875fe in _IO_str_overflow libio/strops.c:133:28
#1 0x7bd75fc86200 in __GI__IO_default_xsputn libio/genops.c:399:24
#2 0x7bd75fc86200 in _IO_default_xsputn libio/genops.c:370:1
#3 0x7bd75fc5fc10 in outstring_func stdio-common/vfprintf-internal.c:239:16
#4 0x7bd75fc5fc10 in __vfprintf_internal
stdio-common/vfprintf-process-arg.c:427:5
#5 0x7bd75fc7b3b2 in __vsprintf_internal libio/iovsprintf.c:96:9
#6 0x7bd75fc7b3b2 in vsprintf libio/iovsprintf.c:105:10
#7 0x55a7350cae46 in vsprintf
(/exim-main/src/build-Linux-x86_64/parser_harness+0x7ce46) (BuildId:
aebaff1561b1ce6ed50579227ad593c295270eeb)
#8 0x55a7350cc21a in sprintf
(/exim-main/src/build-Linux-x86_64/parser_harness+0x7e21a) (BuildId:
aebaff1561b1ce6ed50579227ad593c295270eeb)
#9 0x55a7351a7617 in string_vformat_trc
(/exim-main/src/build-Linux-x86_64/parser_harness+0x159617) (BuildId:
aebaff1561b1ce6ed50579227ad593c295270eeb)
#10 0x55a7351b4c8a in string_fmt_append_noextend log.c
#11 0x55a7351b5dda in log_vwrite log.c
#12 0x55a7351b54b8 in log_write_die
(/exim-main/src/build-Linux-x86_64/parser_harness+0x1674b8) (BuildId:
aebaff1561b1ce6ed50579227ad593c295270eeb)
#13 0x55a7351a7e86 in string_sprintf_trc
(/exim-main/src/build-Linux-x86_64/parser_harness+0x159e86) (BuildId:
aebaff1561b1ce6ed50579227ad593c295270eeb)
#14 0x55a735211b1a in parse_forward_list
(/exim-main/src/build-Linux-x86_64/parser_harness+0x1c3b1a) (BuildId:
aebaff1561b1ce6ed50579227ad593c295270eeb)
#15 0x55a735183ffa in main
/exim-main/src/build-Linux-x86_64/../parser_harness.c:53:13
#16 0x7bd75fc2a249 in __libc_start_call_main
csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#17 0x7bd75fc2a304 in __libc_start_main csu/../csu/libc-start.c:360:3
#18 0x55a7350a43c0 in _start
(/exim-main/src/build-Linux-x86_64/parser_harness+0x563c0) (BuildId:
aebaff1561b1ce6ed50579227ad593c295270eeb)
==1670813==Register values:
rax = 0x0000000000000000 rbx = 0x00007ffc25d95ff0 rcx = 0x0000000000000000
rdx = 0x0000000000000001
rdi = 0x00007ffc25d95ff0 rsi = 0x0000000000000032 rbp = 0x0000000000000032
rsp = 0x00007ffc25d959f0
r8 = 0x000000000000ffff r9 = 0x0000000000000073 r10 = 0x000055a735d715c0
r11 = 0x000055a735d715f3
r12 = 0xffffffffffffffff r13 = 0x0000000000000000 r14 = 0x0000000000000000
r15 = 0x000055a735d715e0
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV libio/strops.c:133:28 in _IO_str_overflow
==1670813==ABORTING
Possible fix that I can suggest:
diff --git a/src/src/log.c b/src/src/log.c
index 40bdfcd0c..60f8e8d53 100644
--- a/src/src/log.c
+++ b/src/src/log.c
@@ -876,11 +876,14 @@ if (panic_recurseflag)
when running Exim proper, only when running utilities. */
if (!log_buffer)
+{
if (!(log_buffer = US malloc(LOG_BUFFER_SIZE)))
{
fprintf(stderr, "exim: failed to get store for log buffer\n");
exim_exit(EXIT_FAILURE);
}
+ gs.s = log_buffer;
+}
/* If we haven't already done so, inspect the setting of log_file_path to
determine whether to log to files and/or to syslog. Bits in logging_mode
After that I fix this bug I have found another bug in log_vwrite() in
log.c:1038:
if (f.really_exim && message_id[0])
Error happens because message_id is NULL.
ASAN report:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1675885==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc
0x634208befe4c bp 0x634208c8b4c8 sp 0x7ffee6d8f9a0 T0)
==1675885==The signal is caused by a READ memory access.
==1675885==Hint: address points to the zero page.
#0 0x634208befe4c in log_vwrite log.c
#1 0x634208bef4b8 in log_write_die
(/exim-main/src/build-Linux-x86_64/parser_harness+0x1674b8) (BuildId:
ed25fae69d25a7f65e7fdfc4b2fb7f0923e1afe5)
#2 0x634208be1e86 in string_sprintf_trc
(/exim-main/src/build-Linux-x86_64/parser_harness+0x159e86) (BuildId:
ed25fae69d25a7f65e7fdfc4b2fb7f0923e1afe5)
#3 0x634208c4bb23 in parse_forward_list
(/exim-main/src/build-Linux-x86_64/parser_harness+0x1c3b23) (BuildId:
ed25fae69d25a7f65e7fdfc4b2fb7f0923e1afe5)
#4 0x634208bbdffa in main
/exim-main/src/build-Linux-x86_64/../parser_harness.c:53:13
#5 0x7cdcd5991249 in __libc_start_call_main
csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#6 0x7cdcd5991304 in __libc_start_main csu/../csu/libc-start.c:360:3
#7 0x634208ade3c0 in _start
(/exim-main/src/build-Linux-x86_64/parser_harness+0x563c0) (BuildId:
ed25fae69d25a7f65e7fdfc4b2fb7f0923e1afe5)
==1675885==Register values:
rax = 0x00007ffee6d8fa60 rbx = 0x0000000000000007 rcx = 0x0000000000000020
rdx = 0x0000000000000000
rdi = 0x0000525000002900 rsi = 0x0000000000000014 rbp = 0x0000634208c8b4c8
rsp = 0x00007ffee6d8f9a0
r8 = 0x00000a4a00000522 r9 = 0x00000a4a7fff8520 r10 = 0x0000000000000000
r11 = 0x00006342097ab5f3
r12 = 0x0000000000000000 r13 = 0x00007ffee6d8fab8 r14 = 0x0000000000000000
r15 = 0x0000000000000002
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV log.c in log_vwrite
==1675885==ABORTING
The possible fix:
diff --git a/src/src/log.c b/src/src/log.c
index 40bdfcd0c..60f8e8d53 100644
--- a/src/src/log.c
+++ b/src/src/log.c
@@ -1032,7 +1035,7 @@ if (LOGGING(pid))
if (!syslog_pid) pid_position[1] = gstring_length(g); /* … and end+1
of the PID */
}
-if (f.really_exim && message_id[0])
+if (f.really_exim && message_id && message_id[0])
string_fmt_append_noextend(g, "%s ", message_id);
if (flags & LOG_CONFIG)
This is the test harness:
#ifndef __AFL_FUZZ_TESTCASE_LEN
ssize_t fuzz_len;
unsigned char fuzz_buf[1024000];
#define __AFL_FUZZ_TESTCASE_BUF fuzz_buf
#define __AFL_FUZZ_TESTCASE_LEN fuzz_len
#define __AFL_LOOP(x) ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0
? 1 : 0)
#define __AFL_FUZZ_INIT() void sync(void);
#define __AFL_INIT() sync()
#endif
#ifndef MAX_INPUT
#define MAX_INPUT (1 << 20)
#endif
__AFL_FUZZ_INIT();
int main(void)
{
store_init();
__AFL_INIT();
while (__AFL_LOOP(1000)) {
size_t len = __AFL_FUZZ_TESTCASE_LEN;
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
if (len == 0 || !buf ) {
return 0;
}
char *buff = (char *)malloc(len + 1);
memcpy(buff, buf, len);
buff[len] = '\0';
uschar *errmess;
address_item *anchor = NULL;
parse_forward_list(buf, -1, &anchor, &errmess, US"incoming.domain",
NULL, NULL);
free(buff);
}
return 0;
}
Build by clang with -fsanitize=address option.
Execute ./src/build-Linux-x86_64/parser_harness < crash.txt
--
You are receiving this mail because:
You are on the CC list for the bug.
--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-dev.lists.exim.org/
## unsubscribe (doesn't require an account):
## [email protected]
## Exim details at https://www.exim.org/
## Please use the Wiki with this list - https://code.exim.org/exim/wiki/wiki