Skip to content

[Security] Integer overflow in cbor_builder_map_start_callback() via size*2 wraparound #415

@Benjamin608608

Description

@Benjamin608608

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 here

The 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions