Skip to content

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

Merged
merged 14 commits into from
Jul 24, 2023

Conversation

joshbsiegel
Copy link
Contributor

@joshbsiegel joshbsiegel commented Jul 19, 2023

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

@joshbsiegel joshbsiegel marked this pull request as draft July 19, 2023 17:42
@joshbsiegel joshbsiegel changed the title Cdriver 4662 CDRIVER-4662 Check for Decimal128 exponent overflow Jul 19, 2023

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;
Copy link
Contributor Author

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.

Copy link
Collaborator

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.

@joshbsiegel joshbsiegel marked this pull request as ready for review July 19, 2023 20:35
@joshbsiegel joshbsiegel requested a review from kevinAlbs July 19, 2023 20:35
@@ -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);
Copy link
Collaborator

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.

Copy link
Contributor Author

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 😑

@joshbsiegel joshbsiegel requested a review from kevinAlbs July 21, 2023 22:05
@kevinAlbs kevinAlbs requested a review from vector-of-bool July 24, 2023 18:04
Copy link
Contributor

@vector-of-bool vector-of-bool left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Collaborator

@kevinAlbs kevinAlbs left a 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

Comment on lines 589 to 590
if (!read_exponent || nread == 0 || temp_exponent > (int64_t) INT32_MAX ||
temp_exponent < (int64_t) INT32_MIN) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
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;
Copy link
Collaborator

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.

@joshbsiegel joshbsiegel merged commit c3587f1 into mongodb:master Jul 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants