-
Notifications
You must be signed in to change notification settings - Fork 109
[Security] NULL pointer dereference in cbor_serialized_size() and cbor_serialize_tag() via cbor_move(cbor_tag_item()) #416
Description
Summary
NULL pointer dereference in cbor_serialized_size() and cbor_serialize_tag() via cbor_move(cbor_tag_item()) when a tag item has no tagged item set, introduced by incomplete fix in commit e87cc36.
Vulnerability Details
- Type: NULL Pointer Dereference (CWE-476)
- Severity: Medium
- Location:
src/cbor/serialization.c, lines 146 and 371 - Functions:
cbor_serialized_size,cbor_serialize_tag - Affected versions: All versions since commit
e87cc36(which madecbor_tag_item()return NULL when no item is set)
Description
Commit e87cc36 correctly changed cbor_tag_item() to return NULL when no tagged item is set. However, several call sites were not updated to handle the new NULL return value.
In cbor_serialized_size (line 146):
case CBOR_TYPE_TAG: {
return _cbor_safe_signaling_add(
_cbor_encoded_header_size(cbor_tag_value(item)),
cbor_serialized_size(cbor_move(cbor_tag_item(item))));
}In cbor_serialize_tag (line 371):
size_t item_written = cbor_serialize(cbor_move(cbor_tag_item(item)),
buffer + written, buffer_size - written);cbor_move() unconditionally dereferences its argument (item->refcount--), so passing NULL causes a crash.
The same pattern also exists in cbor.c:
- Line 287:
cbor_copy()for tags - Line 424:
cbor_copy_definite()for tags - Line 550:
_cbor_nested_describe()for tags
Root Cause
Incomplete fix: cbor_tag_item() was updated to return NULL, but callers using cbor_move(cbor_tag_item(...)) were not updated to check for NULL first.
Impact
- Crash (segfault) when serializing, copying, or describing a tag item that has no tagged item set
- While
cbor_load()always produces tags with items set, users constructing CBOR items via the API can trigger this - Libraries building on libcbor that construct tags programmatically are at risk
Proof of Concept
#include "cbor.h"
int main() {
cbor_item_t* tag = cbor_new_tag(42);
// Do NOT call cbor_tag_set_item() -- leave item unset
size_t size = cbor_serialized_size(tag); // CRASH: NULL deref
// Or:
// size_t buf_size;
// unsigned char* buf;
// cbor_serialize_alloc(tag, &buf, &buf_size); // Also crashes
cbor_decref(&tag);
return 0;
}Suggested Fix
Add NULL checks before cbor_move() at all affected call sites:
// serialization.c line 146
case CBOR_TYPE_TAG: {
cbor_item_t* tagged = cbor_tag_item(item);
if (tagged == NULL) return 0;
return _cbor_safe_signaling_add(
_cbor_encoded_header_size(cbor_tag_value(item)),
cbor_serialized_size(cbor_move(tagged)));
}
// serialization.c line 371
cbor_item_t* tagged = cbor_tag_item(item);
if (tagged == NULL) return written;
size_t item_written = cbor_serialize(cbor_move(tagged),
buffer + written, buffer_size - written);Apply similar fixes in cbor.c at lines 287, 424, and 550.
Affected Version
Tested on latest master commit. Affects all versions since commit e87cc36.