-
Notifications
You must be signed in to change notification settings - Fork 455
CDRIVER-4662 Check for Decimal128 exponent overflow #1349
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
|
||
if (bson->read_state == BSON_JSON_IN_BSON_TYPE) { | ||
if (bson_decimal128_from_string (val_w_null, &decimal128) && | ||
bson->read_state == BSON_JSON_IN_BSON_TYPE) { | ||
bson->bson_type_data.v_decimal128.value = decimal128; | ||
} else { | ||
goto BAD_PARSE; |
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.
On failure, BAD_PARSE
will set the error message as
Invalid input string "0E+xxx", looking for DECIMAL128
I think this message is fine as is, but potentially could be more helpful to the user with some changes. I believe it would involve adding some return information from bson_decimal128_from_string
as to why the parsing fails (because it may not have to do with an overflowing exponent). Open to thoughts.
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 think it may help to determine the cause of the error with a new function: bson_decimal128_from_string_w_error
. But I think that is separate from this bug fix and could be considered in a future change.
@@ -581,10 +581,12 @@ bson_decimal128_from_string_w_len (const char *string, /* IN */ | |||
#else | |||
#define SSCANF sscanf | |||
#endif | |||
int read_exponent = SSCANF (++str_read, "%d%n", &exponent, &nread); | |||
int read_exponent = | |||
SSCANF (++str_read, "%" PRId64 "%n", &exponent, &nread); |
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.
Please investigate the test failures on Windows.
The definition of SSCANF
differs on Windows and may be related to the error.
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.
It ended up being an issue with not converting the INT32 max and min values to int64_t
😑
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.
LGTM
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.
LGTM with minor changes.
This is a bug fix and I think suitable for a patch release. After merging, please cherry-pick the commit to the r1.24
branch with:
git checkout --track upstream/r1.24
git cherry-pick <commit from master>
git push upstream r1.24
if (!read_exponent || nread == 0 || temp_exponent > (int64_t) INT32_MAX || | ||
temp_exponent < (int64_t) INT32_MIN) { |
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.
if (!read_exponent || nread == 0 || temp_exponent > (int64_t) INT32_MAX || | |
temp_exponent < (int64_t) INT32_MIN) { | |
if (!read_exponent || nread == 0 || !bson_in_range_int32_t_signed (temp_exponent)) { |
@@ -501,7 +501,7 @@ bson_decimal128_from_string_w_len (const char *string, /* IN */ | |||
size_t first_digit = 0; /* The index of the first non-zero digit */ | |||
size_t last_digit = 0; /* The index of the last digit */ | |||
|
|||
int32_t exponent = 0; | |||
int64_t exponent = 0; |
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.
int64_t exponent = 0; | |
int32_t exponent = 0; |
Change can be reverted since exponent
is assigned after casting to int32_t
.
|
||
if (bson->read_state == BSON_JSON_IN_BSON_TYPE) { | ||
if (bson_decimal128_from_string (val_w_null, &decimal128) && | ||
bson->read_state == BSON_JSON_IN_BSON_TYPE) { | ||
bson->bson_type_data.v_decimal128.value = decimal128; | ||
} else { | ||
goto BAD_PARSE; |
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 think it may help to determine the cause of the error with a new function: bson_decimal128_from_string_w_error
. But I think that is separate from this bug fix and could be considered in a future change.
Summary
This PR will check that the exponent on a Decimal128 does not overflow when converting from JSON to BSON.
Background
It was brought up here that the C driver does not throw an error when a user tries to convert a Decimal128 value with an exponent that doesn't fit in a 32 bit integer.
What's new
bson_decimal128_from_string
to read in the exponent as anint64_t
and checking if that number would fit in a 32 bit integer, returningfalse
on failurebson_decimal128_from_string
in_bson_json_read_string
and setting error on failurebson_new_from_json
andbson_decimal128_from_string