From bc310b3aa14d10eee24eaccaf5d59574dc2cf7ff Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 12 Jul 2026 19:37:09 +0200 Subject: [PATCH] Verify remaining bytes before every BER-TLV tag, length, and value read/advance. Signed-off-by: Pol Henarejos --- src/tlv.c | 56 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/tlv.c b/src/tlv.c index 12b082f..41dabca 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -78,30 +78,48 @@ uint8_t tlv_format_len(uint16_t len, uint8_t *out) { return 3; } -int tlv_walk(const tlv_ctx_t *ctxi, uint8_t **p, uint16_t *tag, uint16_t *tag_len, uint8_t **data) { - if (!p) { - return 0; +int tlv_walk(const tlv_ctx_t *ctxi, uint8_t **p, uint16_t *tag, uint16_t *tag_len, uint8_t **data) { + if (!ctxi || !ctxi->data || !p) { + return 0; } if (!*p) { *p = (uint8_t *) ctxi->data; } - if (*p - ctxi->data >= ctxi->len) { - return 0; - } + if (*p < ctxi->data || (size_t)(*p - ctxi->data) >= ctxi->len) { + return 0; + } uint16_t tg = 0x0, tgl = 0; - tg = *(*p)++; - if ((tg & 0x1f) == 0x1f) { - tg <<= 8; - tg |= *(*p)++; - } - tgl = *(*p)++; - if (tgl == 0x82) { - tgl = *(*p)++ << 8; - tgl |= *(*p)++; - } - else if (tgl == 0x81) { - tgl = *(*p)++; - } + tg = *(*p)++; + if ((tg & 0x1f) == 0x1f) { + if ((size_t)(*p - ctxi->data) >= ctxi->len) { + return 0; + } + tg <<= 8; + tg |= *(*p)++; + } + if ((size_t)(*p - ctxi->data) >= ctxi->len) { + /* Some OATH commands use a trailing tag as a zero-length marker. */ + tgl = 0; + } + else { + tgl = *(*p)++; + } + if (tgl == 0x82) { + if (ctxi->len - (size_t)(*p - ctxi->data) < 2) { + return 0; + } + tgl = *(*p)++ << 8; + tgl |= *(*p)++; + } + else if (tgl == 0x81) { + if ((size_t)(*p - ctxi->data) >= ctxi->len) { + return 0; + } + tgl = *(*p)++; + } + if (tgl > ctxi->len - (size_t)(*p - ctxi->data)) { + return 0; + } if (tag) { *tag = tg; }