[gnome-software: 1/2] gs-app: Return a reference from gs_app_dup_content_rating()




commit 6f67ca9ebeba3adce1a803a95b37b8373ea76b20
Author: Philip Withnall <pwithnall endlessos org>
Date:   Wed Nov 3 10:04:46 2021 +0000

    gs-app: Return a reference from gs_app_dup_content_rating()
    
    Rename `gs_app_get_content_rating()` to `gs_app_dup_content_rating()`,
    access the `GsApp`’s private data under lock, and atomically return a
    strong reference to the content rating data.
    
    This should avoid a race where the content rating data is returned by
    `get_content_rating()`, and then replaced with new data (from a worker
    thread) while the calling code is using it, resulting in use-after-free
    problems.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Fixes: #1467

 lib/gs-app.c                              | 12 +++++++-----
 lib/gs-app.h                              |  2 +-
 plugins/malcontent/gs-plugin-malcontent.c |  2 +-
 src/gs-age-rating-context-dialog.c        | 10 +++++-----
 src/gs-app-context-bar.c                  |  4 ++--
 5 files changed, 16 insertions(+), 14 deletions(-)
---
diff --git a/lib/gs-app.c b/lib/gs-app.c
index 169af6145..512aa2cf9 100644
--- a/lib/gs-app.c
+++ b/lib/gs-app.c
@@ -2115,21 +2115,23 @@ gs_app_set_local_file (GsApp *app, GFile *local_file)
 }
 
 /**
- * gs_app_get_content_rating:
+ * gs_app_dup_content_rating:
  * @app: a #GsApp
  *
  * Gets the content rating for this application.
  *
- * Returns: (transfer none): a #AsContentRating, or %NULL
+ * Returns: (transfer full) (nullable): a #AsContentRating, or %NULL
  *
- * Since: 40
+ * Since: 41
  **/
 AsContentRating *
-gs_app_get_content_rating (GsApp *app)
+gs_app_dup_content_rating (GsApp *app)
 {
        GsAppPrivate *priv = gs_app_get_instance_private (app);
+       g_autoptr(GMutexLocker) locker = NULL;
        g_return_val_if_fail (GS_IS_APP (app), NULL);
-       return priv->content_rating;
+       locker = g_mutex_locker_new (&priv->mutex);
+       return (priv->content_rating != NULL) ? g_object_ref (priv->content_rating) : NULL;
 }
 
 /**
diff --git a/lib/gs-app.h b/lib/gs-app.h
index 58a6184fd..ac5c82529 100644
--- a/lib/gs-app.h
+++ b/lib/gs-app.h
@@ -371,7 +371,7 @@ void                 gs_app_remove_all_icons        (GsApp          *app);
 GFile          *gs_app_get_local_file          (GsApp          *app);
 void            gs_app_set_local_file          (GsApp          *app,
                                                 GFile          *local_file);
-AsContentRating        *gs_app_get_content_rating      (GsApp          *app);
+AsContentRating        *gs_app_dup_content_rating      (GsApp          *app);
 void            gs_app_set_content_rating      (GsApp          *app,
                                                 AsContentRating *content_rating);
 GsApp          *gs_app_get_runtime             (GsApp          *app);
diff --git a/plugins/malcontent/gs-plugin-malcontent.c b/plugins/malcontent/gs-plugin-malcontent.c
index efbe26f01..8c01b4a53 100644
--- a/plugins/malcontent/gs-plugin-malcontent.c
+++ b/plugins/malcontent/gs-plugin-malcontent.c
@@ -103,7 +103,7 @@ app_is_expected_to_have_content_rating (GsApp *app)
 static gboolean
 app_is_content_rating_appropriate (GsApp *app, MctAppFilter *app_filter)
 {
-       AsContentRating *rating = gs_app_get_content_rating (app);  /* (nullable) */
+       g_autoptr(AsContentRating) rating = gs_app_dup_content_rating (app);  /* (nullable) */
        g_autofree const gchar **oars_sections = mct_app_filter_get_oars_sections (app_filter);
        AsContentRatingValue default_rating_value;
 
diff --git a/src/gs-age-rating-context-dialog.c b/src/gs-age-rating-context-dialog.c
index aeb757aa8..8ffea0e7c 100644
--- a/src/gs-age-rating-context-dialog.c
+++ b/src/gs-age-rating-context-dialog.c
@@ -370,7 +370,7 @@ add_attribute_row (GtkListBox           *list_box,
 /**
  * gs_age_rating_context_dialog_process_attributes:
  * @content_rating: content rating data from an app, retrieved using
- *     gs_app_get_content_rating()
+ *     gs_app_dup_content_rating()
  * @show_worst_only: %TRUE to only process the worst content rating attributes,
  *     %FALSE to process all of them
  * @callback: callback to call for each attribute being processed
@@ -567,7 +567,7 @@ gs_age_rating_context_dialog_update_lozenge (GsApp     *app,
        const gchar *css_class;
        const gchar *locale;
        AsContentRatingSystem system;
-       AsContentRating *content_rating;
+       g_autoptr(AsContentRating) content_rating = NULL;
        GtkStyleContext *context;
        const gchar *css_age_classes[] = {
                "details-rating-18",
@@ -591,7 +591,7 @@ gs_age_rating_context_dialog_update_lozenge (GsApp     *app,
                 as_content_rating_system_to_string (system),
                 locale);
 
-       content_rating = gs_app_get_content_rating (app);
+       content_rating = gs_app_dup_content_rating (app);
        if (content_rating != NULL)
                age = as_content_rating_get_minimum_age (content_rating);
 
@@ -649,7 +649,7 @@ gs_age_rating_context_dialog_update_lozenge (GsApp     *app,
 static void
 update_attributes_list (GsAgeRatingContextDialog *self)
 {
-       AsContentRating *content_rating;
+       g_autoptr(AsContentRating) content_rating = NULL;
        gboolean is_unknown;
        g_autofree gchar *title = NULL;
 
@@ -660,7 +660,7 @@ update_attributes_list (GsAgeRatingContextDialog *self)
                return;
 
        /* Update lozenge and title */
-       content_rating = gs_app_get_content_rating (self->app);
+       content_rating = gs_app_dup_content_rating (self->app);
        gs_age_rating_context_dialog_update_lozenge (self->app,
                                                     self->lozenge,
                                                     self->age,
diff --git a/src/gs-app-context-bar.c b/src/gs-app-context-bar.c
index 3acc8fe7a..ea1e8938f 100644
--- a/src/gs-app-context-bar.c
+++ b/src/gs-app-context-bar.c
@@ -698,7 +698,7 @@ build_age_rating_description (AsContentRating *content_rating)
 static void
 update_age_rating_tile (GsAppContextBar *self)
 {
-       AsContentRating *content_rating;
+       g_autoptr(AsContentRating) content_rating = NULL;
        gboolean is_unknown;
        g_autofree gchar *description = NULL;
 
@@ -708,7 +708,7 @@ update_age_rating_tile (GsAppContextBar *self)
        if (!show_tile_for_non_applications (self, AGE_RATING_TILE))
                return;
 
-       content_rating = gs_app_get_content_rating (self->app);
+       content_rating = gs_app_dup_content_rating (self->app);
        gs_age_rating_context_dialog_update_lozenge (self->app,
                                                     self->tiles[AGE_RATING_TILE].lozenge,
                                                     GTK_LABEL (self->tiles[AGE_RATING_TILE].lozenge_content),


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]