From a307ef9467c3a7cbe041faa2f33ee2bbe7412bae Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Tue, 24 Mar 2026 14:15:09 +0000 Subject: [PATCH] sanitizer: Fix reported issues coap_new_cache_entry() does not correctly check for no PDU data when called with COAP_CACHE_RECORD_PDU. No current libcoap code (examples and library) call coap_new_cache_entry() with COAP_CACHE_RECORD_PDU set. Internal function coap_pdu_resize() can be used to reduce a PDU size, creating current options confusion. Fix is not to reduce PDU if new size is smaller than the current used size. No current libcoap code calls coap_pdu_resize() to reduce the size. If there is an issue with the PDU options where the maximum used option value is larger than the last defined option value, an assert() is triggered. All of the coap_*_option() functions correctly manage pdu->max_opt, but this issue could occur if coap_pdu_resize() was called to reduce the PDU size below that of pdu->used_size. --- src/coap_cache.c | 14 +------------- src/coap_pdu.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/coap_cache.c b/src/coap_cache.c index fa1c9bfa..7811db74 100644 --- a/src/coap_cache.c +++ b/src/coap_cache.c @@ -192,19 +192,7 @@ coap_new_cache_entry_lkd(coap_session_t *session, const coap_pdu_t *pdu, memset(entry, 0, sizeof(coap_cache_entry_t)); entry->session = session; if (record_pdu == COAP_CACHE_RECORD_PDU) { - entry->pdu = coap_pdu_init(pdu->type, pdu->code, pdu->mid, pdu->alloc_size); - if (entry->pdu) { - if (!coap_pdu_resize(entry->pdu, pdu->alloc_size)) { - coap_delete_pdu_lkd(entry->pdu); - coap_free_type(COAP_CACHE_ENTRY, entry); - return NULL; - } - /* Need to get the appropriate data across */ - memcpy(entry->pdu, pdu, offsetof(coap_pdu_t, token)); - memcpy(entry->pdu->token, pdu->token, pdu->used_size); - /* And adjust all the pointers etc. */ - entry->pdu->data = entry->pdu->token + (pdu->data - pdu->token); - } + entry->pdu = coap_const_pdu_reference_lkd(pdu); } entry->cache_key = coap_cache_derive_key(session, pdu, session_based); if (!entry->cache_key) { diff --git a/src/coap_pdu.c b/src/coap_pdu.c index 21e2823a..d6253d12 100644 --- a/src/coap_pdu.c +++ b/src/coap_pdu.c @@ -306,10 +306,12 @@ fail: int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size) { if (new_size > pdu->alloc_size) { + /* Expanding the PDU usage */ #if !defined(WITH_LWIP) uint8_t *new_hdr; size_t offset; #endif + if (pdu->max_size && new_size > pdu->max_size) { coap_log_warn("coap_pdu_resize: pdu too big\n"); return 0; @@ -340,8 +342,8 @@ coap_pdu_resize(coap_pdu_t *pdu, size_t new_size) { else pdu->actual_token.s = &pdu->token[2]; #endif + pdu->alloc_size = new_size; } - pdu->alloc_size = new_size; return 1; } @@ -658,7 +660,12 @@ coap_insert_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, } prev_number = opt_iter.number; } - assert(option != NULL); + if (option == NULL) { + /* Code is broken somewhere */ + coap_log_warn("coap_insert_option: Broken max_opt\n"); + return 0; + } + /* size of option inc header to insert */ shift = coap_opt_encode_size(number - prev_number, len);