-
Notifications
You must be signed in to change notification settings - Fork 109
[Security] Uncontrolled memory allocation in cbor_load() allows DoS via small crafted input #418
Description
Summary
Uncontrolled memory allocation in cbor_load() allows a small crafted CBOR input (as few as 5 bytes) to trigger allocation of gigabytes of memory, causing denial of service.
Vulnerability Details
- Type: Uncontrolled Resource Consumption (CWE-400)
- Severity: Medium
- Location:
src/cbor/arrays.cline 105,src/cbor/maps.c(similar), triggered viasrc/cbor/internal/builder_callbacks.clines 298 and 324 - Affected versions: All versions up to and including current master
Description
When cbor_load() processes a definite-length array or map, it pre-allocates memory for all declared elements without any upper bound check. The CBOR format allows declaring up to 2^64 - 1 elements in just 9 bytes of header.
In builder_callbacks.c:
void cbor_builder_array_start_callback(void* context, uint64_t size) {
CHECK_LENGTH(ctx, size);
cbor_item_t* res = cbor_new_definite_array(size); // allocates size * 8 bytesIn arrays.c:
cbor_item_t* cbor_new_definite_array(size_t size) {
cbor_item_t** data = _cbor_alloc_multiple(sizeof(cbor_item_t*), size);
// No upper bound on size — allocates size * sizeof(pointer) bytesCHECK_LENGTH only ensures the value fits in size_t, not that the resulting allocation is reasonable.
Impact
- 5-byte input
\x9a\x11\x27\x00\x00declares an array of ~287 million elements, attempting to allocate ~2.3 GB - 9-byte input can request allocation up to 128 GB (on 64-bit systems)
- Denial of service for any application parsing untrusted CBOR data via
cbor_load() - Confirmed via fuzzing: 4 distinct OOM crashes found within seconds
Proof of Concept
OOM-triggering inputs (hex):
9a11270000 — array(0x11270000) = ~287M elements → ~2.3 GB allocation
9abb939390ff — nested arrays triggering cascading allocations
Suggested Fix
Add a configurable maximum allocation limit, similar to how other parsers handle this:
// Option 1: Add a compile-time limit
#ifndef CBOR_MAX_DEFINITE_ITEMS
#define CBOR_MAX_DEFINITE_ITEMS (1024 * 1024) // 1M items
#endif
void cbor_builder_array_start_callback(void* context, uint64_t size) {
CHECK_LENGTH(ctx, size);
if (size > CBOR_MAX_DEFINITE_ITEMS) {
ctx->creation_failed = true;
return;
}
// ... proceed with allocationOr provide a runtime-configurable limit via the decoder context.
Affected Version
Tested on latest master commit. All prior versions likely affected.