From: Naveed Khan Date: Mon, 13 Jul 2026 13:16:47 +0000 (+0530) Subject: libctf: bounds-check forward ctt_type before indexing pop[] X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e375c6e25f1a024c5573982f36b64f2bec57449e;p=thirdparty%2Fbinutils-gdb.git libctf: bounds-check forward ctt_type before indexing pop[] init_static_types_internal() walks the CTF type section that comes directly from an object file's .ctf section. During the first counting pass it treats a CTF_K_FORWARD record's ctt_type as the CTF_K_* kind of the forwarded tag and bumps the corresponding population count: if (kind == CTF_K_FORWARD) pop[tp->ctt_type]++; pop[] is a fixed-size stack array with CTF_K_MAX + 1 (64) entries, but ctt_type is a 32-bit value read straight from the file and is never validated. A crafted dict whose forward record carries a ctt_type greater than CTF_K_MAX therefore causes an out-of-bounds write to the stack at an attacker-controlled index. The type walk is reachable from ctf_bufopen()/ctf_open(), i.e. whenever libctf opens a dict: ld while linking CTF, and objdump/nm --ctf. The second pass already tolerates an out-of-range ctt_type (ctf_name_table() has a default case), so only this first-pass index was unguarded. Reject a ctt_type outside the valid kind range as ECTF_CORRUPT, matching the existing corruption handling in the same loop. Reproduced with a 65-byte in-memory dict (one CTF_K_FORWARD record whose ctt_type is 64) passed to ctf_bufopen(). Before the fix, AddressSanitizer reports a stack-buffer-overflow at ctf-open.c:759 overflowing pop[64]; after the fix ctf_bufopen() returns ECTF_CORRUPT. Valid forwards (ctt_type of CTF_K_STRUCT/UNION/ENUM) and the boundary value CTF_K_MAX still open successfully. Signed-off-by: Naveed Khan --- diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c index 584d502a29e..73ff1ab7a6d 100644 --- a/libctf/ctf-open.c +++ b/libctf/ctf-open.c @@ -754,9 +754,15 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth, return ECTF_CORRUPT; /* For forward declarations, ctt_type is the CTF_K_* kind for the tag, - so bump that population count too. */ + so bump that population count too. A corrupt dict may store an + out-of-range kind here, so guard against indexing pop[] out of + bounds. */ if (kind == CTF_K_FORWARD) - pop[tp->ctt_type]++; + { + if (tp->ctt_type > CTF_K_MAX) + return ECTF_CORRUPT; + pop[tp->ctt_type]++; + } tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes); pop[kind]++;