diff options
author | Carlo Lobrano <c.lobrano@gmail.com> | 2022-04-08 11:46:11 +0200 |
---|---|---|
committer | Carlo Lobrano <c.lobrano@gmail.com> | 2022-04-08 15:41:49 +0200 |
commit | ac243f94676695d88e861d225e98ec5bb3c2861e (patch) | |
tree | 339f80e309a17e17e707d0716f2bf4e070fae2c1 | |
parent | 5c8c1136bd3bad2b542a0b3dc334dbd0686ba10d (diff) |
sms: prevent crash if date is out of range
g_date_time_new, and g_date_time_new_utc return NULL if inputs are out
of range, and currently mm_new_iso8601_time passes the GDateTime created
by those two functions to date_time_format_iso8601 without checking for
NULL values, causing a g_date_time_format_iso8601 crash if PDU data is
corrupted with wrong date.
To prevent this, mm_new_iso8601_time now can return NULL and set a new
GError if GDateTime created by g_date_time_new is NULL.
Fixes #546
-rw-r--r-- | libmm-glib/mm-common-helpers.c | 11 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.h | 3 | ||||
-rw-r--r-- | libmm-glib/tests/test-common-helpers.c | 26 | ||||
-rw-r--r-- | plugins/cinterion/mm-modem-helpers-cinterion.c | 7 | ||||
-rw-r--r-- | plugins/huawei/mm-modem-helpers-huawei.c | 19 | ||||
-rw-r--r-- | plugins/icera/mm-broadband-modem-icera.c | 7 | ||||
-rw-r--r-- | plugins/novatel/mm-broadband-modem-novatel.c | 4 | ||||
-rw-r--r-- | plugins/sierra/mm-broadband-modem-sierra.c | 2 | ||||
-rw-r--r-- | src/mm-modem-helpers.c | 8 | ||||
-rw-r--r-- | src/mm-sms-part-3gpp.c | 30 |
10 files changed, 91 insertions, 26 deletions
diff --git a/libmm-glib/mm-common-helpers.c b/libmm-glib/mm-common-helpers.c index b7883b26..085177b7 100644 --- a/libmm-glib/mm-common-helpers.c +++ b/libmm-glib/mm-common-helpers.c @@ -1769,7 +1769,8 @@ mm_new_iso8601_time (guint year, guint minute, guint second, gboolean have_offset, - gint offset_minutes) + gint offset_minutes, + GError **error) { g_autoptr(GDateTime) dt = NULL; @@ -1781,6 +1782,14 @@ mm_new_iso8601_time (guint year, } else dt = g_date_time_new_utc (year, month, day, hour, minute, second); + if (dt == NULL) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_INVALID_ARGS, + "Invalid input for date: got year:%u, month:%u, day:%u, hour:%u, minute:%u, second:%u", + year, month, day, hour, minute, second); + return NULL; + } return date_time_format_iso8601 (dt); } diff --git a/libmm-glib/mm-common-helpers.h b/libmm-glib/mm-common-helpers.h index d444012c..490f882d 100644 --- a/libmm-glib/mm-common-helpers.h +++ b/libmm-glib/mm-common-helpers.h @@ -216,7 +216,8 @@ gchar *mm_new_iso8601_time (guint year, guint minute, guint second, gboolean have_offset, - gint offset_minutes); + gint offset_minutes, + GError **error); /******************************************************************************/ /* Type checkers and conversion utilities */ diff --git a/libmm-glib/tests/test-common-helpers.c b/libmm-glib/tests/test-common-helpers.c index 69b95cb1..a1a2e61e 100644 --- a/libmm-glib/tests/test-common-helpers.c +++ b/libmm-glib/tests/test-common-helpers.c @@ -602,18 +602,40 @@ static void date_time_iso8601 (void) { gchar *date = NULL; + GError *error = NULL; date = mm_new_iso8601_time_from_unix_time (1634307342); g_assert_cmpstr (date, ==, "2021-10-15T14:15:42Z"); g_free (date); - date = mm_new_iso8601_time (2021, 10, 15, 16, 15, 42, FALSE, 0); + date = mm_new_iso8601_time (2021, 10, 15, 16, 15, 42, FALSE, 0, &error); + g_assert_no_error (error); g_assert_cmpstr (date, ==, "2021-10-15T16:15:42Z"); g_free (date); - date = mm_new_iso8601_time (2021, 10, 15, 16, 15, 42, TRUE, 120); + date = mm_new_iso8601_time (2021, 10, 15, 16, 15, 42, TRUE, 120, &error); + g_assert_no_error (error); g_assert_cmpstr (date, ==, "2021-10-15T16:15:42+02"); g_free (date); + + /* Valid args: + * - Year:[1-9999] + * - Month:[1-12] + * - Day:[1-28|29|30|31] according to year and month + * - Hour: [0-23] + * - Minute: [0-59] + * - Seconds: [0.0-60.0) + * */ + date = mm_new_iso8601_time (2021, 13, 15, 16, 15, 42, TRUE, 120, &error); + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS); + g_assert_null (date); + g_clear_error (&error); + + /* No February 29 in 2021 */ + date = mm_new_iso8601_time (2021, 2, 29, 16, 15, 42, TRUE, 120, &error); + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS); + g_assert_null (date); + g_clear_error (&error); } /**************************************************************/ diff --git a/plugins/cinterion/mm-modem-helpers-cinterion.c b/plugins/cinterion/mm-modem-helpers-cinterion.c index f8cec825..a75eb530 100644 --- a/plugins/cinterion/mm-modem-helpers-cinterion.c +++ b/plugins/cinterion/mm-modem-helpers-cinterion.c @@ -1201,6 +1201,7 @@ mm_cinterion_parse_ctzu_urc (GMatchInfo *match_info, MMNetworkTimezone **tzp, GError **error) { + gboolean ret = TRUE; guint year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, dst = 0; gint tz = 0; @@ -1229,7 +1230,9 @@ mm_cinterion_parse_ctzu_urc (GMatchInfo *match_info, /* Return ISO-8601 format date/time string */ *iso8601p = mm_new_iso8601_time (year, month, day, hour, minute, second, - TRUE, tz * 15); + TRUE, tz * 15, + error); + ret = (*iso8601p != NULL); } if (tzp) { @@ -1245,7 +1248,7 @@ mm_cinterion_parse_ctzu_urc (GMatchInfo *match_info, if (tzp && mm_get_uint_from_match_info (match_info, 8, &dst)) mm_network_timezone_set_dst_offset (*tzp, dst * 60); - return TRUE; + return ret; } /*****************************************************************************/ diff --git a/plugins/huawei/mm-modem-helpers-huawei.c b/plugins/huawei/mm-modem-helpers-huawei.c index b8548418..3ded6237 100644 --- a/plugins/huawei/mm-modem-helpers-huawei.c +++ b/plugins/huawei/mm-modem-helpers-huawei.c @@ -1228,6 +1228,9 @@ gboolean mm_huawei_parse_nwtime_response (const gchar *response, mm_get_uint_from_match_info (match_info, 6, &second) && mm_get_int_from_match_info (match_info, 7, &tz) && mm_get_uint_from_match_info (match_info, 8, &dt)) { + + ret = TRUE; + /* adjust year */ if (year < 100) year += 2000; @@ -1240,7 +1243,9 @@ gboolean mm_huawei_parse_nwtime_response (const gchar *response, /* Return ISO-8601 format date/time string */ *iso8601p = mm_new_iso8601_time (year, month, day, hour, minute, second, - TRUE, (tz * 15) + (dt * 60)); + TRUE, (tz * 15) + (dt * 60), + error); + ret = (*iso8601p != NULL); } if (tzp) { *tzp = mm_network_timezone_new (); @@ -1248,7 +1253,6 @@ gboolean mm_huawei_parse_nwtime_response (const gchar *response, mm_network_timezone_set_dst_offset (*tzp, dt * 60); } - ret = TRUE; } else { g_set_error_literal (error, MM_CORE_ERROR, @@ -1312,14 +1316,19 @@ gboolean mm_huawei_parse_time_response (const gchar *response, mm_get_uint_from_match_info (match_info, 4, &hour) && mm_get_uint_from_match_info (match_info, 5, &minute) && mm_get_uint_from_match_info (match_info, 6, &second)) { + ret = TRUE; + /* adjust year */ if (year < 100) year += 2000; + /* Return ISO-8601 format date/time string */ - if (iso8601p) + if (iso8601p) { *iso8601p = mm_new_iso8601_time (year, month, day, hour, - minute, second, FALSE, 0); - ret = TRUE; + minute, second, FALSE, 0, + error); + ret = (*iso8601p != NULL); + } } else { g_set_error_literal (error, MM_CORE_ERROR, diff --git a/plugins/icera/mm-broadband-modem-icera.c b/plugins/icera/mm-broadband-modem-icera.c index 26016c4c..96cb45fa 100644 --- a/plugins/icera/mm-broadband-modem-icera.c +++ b/plugins/icera/mm-broadband-modem-icera.c @@ -1569,6 +1569,7 @@ parse_tlts_query_reply (const gchar *response, MMNetworkTimezone **tz, GError **error) { + gboolean ret = TRUE; gint year; gint month; gint day; @@ -1649,11 +1650,13 @@ parse_tlts_query_reply (const gchar *response, g_date_time_get_minute (adjusted), g_date_time_get_second (adjusted), TRUE, - offset); + offset, + error); + ret = (*iso8601 != NULL); } g_date_time_unref (adjusted); - return TRUE; + return ret; } static MMNetworkTimezone * diff --git a/plugins/novatel/mm-broadband-modem-novatel.c b/plugins/novatel/mm-broadband-modem-novatel.c index 4eba0e16..1cc88e90 100644 --- a/plugins/novatel/mm-broadband-modem-novatel.c +++ b/plugins/novatel/mm-broadband-modem-novatel.c @@ -1431,13 +1431,13 @@ parse_nwltime_reply (const char *response, mm_get_int_from_match_info (match_info, 8, &utc_offset)) { result = mm_new_iso8601_time (year, month, day, hour, minute, second, - TRUE, utc_offset * 60); + TRUE, utc_offset * 60, error); if (out_tz) { *out_tz = mm_network_timezone_new (); mm_network_timezone_set_offset (*out_tz, utc_offset * 60); } - success = TRUE; + success = (result != NULL); } else { g_set_error_literal (error, MM_CORE_ERROR, diff --git a/plugins/sierra/mm-broadband-modem-sierra.c b/plugins/sierra/mm-broadband-modem-sierra.c index 518f8adb..3ac20808 100644 --- a/plugins/sierra/mm-broadband-modem-sierra.c +++ b/plugins/sierra/mm-broadband-modem-sierra.c @@ -1656,7 +1656,7 @@ parse_time (const gchar *response, mm_get_uint_from_match_info (match_info, 4, &hour) && mm_get_uint_from_match_info (match_info, 5, &minute) && mm_get_uint_from_match_info (match_info, 6, &second)) { - result = mm_new_iso8601_time (year, month, day, hour, minute, second, FALSE, 0); + result = mm_new_iso8601_time (year, month, day, hour, minute, second, FALSE, 0, error); } else { g_set_error (error, MM_CORE_ERROR, diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index 72714ab9..5e58ba9d 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -5112,15 +5112,17 @@ mm_parse_cclk_response (const char *response, mm_network_timezone_set_offset (*tzp, tz * 15); } + ret = TRUE; + if (iso8601p) { /* Return ISO-8601 format date/time string */ *iso8601p = mm_new_iso8601_time (year, month, day, hour, minute, second, - TRUE, (tz * 15)); + TRUE, (tz * 15), + error); + ret = (*iso8601p != NULL); } - ret = TRUE; - out: g_match_info_free (match_info); g_regex_unref (r); diff --git a/src/mm-sms-part-3gpp.c b/src/mm-sms-part-3gpp.c index bfae03a8..aeb9decb 100644 --- a/src/mm-sms-part-3gpp.c +++ b/src/mm-sms-part-3gpp.c @@ -161,7 +161,8 @@ sms_decode_address (const guint8 *address, } static gchar * -sms_decode_timestamp (const guint8 *timestamp) +sms_decode_timestamp (const guint8 *timestamp, + GError **error) { /* ISO8601 format: YYYY-MM-DDTHH:MM:SS+HHMM */ guint year, month, day, hour, minute, second; @@ -179,7 +180,7 @@ sms_decode_timestamp (const guint8 *timestamp) offset_minutes = -1 * offset_minutes; return mm_new_iso8601_time (year, month, day, hour, - minute, second, TRUE, offset_minutes); + minute, second, TRUE, offset_minutes, error); } static MMSmsEncoding @@ -509,6 +510,7 @@ mm_sms_part_3gpp_new_from_binary_pdu (guint index, /* Get timestamps and indexes for TP-PID, TP-DCS and TP-UDL/TP-UD */ if (pdu_type == SMS_TP_MTI_SMS_DELIVER) { + gchar *str = NULL; PDU_SIZE_CHECK (offset + 9, "cannot read PID/DCS/Timestamp"); /* 1+1+7=9 */ @@ -519,8 +521,13 @@ mm_sms_part_3gpp_new_from_binary_pdu (guint index, tp_dcs_offset = offset++; /* ------ Timestamp (7 bytes) ------ */ + str = sms_decode_timestamp (&pdu[offset], error); + if (!str) { + mm_sms_part_free (sms_part); + return NULL; + } mm_sms_part_take_timestamp (sms_part, - sms_decode_timestamp (&pdu[offset])); + str); offset += 7; tp_user_data_len_offset = offset; @@ -564,6 +571,7 @@ mm_sms_part_3gpp_new_from_binary_pdu (guint index, tp_user_data_len_offset = offset; } else if (pdu_type == SMS_TP_MTI_SMS_STATUS_REPORT) { + gchar *str = NULL; /* We have 2 timestamps in status report PDUs: * first, the timestamp for when the PDU was received in the SMSC * second, the timestamp for when the PDU was forwarded by the SMSC @@ -571,13 +579,21 @@ mm_sms_part_3gpp_new_from_binary_pdu (guint index, PDU_SIZE_CHECK (offset + 15, "cannot read Timestamps/TP-STATUS"); /* 7+7+1=15 */ /* ------ Timestamp (7 bytes) ------ */ - mm_sms_part_take_timestamp (sms_part, - sms_decode_timestamp (&pdu[offset])); + str = sms_decode_timestamp (&pdu[offset], error); + if (!str) { + mm_sms_part_free (sms_part); + return NULL; + } + mm_sms_part_take_timestamp (sms_part, str); offset += 7; /* ------ Discharge Timestamp (7 bytes) ------ */ - mm_sms_part_take_discharge_timestamp (sms_part, - sms_decode_timestamp (&pdu[offset])); + str = sms_decode_timestamp (&pdu[offset], error); + if (!str) { + mm_sms_part_free (sms_part); + return NULL; + } + mm_sms_part_take_discharge_timestamp (sms_part, str); offset += 7; /* ----- TP-STATUS (1 byte) ------ */ |