Skip to content

Commit e50a625

Browse files
committed
CDRIVER-4662 check for decimal128 exponent overflow (#1349)
1 parent 85ce54b commit e50a625

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
@@ -3511,6 +3511,97 @@ test_bson_as_json_with_opts_all_types (void)
35113511
bson_destroy (&scope);
35123512
}
35133513

3514+
static void
3515+
test_decimal128_overflowing_exponent (void)
3516+
{
3517+
{
3518+
bson_decimal128_t decimal128;
3519+
BSON_ASSERT (!bson_decimal128_from_string ("0E+2147483648", &decimal128));
3520+
}
3521+
3522+
{
3523+
bson_decimal128_t decimal128;
3524+
BSON_ASSERT (!bson_decimal128_from_string ("0E-2147483649", &decimal128));
3525+
}
3526+
3527+
{
3528+
bson_decimal128_t decimal128;
3529+
BSON_ASSERT (
3530+
!bson_decimal128_from_string ("-0E+2147483648", &decimal128));
3531+
}
3532+
{
3533+
bson_decimal128_t decimal128;
3534+
BSON_ASSERT (
3535+
!bson_decimal128_from_string ("-0E-2147483649", &decimal128));
3536+
}
3537+
{
3538+
bson_error_t error;
3539+
const char *degenerate_extjson =
3540+
"{\"d\" : {\"$numberDecimal\" : \"0E+2147483648\"}}";
3541+
3542+
BSON_ASSERT (!bson_new_from_json (
3543+
(const uint8_t *) degenerate_extjson, -1, &error));
3544+
ASSERT_ERROR_CONTAINS (
3545+
error,
3546+
BSON_ERROR_JSON,
3547+
BSON_JSON_ERROR_READ_INVALID_PARAM,
3548+
"Invalid input string \"0E+2147483648\", looking for DECIMAL128");
3549+
}
3550+
3551+
{
3552+
bson_error_t error;
3553+
const char *degenerate_extjson =
3554+
"{\"d\" : {\"$numberDecimal\" : \"0E-2147483649\"}}";
3555+
3556+
BSON_ASSERT (!bson_new_from_json (
3557+
(const uint8_t *) degenerate_extjson, -1, &error));
3558+
ASSERT_ERROR_CONTAINS (
3559+
error,
3560+
BSON_ERROR_JSON,
3561+
BSON_JSON_ERROR_READ_INVALID_PARAM,
3562+
"Invalid input string \"0E-2147483649\", looking for DECIMAL128");
3563+
}
3564+
3565+
{
3566+
bson_error_t error;
3567+
const char *degenerate_extjson =
3568+
"{\"d\" : {\"$numberDecimal\" : \"-0E+2147483648\"}}";
3569+
3570+
BSON_ASSERT (!bson_new_from_json (
3571+
(const uint8_t *) degenerate_extjson, -1, &error));
3572+
ASSERT_ERROR_CONTAINS (
3573+
error,
3574+
BSON_ERROR_JSON,
3575+
BSON_JSON_ERROR_READ_INVALID_PARAM,
3576+
"Invalid input string \"-0E+2147483648\", looking for DECIMAL128");
3577+
}
3578+
3579+
{
3580+
bson_error_t error;
3581+
const char *degenerate_extjson =
3582+
"{\"d\" : {\"$numberDecimal\" : \"-0E-2147483649\"}}";
3583+
3584+
BSON_ASSERT (!bson_new_from_json (
3585+
(const uint8_t *) degenerate_extjson, -1, &error));
3586+
ASSERT_ERROR_CONTAINS (
3587+
error,
3588+
BSON_ERROR_JSON,
3589+
BSON_JSON_ERROR_READ_INVALID_PARAM,
3590+
"Invalid input string \"-0E-2147483649\", looking for DECIMAL128");
3591+
}
3592+
3593+
{
3594+
bson_decimal128_t decimal128;
3595+
BSON_ASSERT (
3596+
!bson_decimal128_from_string ("0E+99999999999999999999", &decimal128));
3597+
}
3598+
{
3599+
bson_decimal128_t decimal128;
3600+
BSON_ASSERT (
3601+
!bson_decimal128_from_string ("0E-99999999999999999999", &decimal128));
3602+
}
3603+
}
3604+
35143605
void
35153606
test_json_install (TestSuite *suite)
35163607
{
@@ -3700,4 +3791,7 @@ test_json_install (TestSuite *suite)
37003791
TestSuite_Add (suite,
37013792
"/bson/as_json_with_opts/all_types",
37023793
test_bson_as_json_with_opts_all_types);
3794+
TestSuite_Add (suite,
3795+
"/bson/decimal128_overflowing_exponent",
3796+
test_decimal128_overflowing_exponent);
37033797
}

0 commit comments

Comments
 (0)