Skip to content

Commit c3587f1

Browse files
authored
CDRIVER-4662 check for decimal128 exponent overflow (#1349)
1 parent ac436db commit c3587f1

File tree

4 files changed

+126
-4
lines changed

4 files changed

+126
-4
lines changed

src/libbson/src/bson/bson-decimal128.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,14 +581,18 @@ bson_decimal128_from_string_w_len (const char *string, /* IN */
581581
#else
582582
#define SSCANF sscanf
583583
#endif
584-
int read_exponent = SSCANF (++str_read, "%d%n", &exponent, &nread);
584+
int64_t temp_exponent = 0;
585+
int read_exponent =
586+
SSCANF (++str_read, "%" SCNd64 "%n", &temp_exponent, &nread);
585587
str_read += nread;
586588

587-
if (!read_exponent || nread == 0) {
589+
if (!read_exponent || nread == 0 ||
590+
!bson_in_range_int32_t_signed (temp_exponent)) {
588591
BSON_DECIMAL128_SET_NAN (*dec);
589592
return false;
590593
}
591594

595+
exponent = (int32_t) temp_exponent;
592596
#undef SSCANF
593597
}
594598

src/libbson/src/bson/bson-json.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,9 +1124,9 @@ _bson_json_read_string (bson_json_reader_t *reader, /* IN */
11241124
} break;
11251125
case BSON_JSON_LF_DECIMAL128: {
11261126
bson_decimal128_t decimal128;
1127-
bson_decimal128_from_string (val_w_null, &decimal128);
11281127

1129-
if (bson->read_state == BSON_JSON_IN_BSON_TYPE) {
1128+
if (bson_decimal128_from_string (val_w_null, &decimal128) &&
1129+
bson->read_state == BSON_JSON_IN_BSON_TYPE) {
11301130
bson->bson_type_data.v_decimal128.value = decimal128;
11311131
} else {
11321132
goto BAD_PARSE;

src/libbson/tests/json/bson_corpus/decimal128-1.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,30 @@
312312
"canonical_bson": "18000000136400000000000a5bc138938d44c64d31cc3700",
313313
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}",
314314
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+999\"}}"
315+
},
316+
{
317+
"description": "Clamped zeros with a large positive exponent",
318+
"canonical_bson": "180000001364000000000000000000000000000000FE5F00",
319+
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+2147483647\"}}",
320+
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}"
321+
},
322+
{
323+
"description": "Clamped zeros with a large negative exponent",
324+
"canonical_bson": "180000001364000000000000000000000000000000000000",
325+
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-2147483647\"}}",
326+
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}"
327+
},
328+
{
329+
"description": "Clamped negative zeros with a large positive exponent",
330+
"canonical_bson": "180000001364000000000000000000000000000000FEDF00",
331+
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+2147483647\"}}",
332+
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}"
333+
},
334+
{
335+
"description": "Clamped negative zeros with a large negative exponent",
336+
"canonical_bson": "180000001364000000000000000000000000000000008000",
337+
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-2147483647\"}}",
338+
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}"
315339
}
316340
]
317341
}

src/libbson/tests/test-json.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3555,6 +3555,97 @@ test_bson_as_json_with_opts_all_types (void)
35553555
bson_destroy (&scope);
35563556
}
35573557

3558+
static void
3559+
test_decimal128_overflowing_exponent (void)
3560+
{
3561+
{
3562+
bson_decimal128_t decimal128;
3563+
BSON_ASSERT (!bson_decimal128_from_string ("0E+2147483648", &decimal128));
3564+
}
3565+
3566+
{
3567+
bson_decimal128_t decimal128;
3568+
BSON_ASSERT (!bson_decimal128_from_string ("0E-2147483649", &decimal128));
3569+
}
3570+
3571+
{
3572+
bson_decimal128_t decimal128;
3573+
BSON_ASSERT (
3574+
!bson_decimal128_from_string ("-0E+2147483648", &decimal128));
3575+
}
3576+
{
3577+
bson_decimal128_t decimal128;
3578+
BSON_ASSERT (
3579+
!bson_decimal128_from_string ("-0E-2147483649", &decimal128));
3580+
}
3581+
{
3582+
bson_error_t error;
3583+
const char *degenerate_extjson =
3584+
"{\"d\" : {\"$numberDecimal\" : \"0E+2147483648\"}}";
3585+
3586+
BSON_ASSERT (!bson_new_from_json (
3587+
(const uint8_t *) degenerate_extjson, -1, &error));
3588+
ASSERT_ERROR_CONTAINS (
3589+
error,
3590+
BSON_ERROR_JSON,
3591+
BSON_JSON_ERROR_READ_INVALID_PARAM,
3592+
"Invalid input string \"0E+2147483648\", looking for DECIMAL128");
3593+
}
3594+
3595+
{
3596+
bson_error_t error;
3597+
const char *degenerate_extjson =
3598+
"{\"d\" : {\"$numberDecimal\" : \"0E-2147483649\"}}";
3599+
3600+
BSON_ASSERT (!bson_new_from_json (
3601+
(const uint8_t *) degenerate_extjson, -1, &error));
3602+
ASSERT_ERROR_CONTAINS (
3603+
error,
3604+
BSON_ERROR_JSON,
3605+
BSON_JSON_ERROR_READ_INVALID_PARAM,
3606+
"Invalid input string \"0E-2147483649\", looking for DECIMAL128");
3607+
}
3608+
3609+
{
3610+
bson_error_t error;
3611+
const char *degenerate_extjson =
3612+
"{\"d\" : {\"$numberDecimal\" : \"-0E+2147483648\"}}";
3613+
3614+
BSON_ASSERT (!bson_new_from_json (
3615+
(const uint8_t *) degenerate_extjson, -1, &error));
3616+
ASSERT_ERROR_CONTAINS (
3617+
error,
3618+
BSON_ERROR_JSON,
3619+
BSON_JSON_ERROR_READ_INVALID_PARAM,
3620+
"Invalid input string \"-0E+2147483648\", looking for DECIMAL128");
3621+
}
3622+
3623+
{
3624+
bson_error_t error;
3625+
const char *degenerate_extjson =
3626+
"{\"d\" : {\"$numberDecimal\" : \"-0E-2147483649\"}}";
3627+
3628+
BSON_ASSERT (!bson_new_from_json (
3629+
(const uint8_t *) degenerate_extjson, -1, &error));
3630+
ASSERT_ERROR_CONTAINS (
3631+
error,
3632+
BSON_ERROR_JSON,
3633+
BSON_JSON_ERROR_READ_INVALID_PARAM,
3634+
"Invalid input string \"-0E-2147483649\", looking for DECIMAL128");
3635+
}
3636+
3637+
{
3638+
bson_decimal128_t decimal128;
3639+
BSON_ASSERT (
3640+
!bson_decimal128_from_string ("0E+99999999999999999999", &decimal128));
3641+
}
3642+
{
3643+
bson_decimal128_t decimal128;
3644+
BSON_ASSERT (
3645+
!bson_decimal128_from_string ("0E-99999999999999999999", &decimal128));
3646+
}
3647+
}
3648+
35583649
void
35593650
test_json_install (TestSuite *suite)
35603651
{
@@ -3748,4 +3839,7 @@ test_json_install (TestSuite *suite)
37483839
TestSuite_Add (suite,
37493840
"/bson/as_json_with_opts/all_types",
37503841
test_bson_as_json_with_opts_all_types);
3842+
TestSuite_Add (suite,
3843+
"/bson/decimal128_overflowing_exponent",
3844+
test_decimal128_overflowing_exponent);
37513845
}

0 commit comments

Comments
 (0)