core: port GRegex/GMatchInfo to use autoptr()

The behavior of GRegex changed in 2.73.2 once it was ported from pcre1
to pcre2. In some cases it was made more strict, which is fine, in
other cases it exposed some change in how it behaves on certain
matches that is not extremely clear whether it's ok or not.

See https://gitlab.gnome.org/GNOME/glib/-/issues/2729
See https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/601
See https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/621

Either way, one thing that was assumed was that initializing all
GRegex/GMatchInfo variables to NULL and making sure they're NULL
before they're initialized by glib (especially the GMatchInfo) was a
good and safer approach.

So, whenever possible, g_autoptr() is used to cleanup the allocated
GMatchInfo/GRegex variables, and otherwise, g_clear_pointer() is used
to ensure that no free/unref is attempted unless the given variable is
not NULL, and also so that the variable is reseted to NULL after being
disposed.
This commit is contained in:
Aleksander Morgado
2022-09-05 17:33:11 +00:00
parent b2a186b5c8
commit 74fc5baca2
33 changed files with 850 additions and 1268 deletions
+7 -12
View File
@@ -627,12 +627,13 @@ load_unlock_retries_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
MMUnlockRetries *unlock_retries;
const gchar *result;
GRegex *r;
GMatchInfo *match_info = NULL;
GError *match_error = NULL;
guint i;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
MMUnlockRetries *unlock_retries;
const gchar *result;
GError *match_error = NULL;
guint i;
MMModemLock locks[4] = {
MM_MODEM_LOCK_SIM_PUK,
MM_MODEM_LOCK_SIM_PIN,
@@ -657,9 +658,6 @@ load_unlock_retries_finish (MMIfaceModem *self,
MM_CORE_ERROR_FAILED,
"Could not parse ^CPIN results: Response didn't match (%s)",
result);
g_match_info_free (match_info);
g_regex_unref (r);
return NULL;
}
@@ -683,9 +681,6 @@ load_unlock_retries_finish (MMIfaceModem *self,
mm_unlock_retries_set (unlock_retries, locks[i], num);
}
g_match_info_free (match_info);
g_regex_unref (r);
return unlock_retries;
}
+153 -180
View File
@@ -39,8 +39,6 @@ mm_huawei_parse_ndisstatqry_response (const gchar *response,
gboolean *ipv6_connected,
GError **error)
{
GRegex *r;
GMatchInfo *match_info;
GError *inner_error = NULL;
if (!response ||
@@ -71,6 +69,9 @@ mm_huawei_parse_ndisstatqry_response (const gchar *response,
/* If multiple fields available, try first parsing method */
if (strchr (response, ',')) {
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
r = g_regex_new ("\\^NDISSTAT(?:QRY)?(?:Qry)?:\\s*(\\d),([^,]*),([^,]*),([^,\\r\\n]*)(?:\\r\\n)?"
"(?:\\^NDISSTAT:|\\^NDISSTATQRY:)?\\s*,?(\\d)?,?([^,]*)?,?([^,]*)?,?([^,\\r\\n]*)?(?:\\r\\n)?",
G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW,
@@ -108,12 +109,12 @@ mm_huawei_parse_ndisstatqry_response (const gchar *response,
ip_type_field += 4;
}
}
g_match_info_free (match_info);
g_regex_unref (r);
}
/* No separate IPv4/IPv6 info given just connected/not connected */
else {
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
r = g_regex_new ("\\^NDISSTAT(?:QRY)?(?:Qry)?:\\s*(\\d)(?:\\r\\n)?",
G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW,
0, NULL);
@@ -134,9 +135,6 @@ mm_huawei_parse_ndisstatqry_response (const gchar *response,
*ipv4_connected = (gboolean)connected;
}
}
g_match_info_free (match_info);
g_regex_unref (r);
}
if (!ipv4_available && !ipv6_available) {
@@ -208,10 +206,10 @@ mm_huawei_parse_dhcp_response (const char *reply,
guint *out_dns2,
GError **error)
{
gboolean matched;
GRegex *r;
GMatchInfo *match_info = NULL;
GError *match_error = NULL;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
gboolean matched;
GError *match_error = NULL;
g_assert (reply != NULL);
g_assert (out_address != NULL);
@@ -257,8 +255,6 @@ mm_huawei_parse_dhcp_response (const char *reply,
}
}
g_match_info_free (match_info);
g_regex_unref (r);
return matched;
}
@@ -276,10 +272,10 @@ mm_huawei_parse_sysinfo_response (const char *reply,
guint *out_sys_submode,
GError **error)
{
gboolean matched;
GRegex *r;
GMatchInfo *match_info = NULL;
GError *match_error = NULL;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
gboolean matched;
GError *match_error = NULL;
g_assert (out_srv_status != NULL);
g_assert (out_srv_domain != NULL);
@@ -323,8 +319,6 @@ mm_huawei_parse_sysinfo_response (const char *reply,
}
}
g_match_info_free (match_info);
g_regex_unref (r);
return matched;
}
@@ -341,10 +335,10 @@ mm_huawei_parse_sysinfoex_response (const char *reply,
guint *out_sys_submode,
GError **error)
{
gboolean matched;
GRegex *r;
GMatchInfo *match_info = NULL;
GError *match_error = NULL;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
gboolean matched;
GError *match_error = NULL;
g_assert (out_srv_status != NULL);
g_assert (out_srv_domain != NULL);
@@ -387,8 +381,6 @@ mm_huawei_parse_sysinfoex_response (const char *reply,
mm_get_uint_from_match_info (match_info, 8, out_sys_submode);
}
g_match_info_free (match_info);
g_regex_unref (r);
return matched;
}
@@ -1189,17 +1181,23 @@ mm_huawei_parse_syscfgex_response (const gchar *response,
/*****************************************************************************/
/* ^NWTIME response parser */
gboolean mm_huawei_parse_nwtime_response (const gchar *response,
gchar **iso8601p,
MMNetworkTimezone **tzp,
GError **error)
gboolean
mm_huawei_parse_nwtime_response (const gchar *response,
gchar **iso8601p,
MMNetworkTimezone **tzp,
GError **error)
{
GRegex *r;
GMatchInfo *match_info = NULL;
GError *match_error = NULL;
guint year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, dt = 0;
gint tz = 0;
gboolean ret = FALSE;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
GError *match_error = NULL;
guint year = 0;
guint month = 0;
guint day = 0;
guint hour = 0;
guint minute = 0;
guint second = 0;
guint dt = 0;
gint tz = 0;
g_assert (iso8601p || tzp); /* at least one */
@@ -1211,75 +1209,72 @@ gboolean mm_huawei_parse_nwtime_response (const gchar *response,
g_propagate_error (error, match_error);
g_prefix_error (error, "Could not parse ^NWTIME results: ");
} else {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Couldn't match ^NWTIME reply");
}
} else {
/* Remember that g_match_info_get_match_count() includes match #0 */
g_assert (g_match_info_get_match_count (match_info) >= 9);
if (mm_get_uint_from_match_info (match_info, 1, &year) &&
mm_get_uint_from_match_info (match_info, 2, &month) &&
mm_get_uint_from_match_info (match_info, 3, &day) &&
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) &&
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;
/*
* tz = timezone offset in 15 minute intervals
* dt = daylight adjustment, 0 = none, 1 = 1 hour, 2 = 2 hours
* other values are marked reserved.
*/
if (iso8601p) {
/* Return ISO-8601 format date/time string */
*iso8601p = mm_new_iso8601_time (year, month, day, hour,
minute, second,
TRUE, (tz * 15) + (dt * 60),
error);
ret = (*iso8601p != NULL);
}
if (tzp) {
*tzp = mm_network_timezone_new ();
mm_network_timezone_set_offset (*tzp, tz * 15);
mm_network_timezone_set_dst_offset (*tzp, dt * 60);
}
} else {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Failed to parse ^NWTIME reply");
}
return FALSE;
}
g_match_info_free (match_info);
g_regex_unref (r);
/* Remember that g_match_info_get_match_count() includes match #0 */
g_assert (g_match_info_get_match_count (match_info) >= 9);
return ret;
if (mm_get_uint_from_match_info (match_info, 1, &year) &&
mm_get_uint_from_match_info (match_info, 2, &month) &&
mm_get_uint_from_match_info (match_info, 3, &day) &&
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) &&
mm_get_int_from_match_info (match_info, 7, &tz) &&
mm_get_uint_from_match_info (match_info, 8, &dt)) {
/* adjust year */
if (year < 100)
year += 2000;
/*
* tz = timezone offset in 15 minute intervals
* dt = daylight adjustment, 0 = none, 1 = 1 hour, 2 = 2 hours
* other values are marked reserved.
*/
if (tzp) {
*tzp = mm_network_timezone_new ();
mm_network_timezone_set_offset (*tzp, tz * 15);
mm_network_timezone_set_dst_offset (*tzp, dt * 60);
}
if (iso8601p) {
/* Return ISO-8601 format date/time string */
*iso8601p = mm_new_iso8601_time (year, month, day, hour,
minute, second,
TRUE, (tz * 15) + (dt * 60),
error);
return (*iso8601p != NULL);
}
return TRUE;
}
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Failed to parse ^NWTIME reply");
return FALSE;
}
/*****************************************************************************/
/* ^TIME response parser */
gboolean mm_huawei_parse_time_response (const gchar *response,
gchar **iso8601p,
MMNetworkTimezone **tzp,
GError **error)
gboolean
mm_huawei_parse_time_response (const gchar *response,
gchar **iso8601p,
MMNetworkTimezone **tzp,
GError **error)
{
GRegex *r;
GMatchInfo *match_info = NULL;
GError *match_error = NULL;
guint year, month, day, hour, minute, second;
gboolean ret = FALSE;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
GError *match_error = NULL;
guint year = 0;
guint month = 0;
guint day = 0;
guint hour = 0;
guint minute = 0;
guint second = 0;
g_assert (iso8601p || tzp); /* at least one */
@@ -1306,41 +1301,35 @@ gboolean mm_huawei_parse_time_response (const gchar *response,
MM_CORE_ERROR_FAILED,
"Couldn't match ^TIME reply");
}
} else {
/* Remember that g_match_info_get_match_count() includes match #0 */
g_assert (g_match_info_get_match_count (match_info) >= 7);
if (mm_get_uint_from_match_info (match_info, 1, &year) &&
mm_get_uint_from_match_info (match_info, 2, &month) &&
mm_get_uint_from_match_info (match_info, 3, &day) &&
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) {
*iso8601p = mm_new_iso8601_time (year, month, day, hour,
minute, second, FALSE, 0,
error);
ret = (*iso8601p != NULL);
}
} else {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Failed to parse ^TIME reply");
}
return FALSE;
}
g_match_info_free (match_info);
g_regex_unref (r);
/* Remember that g_match_info_get_match_count() includes match #0 */
g_assert (g_match_info_get_match_count (match_info) >= 7);
return ret;
if (mm_get_uint_from_match_info (match_info, 1, &year) &&
mm_get_uint_from_match_info (match_info, 2, &month) &&
mm_get_uint_from_match_info (match_info, 3, &day) &&
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)) {
/* adjust year */
if (year < 100)
year += 2000;
/* Return ISO-8601 format date/time string */
if (iso8601p) {
*iso8601p = mm_new_iso8601_time (year, month, day, hour,
minute, second, FALSE, 0,
error);
return (*iso8601p != NULL);
}
return TRUE;
}
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Failed to parse ^TIME reply");
return FALSE;
}
/*****************************************************************************/
@@ -1356,11 +1345,9 @@ mm_huawei_parse_hcsq_response (const gchar *response,
guint *out_value5,
GError **error)
{
GRegex *r;
GMatchInfo *match_info = NULL;
GError *match_error = NULL;
gboolean ret = FALSE;
char *s;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
GError *match_error = NULL;
r = g_regex_new ("\\^HCSQ:\\s*\"?([a-zA-Z]*)\"?,(\\d+),?(\\d+)?,?(\\d+)?,?(\\d+)?,?(\\d+)?$", 0, 0, NULL);
g_assert (r != NULL);
@@ -1370,27 +1357,24 @@ mm_huawei_parse_hcsq_response (const gchar *response,
g_propagate_error (error, match_error);
g_prefix_error (error, "Could not parse ^HCSQ results: ");
} else {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Couldn't match ^HCSQ reply");
}
goto done;
return FALSE;
}
/* Remember that g_match_info_get_match_count() includes match #0 */
if (g_match_info_get_match_count (match_info) < 3) {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Not enough elements in ^HCSQ reply");
goto done;
return FALSE;
}
if (out_act) {
g_autofree gchar *s = NULL;
s = g_match_info_fetch (match_info, 1);
*out_act = mm_string_to_access_tech (s);
g_free (s);
}
if (out_value1)
@@ -1404,13 +1388,7 @@ mm_huawei_parse_hcsq_response (const gchar *response,
if (out_value5)
mm_get_uint_from_match_info (match_info, 6, out_value5);
ret = TRUE;
done:
g_match_info_free (match_info);
g_regex_unref (r);
return ret;
return TRUE;
}
/*****************************************************************************/
@@ -1422,11 +1400,12 @@ mm_huawei_parse_cvoice_response (const gchar *response,
guint *out_bits,
GError **error)
{
GRegex *r;
GMatchInfo *match_info = NULL;
GError *match_error = NULL;
guint supported = 0, hz = 0, bits = 0;
gboolean ret = FALSE;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
GError *match_error = NULL;
guint supported = 0;
guint hz = 0;
guint bits = 0;
/* ^CVOICE: <0=supported,1=unsupported>,<hz>,<bits>,<unknown> */
r = g_regex_new ("\\^CVOICE:\\s*(\\d)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)$", 0, 0, NULL);
@@ -1442,37 +1421,31 @@ mm_huawei_parse_cvoice_response (const gchar *response,
MM_CORE_ERROR_FAILED,
"Couldn't match ^CVOICE reply");
}
} else {
/* Remember that g_match_info_get_match_count() includes match #0 */
g_assert (g_match_info_get_match_count (match_info) >= 5);
if (mm_get_uint_from_match_info (match_info, 1, &supported) &&
mm_get_uint_from_match_info (match_info, 2, &hz) &&
mm_get_uint_from_match_info (match_info, 3, &bits)) {
if (supported == 0) {
if (out_hz)
*out_hz = hz;
if (out_bits)
*out_bits = bits;
ret = TRUE;
} else {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"^CVOICE not supported by this device");
}
} else {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Failed to parse ^CVOICE reply");
}
return FALSE;
}
g_match_info_free (match_info);
g_regex_unref (r);
/* Remember that g_match_info_get_match_count() includes match #0 */
g_assert (g_match_info_get_match_count (match_info) >= 5);
return ret;
if (mm_get_uint_from_match_info (match_info, 1, &supported) &&
mm_get_uint_from_match_info (match_info, 2, &hz) &&
mm_get_uint_from_match_info (match_info, 3, &bits)) {
if (supported == 0) {
if (out_hz)
*out_hz = hz;
if (out_bits)
*out_bits = bits;
return TRUE;
}
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"^CVOICE not supported by this device");
return FALSE;
}
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Failed to parse ^CVOICE reply");
return FALSE;
}
/*****************************************************************************/