summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2013-05-23 15:52:31 +0200
committerAleksander Morgado <aleksander@lanedo.com>2013-05-23 18:00:03 +0200
commita12be165d14083c11d9f8f916b1dd82ae3cf9e21 (patch)
tree3d233be9de4b2c7e7dcf221b210907cdb51b6612
parentd0a8911cf66b7a4f6a6209698bfabd69af1aa3f5 (diff)
downloadModemManager-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.c77
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;