-
Notifications
You must be signed in to change notification settings - Fork 109
[Security] Integer overflow in cbor_builder_map_start_callback() via size*2 wraparound #415
Description
Summary
Integer overflow in cbor_builder_map_start_callback() allows size * 2 to wrap around, corrupting the parser's subitem tracking state when processing a crafted CBOR map declaration.
Vulnerability Details
- Type: Integer Overflow (CWE-190)
- Severity: High
- Location:
src/cbor/internal/builder_callbacks.c, line 327 - Function:
cbor_builder_map_start_callback - Affected versions: All versions up to and including current master (tested on commit
e1f711a)
Description
When parsing a definite-length CBOR map, cbor_builder_map_start_callback computes the number of expected sub-items as size * 2 (since each map entry has a key and a value):
void cbor_builder_map_start_callback(void* context, uint64_t size) {
struct _cbor_decoder_context* ctx = context;
CHECK_LENGTH(ctx, size);
cbor_item_t* res = cbor_new_definite_map(size);
CHECK_RES(ctx, res);
if (size > 0) {
PUSH_CTX_STACK(ctx, res, size * 2); // <-- overflow hereThe CHECK_LENGTH macro only checks size > SIZE_MAX, but does not check whether size * 2 overflows size_t. On 64-bit platforms with memory overcommit enabled, if size is in the range (SIZE_MAX/2, SIZE_MAX], the allocation cbor_new_definite_map(size) may succeed (due to lazy allocation), but size * 2 silently wraps to a small value.
This causes the parser's stack to track an incorrect (very small) subitems count. The parser will prematurely consider the map complete after only a few items, potentially corrupting the parse tree by appending subsequent items to incorrect parent containers.
Root Cause
Missing overflow check on the size * 2 multiplication before passing to PUSH_CTX_STACK.
Impact
- Parse tree corruption leading to incorrect data interpretation
- On systems with memory overcommit (common on Linux), this can be triggered with crafted input
- Applications relying on
cbor_load()to parse untrusted CBOR data are affected
Proof of Concept
A CBOR input encoding a definite map with size = SIZE_MAX/2 + 1:
On a 64-bit system: \xbb\x80\x00\x00\x00\x00\x00\x00\x01 (map with 2^63 + 1 pairs)
This passes CHECK_LENGTH (since the value fits in size_t), and size * 2 overflows to 2.
Suggested Fix
Add an overflow check before the multiplication:
if (size > SIZE_MAX / 2) {
cbor_decref(&res);
ctx->creation_failed = true;
return;
}
PUSH_CTX_STACK(ctx, res, size * 2);Affected Version
Tested on latest master commit. All prior versions likely affected.