diff --git a/include/boost/mysql/detail/protocol/impl/binary_deserialization.ipp b/include/boost/mysql/detail/protocol/impl/binary_deserialization.ipp index 239e41c0..af739602 100644 --- a/include/boost/mysql/detail/protocol/impl/binary_deserialization.ipp +++ b/include/boost/mysql/detail/protocol/impl/binary_deserialization.ipp @@ -107,6 +107,13 @@ inline errc deserialize_binary_ymd( return errc::ok; } +inline bool is_out_of_range( + const date& d +) +{ + return d < min_date || d > max_date; +} + inline errc deserialize_binary_value_to_variant_date( deserialization_context& ctx, value& output @@ -140,7 +147,7 @@ inline errc deserialize_binary_value_to_variant_date( // Range check date d (ymd); - if (d < min_date || d > max_date) + if (is_out_of_range(d)) return errc::protocol_value_error; // Convert to sys_days (date) @@ -204,7 +211,9 @@ inline errc deserialize_binary_value_to_variant_datetime( } // Range check - if (hours.value > max_hour || + date d (ymd); + if (is_out_of_range(d) || + hours.value > max_hour || minutes.value > max_min || seconds.value > max_sec || micros.value > max_micro) diff --git a/test/unit/detail/protocol/binary_deserialization_error.cpp b/test/unit/detail/protocol/binary_deserialization_error.cpp index ff57d685..1837e02f 100644 --- a/test/unit/detail/protocol/binary_deserialization_error.cpp +++ b/test/unit/detail/protocol/binary_deserialization_error.cpp @@ -143,6 +143,39 @@ INSTANTIATE_TEST_SUITE_P(DATE, DeserializeBinaryValueErrorTest, Values( protocol_field_type::date) )); +std::vector make_datetime_cases( + protocol_field_type type +) +{ + return { + { "empty", {}, type, errc::incomplete_message }, + { "incomplete_date", {0x04, 0x09, 0x27, 0x01}, type, errc::incomplete_message }, + { "no_hours_mins_secs", {0x07, 0x09, 0x27, 0x01, 0x01}, type, errc::incomplete_message }, + { "no_mins_secs", {0x07, 0x09, 0x27, 0x01, 0x01, 0x01}, type, errc::incomplete_message }, + { "no_secs", {0x07, 0x09, 0x27, 0x01, 0x01, 0x01, 0x01}, type, errc::incomplete_message }, + { "no_micros", {0x0b, 0x09, 0x27, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00}, + type, errc::incomplete_message }, + { "date_gt_max", {0x0b, 0xff, 0xff, 0x01, 0x01, 0x17, 0x01, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, type }, + { "invalid_hour", {0x0b, 0xda, 0x07, 0x01, 0x01, 24, 0x01, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, type }, + { "invalid_hour_max", {0x0b, 0xda, 0x07, 0x01, 0x01, 0xff, 0x01, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, type }, + { "invalid_min", {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 60, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, type }, + { "invalid_min_max", {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0xff, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, type }, + { "invalid_sec", {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0x01, 60, 0x56, 0xc3, 0x0e, 0x00}, type }, + { "invalid_sec_max", {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0x01, 0xff, 0x56, 0xc3, 0x0e, 0x00}, type }, + { "invalid_micro", {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0x01, 0x3b, 0x40, 0x42, 0xf4, 0x00}, type }, // 1M + { "invalid_micro_max", {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0x01, 0x3b, 0xff, 0xff, 0xff, 0xff}, type }, + { "protocol_max", {0xff, 0xff, 0xff, 12, 31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, type }, // make date valid + }; +} + +INSTANTIATE_TEST_SUITE_P(DATETIME, DeserializeBinaryValueErrorTest, ValuesIn( + make_datetime_cases(protocol_field_type::datetime) +), test_name_generator); + +INSTANTIATE_TEST_SUITE_P(TIMESTAMP, DeserializeBinaryValueErrorTest, ValuesIn( + make_datetime_cases(protocol_field_type::timestamp) +), test_name_generator); + INSTANTIATE_TEST_SUITE_P(YEAR, DeserializeBinaryValueErrorTest, ValuesIn( make_int_cases(protocol_field_type::year, 1) ), test_name_generator);