Skip to content

Conversation

@thevilledev
Copy link
Contributor

CBOR encodes negative integers as "-1 - n" where n is uint64_t. When n > INT64_MAX, casting to int64_t caused undefined behavior and silent data corruption. Large negative values were incorrectly parsed as positive integers (e.g., -9223372036854775809 became 9223372036854775807).

Add bounds check for to reject values that exceed int64_t representable range, returning parse_error instead of silently corrupting data.

Added regression test cases to verify.

  • The changes are described in detail, both the what and why.
  • If applicable, an existing issue is referenced.
  • The Code coverage remained at 100%. A test case for every new line of code.
  • If applicable, the documentation is updated.
  • The source code is amalgamated by running make amalgamate.

@github-actions
Copy link

🔴 Amalgamation check failed! 🔴

The source code has not been amalgamated. @thevilledev
Please read and follow the Contribution Guidelines.

@thevilledev thevilledev force-pushed the fix/cbor-int-overflow branch from a17996e to 47d033b Compare December 21, 2025 10:13
@coveralls
Copy link

coveralls commented Dec 21, 2025

Coverage Status

coverage: 99.192% (+0.001%) from 99.191%
when pulling c3f4e5b on thevilledev:fix/cbor-int-overflow
into 7c2b2ed on nlohmann:develop.

CBOR encodes negative integers as "-1 - n" where n is uint64_t. When
n > INT64_MAX, casting to int64_t caused undefined behavior and silent
data corruption. Large negative values were incorrectly parsed as
positive integers (e.g., -9223372036854775809 became 9223372036854775807).

Add bounds check for to reject values that exceed int64_t
representable range, returning parse_error instead of silently
corrupting data.

Added regression test cases to verify.

Signed-off-by: Ville Vesilehto <[email protected]>
@thevilledev thevilledev force-pushed the fix/cbor-int-overflow branch from 47d033b to aeff909 Compare December 21, 2025 12:19
Copy link
Owner

@nlohmann nlohmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@nlohmann nlohmann added the review needed It would be great if someone could review the proposed changes. label Dec 21, 2025
@nlohmann
Copy link
Owner

It would be great to have a second opinion here. @gregmarr

Copy link
Contributor

@gregmarr gregmarr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure that the tests are testing what they should be. It should be testing getting a result of int64 max, and getting a result of int64 max + 1 failing, but it looks like it's testing putting the bit patterns for those values in the CBOR data and then checking for the results from those bit patterns.

I should be sleeping now, maybe it will make more sense tomorrow.

@thevilledev
Copy link
Contributor Author

It should be testing getting a result of int64 max, and getting a result of int64 max + 1 failing

So the tests are specifically for CBOR type 0x3B (negative integers). The formula for result is result = -1 - n and it can (or should) only produce negative results. Therefore result of INT64_MAX is not applicable here. The boundaries being tested are:

  • n=INT64_MAX => result = INT64_MIN implying the most negative representable value
  • n=INT64_MAX + 1 => result = INT64_MIN - 1 overflows & rejected

I ran the tests against develop branch with ./build/tests/test-cbor_cpp11 "Tagged values" and got this:

TEST CASE:  Tagged values
  negative integer overflow
  n = INT64_MAX + 1 causes overflow

/git/json/tests/src/unit-cbor.cpp:2712: ERROR: CHECK_THROWS_WITH_AS( _ = json::from_cbor(input), "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: negative integer overflow", json::parse_error ) did NOT throw at all!

---

TEST CASE:  Tagged values
  negative integer overflow
  n = UINT64_MAX causes overflow

/git/json/tests/src/unit-cbor.cpp:2722: ERROR: CHECK_THROWS_WITH_AS( _ = json::from_cbor(input), "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: negative integer overflow", json::parse_error ) did NOT throw at all!

---

TEST CASE:  Tagged values
  negative integer overflow
  overflow with allow_exceptions=false returns discarded

/git/json/tests/src/unit-cbor.cpp:2729: ERROR: CHECK( result.is_discarded() ) is NOT correct!
  values: CHECK( false )

For positive integers (type 0x1B) we use number_unsigned so it doesn't have an equivalent overflow issue.

But of course welcome to other ideas how to test this. I guess we could check that there's no sign flip, i.e. negative results are never positive?

@gregmarr
Copy link
Contributor

Like I said, don't review code when you should be sleeping. :)

I mostly deal with floating point, where "min" refers to the smallest possible positive number, rather than integers, where it refers to the negative number with the largest magnitude, so I often mix up the integer min unless I really stop and think about it, and I was definitely not doing that properly.

I agree that we should be testing -1 which should work as a round trip, 0 which should fail, int64_min which should work as a round trip, and int64_min - 1 which should fail.

Add test for "n=0" case (result=-1) to cover the smallest magnitude
boundary. Update comments to explain CBOR 0x3B encoding and why
"result=0" is not possible. Clarify that n is an unsigned integer
in the formula "result = -1 - n" to help understanding the tests.

Signed-off-by: Ville Vesilehto <[email protected]>
@thevilledev
Copy link
Contributor Author

np, no worries! I clarified the tests a bit, hopefully covering the boundaries fully now. Let me know what you think 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

M review needed It would be great if someone could review the proposed changes. tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants