base-sms: fix segfault when storing already sent messages

The internal list of parts in the base SMS object is created either
when the message is sent or when the message is stored.

The daemon should not expect the list of SMS parts to be empty upon a
store() operation requested via DBus, as the list of parts may have
already been created during send().

Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/598
This commit is contained in:
Aleksander Morgado
2022-07-24 14:46:10 +02:00
parent a8b9058a0c
commit 4aaea37022

View File

@@ -361,31 +361,37 @@ handle_store_ready (MMBaseSms *self,
}
static gboolean
prepare_sms_to_be_stored (MMBaseSms *self,
GError **error)
prepare_sms_to_be_stored (MMBaseSms *self,
GError **error)
{
GList *l;
guint8 reference;
g_assert (self->priv->parts == NULL);
/* Look for a valid multipart reference to use. When storing, we need to
* check whether we have already stored multipart SMS with the same
* reference and destination number */
reference = (mm_iface_modem_messaging_get_local_multipart_reference (
MM_IFACE_MODEM_MESSAGING (self->priv->modem),
mm_gdbus_sms_get_number (MM_GDBUS_SMS (self)),
error));
if (!reference ||
!generate_submit_pdus (self, error)) {
g_prefix_error (error, "Cannot prepare SMS to be stored: ");
/* Create parts if we did not create them already before (e.g. when
* sending) */
if (!self->priv->parts && !generate_submit_pdus (self, error)) {
g_prefix_error (error, "Cannot create submit PDUs: ");
return FALSE;
}
/* If the message is a multipart message, we need to set a proper
* multipart reference. When sending a message which wasn't stored
* yet, we can just get a random multipart reference. */
* yet, we chose a random multipart reference, but that doesn't work
* when storing locally, as we could collide with the references used
* in other existing messages. */
if (self->priv->is_multipart) {
GList *l;
guint8 reference;
/* Look for a valid multipart reference to use. When storing, we need to
* check whether we have already stored multipart SMS with the same
* reference and destination number */
reference = mm_iface_modem_messaging_get_local_multipart_reference (
MM_IFACE_MODEM_MESSAGING (self->priv->modem),
mm_gdbus_sms_get_number (MM_GDBUS_SMS (self)),
error);
if (!reference) {
g_prefix_error (error, "Cannot get local multipart reference: ");
return FALSE;
}
self->priv->multipart_reference = reference;
for (l = self->priv->parts; l; l = g_list_next (l)) {
mm_sms_part_set_concat_reference ((MMSmsPart *)l->data,
@@ -438,6 +444,7 @@ handle_store_auth_ready (MMBaseModem *modem,
/* Prepare the SMS to be stored, creating the PDU list if required */
if (!prepare_sms_to_be_stored (ctx->self, &error)) {
g_prefix_error (&error, "Cannot prepare SMS to be stored: ");
g_dbus_method_invocation_take_error (ctx->invocation, error);
handle_store_context_free (ctx);
return;
@@ -546,11 +553,12 @@ prepare_sms_to_be_sent (MMBaseSms *self,
{
GList *l;
/* If we created the parts when storing, we're fine already */
if (self->priv->parts)
return TRUE;
if (!generate_submit_pdus (self, error)) {
g_prefix_error (error, "Cannot prepare SMS to be sent: ");
g_prefix_error (error, "Cannot create submit PDUs: ");
return FALSE;
}
@@ -606,6 +614,7 @@ handle_send_auth_ready (MMBaseModem *modem,
/* Prepare the SMS to be sent, creating the PDU list if required */
if (!prepare_sms_to_be_sent (ctx->self, &error)) {
g_prefix_error (&error, "Cannot prepare SMS to be sent: ");
g_dbus_method_invocation_take_error (ctx->invocation, error);
handle_send_context_free (ctx);
return;