diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2013-05-23 15:52:31 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2013-05-23 18:00:03 +0200 |
commit | a12be165d14083c11d9f8f916b1dd82ae3cf9e21 (patch) | |
tree | 3d233be9de4b2c7e7dcf221b210907cdb51b6612 | |
parent | d0a8911cf66b7a4f6a6209698bfabd69af1aa3f5 (diff) | |
download | ModemManager-a12be165d14083c11d9f8f916b1dd82ae3cf9e21.tar.gz |
libmm-glib,modem: avoid accessing an already freed GArray
We cannot g_array_unref() the GArray when get()-ing bands as that will clear
the contents of the GArray, even if there are references around. Instead, just
dup the array contents when returning.
-rw-r--r-- | libmm-glib/mm-modem.c | 77 |
1 files changed, 47 insertions, 30 deletions
diff --git a/libmm-glib/mm-modem.c b/libmm-glib/mm-modem.c index dbf03aee6..25b73a769 100644 --- a/libmm-glib/mm-modem.c +++ b/libmm-glib/mm-modem.c @@ -22,6 +22,7 @@ */ #include <gio/gio.h> +#include <string.h> #include "mm-common-helpers.h" #include "mm-errors-types.h" @@ -988,10 +989,13 @@ supported_bands_updated (MMModem *self, g_mutex_unlock (&self->priv->supported_bands_mutex); } -static void +static gboolean ensure_internal_supported_bands (MMModem *self, - GArray **dup) + MMModemBand **dup_bands, + guint *dup_bands_n) { + gboolean ret; + g_mutex_lock (&self->priv->supported_bands_mutex); { /* If this is the first time ever asking for the array, setup the @@ -1013,10 +1017,24 @@ ensure_internal_supported_bands (MMModem *self, NULL); } - if (dup && self->priv->supported_bands) - *dup = g_array_ref (self->priv->supported_bands); + if (!self->priv->supported_bands) + ret = FALSE; + else { + ret = TRUE; + + if (dup_bands && dup_bands_n) { + *dup_bands_n = self->priv->supported_bands->len; + if (self->priv->supported_bands->len > 0) { + *dup_bands = g_malloc (sizeof (MMModemBand) * self->priv->supported_bands->len); + memcpy (*dup_bands, self->priv->supported_bands->data, sizeof (MMModemBand) * self->priv->supported_bands->len); + } else + *dup_bands = NULL; + } + } } g_mutex_unlock (&self->priv->supported_bands_mutex); + + return ret; } /** @@ -1036,19 +1054,11 @@ mm_modem_get_supported_bands (MMModem *self, MMModemBand **bands, guint *n_bands) { - GArray *array = NULL; - g_return_val_if_fail (MM_IS_MODEM (self), FALSE); g_return_val_if_fail (bands != NULL, FALSE); g_return_val_if_fail (n_bands != NULL, FALSE); - ensure_internal_supported_bands (self, &array); - if (!array) - return FALSE; - - *n_bands = array->len; - *bands = (MMModemBand *)g_array_free (array, FALSE); - return TRUE; + return ensure_internal_supported_bands (self, bands, n_bands); } /** @@ -1072,8 +1082,7 @@ mm_modem_peek_supported_bands (MMModem *self, g_return_val_if_fail (bands != NULL, FALSE); g_return_val_if_fail (n_bands != NULL, FALSE); - ensure_internal_supported_bands (self, NULL); - if (!self->priv->supported_bands) + if (!ensure_internal_supported_bands (self, NULL, NULL)) return FALSE; *n_bands = self->priv->supported_bands->len; @@ -1102,10 +1111,13 @@ bands_updated (MMModem *self, g_mutex_unlock (&self->priv->bands_mutex); } -static void +static gboolean ensure_internal_bands (MMModem *self, - GArray **dup) + MMModemBand **dup_bands, + guint *dup_bands_n) { + gboolean ret; + g_mutex_lock (&self->priv->bands_mutex); { /* If this is the first time ever asking for the array, setup the @@ -1127,10 +1139,24 @@ ensure_internal_bands (MMModem *self, NULL); } - if (dup && self->priv->bands) - *dup = g_array_ref (self->priv->bands); + if (!self->priv->bands) + ret = FALSE; + else { + ret = TRUE; + + if (dup_bands && dup_bands_n) { + *dup_bands_n = self->priv->bands->len; + if (self->priv->bands->len > 0) { + *dup_bands = g_malloc (sizeof (MMModemBand) * self->priv->bands->len); + memcpy (*dup_bands, self->priv->bands->data, sizeof (MMModemBand) * self->priv->bands->len); + } else + *dup_bands = NULL; + } + } } g_mutex_unlock (&self->priv->bands_mutex); + + return ret; } /** @@ -1151,19 +1177,11 @@ mm_modem_get_bands (MMModem *self, MMModemBand **bands, guint *n_bands) { - GArray *array = NULL; - g_return_val_if_fail (MM_IS_MODEM (self), FALSE); g_return_val_if_fail (bands != NULL, FALSE); g_return_val_if_fail (n_bands != NULL, FALSE); - ensure_internal_bands (self, &array); - if (!array) - return FALSE; - - *n_bands = array->len; - *bands = (MMModemBand *)g_array_free (array, FALSE); - return TRUE; + return ensure_internal_bands (self, bands, n_bands); } /** @@ -1188,8 +1206,7 @@ mm_modem_peek_bands (MMModem *self, g_return_val_if_fail (bands != NULL, FALSE); g_return_val_if_fail (n_bands != NULL, FALSE); - ensure_internal_bands (self, NULL); - if (!self->priv->bands) + if (!ensure_internal_bands (self, NULL, NULL)) return FALSE; *n_bands = self->priv->bands->len; |