-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
fix(cbor): reject overflowing negative integers #5039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🔴 Amalgamation check failed! 🔴The source code has not been amalgamated. @thevilledev |
a17996e to
47d033b
Compare
47d033b to
aeff909
Compare
nlohmann
left a comment
There was a problem hiding this 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.
|
It would be great to have a second opinion here. @gregmarr |
gregmarr
left a comment
There was a problem hiding this 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.
So the tests are specifically for CBOR type
I ran the tests against For positive integers (type 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? |
|
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 |
|
np, no worries! I clarified the tests a bit, hopefully covering the boundaries fully now. Let me know what you think 👍 |
|
Quick question: don't we have the same situation with int32 overflow? #include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;
int main() {
const std::vector<uint8_t> input = {0x3A, 0x80, 0x00, 0x00, 0x00};
auto j = json::from_cbor(input);
std::cout << j << '\n';
}Instead of printing |
|
I gotta say I totally missed the Thanks for pointing this out! |
|
Come to think of it, I think adding a check also for the other types would be consequent. |
|
Sure, I'll add those while at it |
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 <ville@vesilehto.fi>
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 <ville@vesilehto.fi>
c3f4e5b to
7d335c0
Compare
7d335c0 to
fd60a2a
Compare
|
Hmm, tests failing only on Windows clang-cl-12 (x64) failing due to:
The new boundary checks introduce switch-case-local variables (number, max_val). Since Is this test flaky in general? Or should we try breaking the logic down to a helper function? I'm not sure if this would get inlined though: |
Oh no!
That's not good...
No, the test was not flaky so far. |
Extend negative integer overflow detection to all CBOR negative integer cases (0x38, 0x39, 0x3A) for consistency with the existing 0x3B check. Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
fd60a2a to
482de87
Compare
|
Looks like it's fixed now 👍 |
nlohmann
left a comment
There was a problem hiding this 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.
Thanks! This is much cleaner now! |
Motivation
CBOR encodes negative integers as "-1 - n" where n is an unsigned integer. Per RFC 8949 Section 5.5:
and:
When n exceeds the representable range of
number_integer_t, the computation causes undefined behaviour and silent data corruption.For the default
int64_ttype:n = 0x8000000000000000) was incorrectly parsed as 9223372036854775807For custom 32-bit configurations (
int32_t):n = 0x80000000) would similarly overflowChanges
Add bounds checks for all CBOR negative integer types (
0x38,0x39,0x3A,0x3B) to reject values exceedingnumber_integer_trange, returningparse_error.112instead of silently corrupting data.Add regression tests for:
Overflow detection at boundary values
Truncated input handling
Custom
int32_tinteger type configurationsThe 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.