Blob Blame History Raw
From a5fa286732b08b832ea642347963cb0456c1e19f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
Date: Tue, 9 Jul 2019 11:13:09 +0200
Subject: [PATCH 01/28] cogl: Use autopointers to free structs on return

This is a potential leak discovered by static analysis, in fact if
_COGL_GET_CONTEXT returns, the newly allocated struct isn't released.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/682
---
 cogl/cogl-pango/cogl-pango-fontmap.c | 4 ++--
 cogl/cogl/cogl-onscreen.c            | 4 +++-
 cogl/cogl/cogl-pipeline-cache.c      | 4 ++--
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/cogl/cogl-pango/cogl-pango-fontmap.c b/cogl/cogl-pango/cogl-pango-fontmap.c
index 145f3b9e8..3ec64eee6 100644
--- a/cogl/cogl-pango/cogl-pango-fontmap.c
+++ b/cogl/cogl-pango/cogl-pango-fontmap.c
@@ -49,72 +49,72 @@
 #include <pango/pango-renderer.h>
 
 #include "cogl-pango.h"
 #include "cogl-pango-private.h"
 #include "cogl-util.h"
 #include "cogl/cogl-context-private.h"
 
 static GQuark cogl_pango_font_map_get_priv_key (void) G_GNUC_CONST;
 
 typedef struct _CoglPangoFontMapPriv
 {
   CoglContext *ctx;
   PangoRenderer *renderer;
 } CoglPangoFontMapPriv;
 
 static void
 free_priv (gpointer data)
 {
   CoglPangoFontMapPriv *priv = data;
 
   cogl_object_unref (priv->ctx);
   cogl_object_unref (priv->renderer);
 
   g_free (priv);
 }
 
 PangoFontMap *
 cogl_pango_font_map_new (void)
 {
   PangoFontMap *fm = pango_cairo_font_map_new ();
-  CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1);
+  g_autofree CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1);
 
   _COGL_GET_CONTEXT (context, NULL);
 
   priv->ctx = cogl_object_ref (context);
 
   /* XXX: The public pango api doesn't let us sub-class
    * PangoCairoFontMap so we attach our own private data using qdata
    * for now. */
   g_object_set_qdata_full (G_OBJECT (fm),
                            cogl_pango_font_map_get_priv_key (),
-                           priv,
+                           g_steal_pointer (&priv),
                            free_priv);
 
   return fm;
 }
 
 PangoContext *
 cogl_pango_font_map_create_context (CoglPangoFontMap *fm)
 {
   _COGL_RETURN_VAL_IF_FAIL (COGL_PANGO_IS_FONT_MAP (fm), NULL);
 
 #if PANGO_VERSION_CHECK (1, 22, 0)
   /* We can just directly use the pango context from the Cairo font
      map */
   return pango_font_map_create_context (PANGO_FONT_MAP (fm));
 #else
   return pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fm));
 #endif
 }
 
 static CoglPangoFontMapPriv *
 _cogl_pango_font_map_get_priv (CoglPangoFontMap *fm)
 {
   return g_object_get_qdata (G_OBJECT (fm),
 			     cogl_pango_font_map_get_priv_key ());
 }
 
 PangoRenderer *
 _cogl_pango_font_map_get_renderer (CoglPangoFontMap *fm)
 {
   CoglPangoFontMapPriv *priv = _cogl_pango_font_map_get_priv (fm);
diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c
index e766e59d0..fcf7f4168 100644
--- a/cogl/cogl/cogl-onscreen.c
+++ b/cogl/cogl/cogl-onscreen.c
@@ -72,64 +72,66 @@ COGL_GTYPE_DEFINE_BOXED (FrameClosure, frame_closure,
                          cogl_dummy_free);
 COGL_GTYPE_DEFINE_BOXED (OnscreenResizeClosure,
                          onscreen_resize_closure,
                          cogl_dummy_copy,
                          cogl_dummy_free);
 COGL_GTYPE_DEFINE_BOXED (OnscreenDirtyClosure,
                          onscreen_dirty_closure,
                          cogl_dummy_copy,
                          cogl_dummy_free);
 
 static void
 _cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
                                    CoglOnscreenTemplate *onscreen_template)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
 
   _cogl_list_init (&onscreen->frame_closures);
   _cogl_list_init (&onscreen->resize_closures);
   _cogl_list_init (&onscreen->dirty_closures);
 
   framebuffer->config = onscreen_template->config;
   cogl_object_ref (framebuffer->config.swap_chain);
 }
 
 /* XXX: While we still have backend in Clutter we need a dummy object
  * to represent the CoglOnscreen framebuffer that the backend
  * creates... */
 CoglOnscreen *
 _cogl_onscreen_new (void)
 {
-  CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1);
+  g_autofree CoglOnscreen *onscreen_ptr = g_new0 (CoglOnscreen, 1);
+  CoglOnscreen *onscreen;
 
   _COGL_GET_CONTEXT (ctx, NULL);
 
+  onscreen = g_steal_pointer (&onscreen_ptr);
   _cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen),
                           ctx,
                           COGL_FRAMEBUFFER_TYPE_ONSCREEN,
                           0x1eadbeef, /* width */
                           0x1eadbeef); /* height */
   /* NB: make sure to pass positive width/height numbers here
    * because otherwise we'll hit input validation assertions!*/
 
   _cogl_onscreen_init_from_template (onscreen, ctx->display->onscreen_template);
 
   COGL_FRAMEBUFFER (onscreen)->allocated = TRUE;
 
   /* XXX: Note we don't initialize onscreen->winsys in this case. */
 
   return _cogl_onscreen_object_new (onscreen);
 }
 
 CoglOnscreen *
 cogl_onscreen_new (CoglContext *ctx, int width, int height)
 {
   CoglOnscreen *onscreen;
 
   /* FIXME: We are assuming onscreen buffers will always be
      premultiplied so we'll set the premult flag on the bitmap
      format. This will usually be correct because the result of the
      default blending operations for Cogl ends up with premultiplied
      data in the framebuffer. However it is possible for the
      framebuffer to be in whatever format depending on what
      CoglPipeline is used to render to it. Eventually we may want to
      add a way for an application to inform Cogl that the framebuffer
diff --git a/cogl/cogl/cogl-pipeline-cache.c b/cogl/cogl/cogl-pipeline-cache.c
index 62b372406..4267d2ccb 100644
--- a/cogl/cogl/cogl-pipeline-cache.c
+++ b/cogl/cogl/cogl-pipeline-cache.c
@@ -25,91 +25,91 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
  *
  * Authors:
  *   Neil Roberts <neil@linux.intel.com>
  *   Robert Bragg <robert@linux.intel.com>
  */
 
 #ifdef HAVE_CONFIG_H
 #include "cogl-config.h"
 #endif
 
 #include <test-fixtures/test-unit.h>
 
 #include "cogl-context-private.h"
 #include "cogl-pipeline-private.h"
 #include "cogl-pipeline-cache.h"
 #include "cogl-pipeline-hash-table.h"
 
 struct _CoglPipelineCache
 {
   CoglPipelineHashTable fragment_hash;
   CoglPipelineHashTable vertex_hash;
   CoglPipelineHashTable combined_hash;
 };
 
 CoglPipelineCache *
 _cogl_pipeline_cache_new (void)
 {
-  CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
+  g_autofree CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
   unsigned long vertex_state;
   unsigned long layer_vertex_state;
   unsigned int fragment_state;
   unsigned int layer_fragment_state;
 
   _COGL_GET_CONTEXT (ctx, 0);
 
   vertex_state =
     _cogl_pipeline_get_state_for_vertex_codegen (ctx);
   layer_vertex_state =
     COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN;
   fragment_state =
     _cogl_pipeline_get_state_for_fragment_codegen (ctx);
   layer_fragment_state =
     _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx);
 
   _cogl_pipeline_hash_table_init (&cache->vertex_hash,
                                   vertex_state,
                                   layer_vertex_state,
                                   "vertex shaders");
   _cogl_pipeline_hash_table_init (&cache->fragment_hash,
                                   fragment_state,
                                   layer_fragment_state,
                                   "fragment shaders");
   _cogl_pipeline_hash_table_init (&cache->combined_hash,
                                   vertex_state | fragment_state,
                                   layer_vertex_state | layer_fragment_state,
                                   "programs");
 
-  return cache;
+  return g_steal_pointer (&cache);
 }
 
 void
 _cogl_pipeline_cache_free (CoglPipelineCache *cache)
 {
   _cogl_pipeline_hash_table_destroy (&cache->fragment_hash);
   _cogl_pipeline_hash_table_destroy (&cache->vertex_hash);
   _cogl_pipeline_hash_table_destroy (&cache->combined_hash);
   g_free (cache);
 }
 
 CoglPipelineCacheEntry *
 _cogl_pipeline_cache_get_fragment_template (CoglPipelineCache *cache,
                                             CoglPipeline *key_pipeline)
 {
   return _cogl_pipeline_hash_table_get (&cache->fragment_hash,
                                         key_pipeline);
 }
 
 CoglPipelineCacheEntry *
 _cogl_pipeline_cache_get_vertex_template (CoglPipelineCache *cache,
                                           CoglPipeline *key_pipeline)
 {
   return _cogl_pipeline_hash_table_get (&cache->vertex_hash,
                                         key_pipeline);
 }
 
 CoglPipelineCacheEntry *
 _cogl_pipeline_cache_get_combined_template (CoglPipelineCache *cache,
                                             CoglPipeline *key_pipeline)
-- 
2.26.2