From fdf2662b602ac81d952affe890983e46262b9861 Mon Sep 17 00:00:00 2001 From: ruben Date: Mon, 11 May 2020 09:20:22 +0100 Subject: [PATCH] Improved error detection in DATETIME bin deseriaiz Now DATETIMEs with invalid dates and invalid hours/mins/secs/micros are considered an error. Added tests. --- .../protocol/impl/binary_deserialization.ipp | 17 +++++++--- .../protocol/binary_deserialization_error.cpp | 34 +++++++++++-------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/include/boost/mysql/detail/protocol/impl/binary_deserialization.ipp b/include/boost/mysql/detail/protocol/impl/binary_deserialization.ipp index b40c95cf..dcfdc001 100644 --- a/include/boost/mysql/detail/protocol/impl/binary_deserialization.ipp +++ b/include/boost/mysql/detail/protocol/impl/binary_deserialization.ipp @@ -200,6 +200,17 @@ inline errc deserialize_binary_value_to_variant_datetime( return err; } + // Validity check. We make this check before + // the invalid date check to make invalid dates with incorrect + // hours/mins/secs/micros fail + if (hours.value > max_hour || + minutes.value > max_min || + seconds.value > max_sec || + micros.value > max_micro) + { + return errc::protocol_value_error; + } + // Check for invalid dates, represented in C++ as NULL. // Note: we do the check here to ensure we consume all the bytes // associated to this datetime @@ -211,11 +222,7 @@ inline errc deserialize_binary_value_to_variant_datetime( // Range check 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) + if (is_out_of_range(d)) { return errc::protocol_value_error; } diff --git a/test/unit/detail/protocol/binary_deserialization_error.cpp b/test/unit/detail/protocol/binary_deserialization_error.cpp index cb0e4d6d..b11c5726 100644 --- a/test/unit/detail/protocol/binary_deserialization_error.cpp +++ b/test/unit/detail/protocol/binary_deserialization_error.cpp @@ -149,22 +149,26 @@ std::vector make_datetime_cases( { 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}, + { "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 + { "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_hour_invalid_date", {0x0b, 0x00, 0x00, 0x00, 0x00, 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_min_invalid_date", {0x0b, 0x00, 0x00, 0x00, 0x00, 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_sec_invalid_date", {0x0b, 0x00, 0x00, 0x00, 0x00, 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 }, + { "invalid_micro_invalid_date", {0x0b, 0x00, 0x00, 0x00, 0x00, 0x17, 0x01, 0x3b, 0xff, 0xff, 0xff, 0xff}, type }, + { "protocol_max", {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, type } }; }