aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlo Lobrano <c.lobrano@gmail.com>2022-04-08 11:46:11 +0200
committerCarlo Lobrano <c.lobrano@gmail.com>2022-04-08 15:41:49 +0200
commitac243f94676695d88e861d225e98ec5bb3c2861e (patch)
tree339f80e309a17e17e707d0716f2bf4e070fae2c1
parent5c8c1136bd3bad2b542a0b3dc334dbd0686ba10d (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.c11
-rw-r--r--libmm-glib/mm-common-helpers.h3
-rw-r--r--libmm-glib/tests/test-common-helpers.c26
-rw-r--r--plugins/cinterion/mm-modem-helpers-cinterion.c7
-rw-r--r--plugins/huawei/mm-modem-helpers-huawei.c19
-rw-r--r--plugins/icera/mm-broadband-modem-icera.c7
-rw-r--r--plugins/novatel/mm-broadband-modem-novatel.c4
-rw-r--r--plugins/sierra/mm-broadband-modem-sierra.c2
-rw-r--r--src/mm-modem-helpers.c8
-rw-r--r--src/mm-sms-part-3gpp.c30
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) ------ */