Summary
ares_parse() (opendmarc/opendmarc-ar.c:455) parses an
Authentication-Results: header with an unbounded n++ -- there is no check
against MAXARESULTS (16). struct authres embeds ares_result[16], each
~8.5KB, declared as a stack local in mlfi_eom. A header with more than 16
;-separated results overflows the stack array (WRITE of size 4 per extra
result at :458/:476/...). Reachable remote, pre-auth: parsing happens in
mlfi_eom before the trust check.
CWE-787 / CWE-121. CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H = 7.5 High.
Affected version
OpenDMARC current master (opendmarc/opendmarc-ar.c:455; MAXARESULTS=16).
Root cause
opendmarc/opendmarc-ar.c:
struct authres ar; // stack local in mlfi_eom (opendmarc.c:2350)
...
case 3:
...
n++; // :455 -- no check against MAXARESULTS (16)
struct authres embeds struct result ares_result[MAXARESULTS] with
MAXARESULTS = 16 (opendmarc-ar.h:82); each struct result is ~8.5KB
(result_property[16][257], result_value[16][257]). The state machine
re-enters case 3 on every ; and does n++ each time; ares_convert()
returns an UNKNOWN enum for unrecognized names but does not error, so
parsing continues past 16 results.
PoC (attachment)
See attached gist: https://gist.github.com/afldl/6d1b6c4520b6f82c26649a777b42ba23
| File |
Purpose |
harness.c |
Reproducer: drives ares_parse with 17 results into ares_result[16] |
stubs.c / build-config.h |
Build support |
repro.sh |
Full ASAN build + run |
asan_output.txt |
Real ASAN output |
Reproduction:
bash repro.sh # or gcc -fsanitize=address harness.c stubs.c -o poc && ./poc
Expected output (real, ASAN):
calling ares_parse with 17 results (ares_result[16] array)
==445813==ERROR: AddressSanitizer: stack-buffer-overflow
WRITE of size 4
#0 0x... in ares_parse opendmarc/opendmarc-ar.c:458:41
Suggested fix
Bound n against MAXARESULTS:
if (n >= MAXARESULTS) { /* reject / stop parsing */ }
n++;
Credit
Reported by afldl, 2026-07.
Summary
ares_parse()(opendmarc/opendmarc-ar.c:455) parses anAuthentication-Results:header with an unboundedn++-- there is no checkagainst
MAXARESULTS(16).struct authresembedsares_result[16], each~8.5KB, declared as a stack local in
mlfi_eom. A header with more than 16;-separated results overflows the stack array (WRITE of size 4 per extraresult at :458/:476/...). Reachable remote, pre-auth: parsing happens in
mlfi_eombefore the trust check.CWE-787 / CWE-121. CVSS 3.1:
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H= 7.5 High.Affected version
OpenDMARC current master (
opendmarc/opendmarc-ar.c:455; MAXARESULTS=16).Root cause
opendmarc/opendmarc-ar.c:struct authresembedsstruct result ares_result[MAXARESULTS]withMAXARESULTS = 16 (opendmarc-ar.h:82); each
struct resultis ~8.5KB(
result_property[16][257],result_value[16][257]). The state machinere-enters
case 3on every;and doesn++each time;ares_convert()returns an UNKNOWN enum for unrecognized names but does not error, so
parsing continues past 16 results.
PoC (attachment)
See attached gist: https://gist.github.com/afldl/6d1b6c4520b6f82c26649a777b42ba23
harness.cstubs.c/build-config.hrepro.shasan_output.txtReproduction:
bash repro.sh # or gcc -fsanitize=address harness.c stubs.c -o poc && ./pocExpected output (real, ASAN):
Suggested fix
Bound
nagainst MAXARESULTS:Credit
Reported by afldl, 2026-07.