[binutils-gdb] libctf: bounds-check forward ctt_type before indexing pop[]
Alan Modra
amodra@sourceware.org
Thu Jul 16 00:18:43 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e375c6e25f1a024c5573982f36b64f2bec57449e
commit e375c6e25f1a024c5573982f36b64f2bec57449e
Author: Naveed Khan <naveed@digiscrypt.com>
Date: Mon Jul 13 18:46:47 2026 +0530
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 <naveed@digiscrypt.com>
Diff:
---
libctf/ctf-open.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
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]++;
More information about the Binutils-cvs
mailing list