[gimp] Issue #5888: GIMP 2.99.2 crash when using brush in multiply mode.



commit b3fc24268a39212b21b292655e609f7f9a477a7a
Author: Jehan <jehan girinstud io>
Date:   Tue Nov 10 00:43:08 2020 +0100

    Issue #5888: GIMP 2.99.2 crash when using brush in multiply mode.
    
    The GimpOperationLayerMode variable member in DoLayerBlend was not
    properly constructed. C++ class constructor can be called by creating
    object variables, but with GObject, we have to do it with pointers.
    Otherwise here we were only allocating the memory for the struct, but
    not actually calling any initialization functions.
    
    Also it would seem that the struct was not initialized at zero, as the
    space_fish variable was not NULL when it should (i.e. even with same
    composite and blend space), hence composite_to_blend_fish was not NULL
    and since the operation was not a valid GeglOperation when entering
    gimp_operation_layer_mode_real_process(), we crashed.
    Not sure how it went unseen for so long!
    
    So instead let's make the layer_mode class member into a pointer. As
    such, I have to properly allocate and free it. This is also why I am
    adding a copy constructor which will ref the pointer (otherwise we unref
    more than we ref as the default copy constructor would just copy the
    pointer).

 app/gegl/gimp-gegl-nodes.c                    |  2 +-
 app/operations/layer-modes/gimp-layer-modes.c | 23 ++++++++++-
 app/operations/layer-modes/gimp-layer-modes.h |  3 +-
 app/paint/gimppaintcore-loops.cc              | 56 +++++++++++++++++----------
 4 files changed, 60 insertions(+), 24 deletions(-)
---
diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c
index 0dde5199c6..18edf2a188 100644
--- a/app/gegl/gimp-gegl-nodes.c
+++ b/app/gegl/gimp-gegl-nodes.c
@@ -204,7 +204,7 @@ gimp_gegl_mode_node_set_mode (GeglNode               *node,
    * all its properties
    */
   gegl_node_set (node,
-                 "operation",       gimp_layer_mode_get_operation (mode),
+                 "operation",       gimp_layer_mode_get_operation_name (mode),
                  "layer-mode",      mode,
                  "opacity",         opacity,
                  "blend-space",     blend_space,
diff --git a/app/operations/layer-modes/gimp-layer-modes.c b/app/operations/layer-modes/gimp-layer-modes.c
index 10ff4f3e09..587e1c0b9c 100644
--- a/app/operations/layer-modes/gimp-layer-modes.c
+++ b/app/operations/layer-modes/gimp-layer-modes.c
@@ -1255,7 +1255,7 @@ gimp_layer_mode_get_paint_composite_mode (GimpLayerMode mode)
 }
 
 const gchar *
-gimp_layer_mode_get_operation (GimpLayerMode mode)
+gimp_layer_mode_get_operation_name (GimpLayerMode mode)
 {
   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
 
@@ -1265,6 +1265,27 @@ gimp_layer_mode_get_operation (GimpLayerMode mode)
   return info->op_name;
 }
 
+GeglOperation *
+gimp_layer_mode_get_operation (GimpLayerMode mode)
+{
+  const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
+  GeglNode                *node;
+  GeglOperation           *operation;
+
+  if (! info)
+    info = layer_mode_infos;
+
+  node = gegl_node_new_child (NULL,
+                              "operation", info->op_name,
+                              NULL);
+
+  operation = gegl_node_get_gegl_operation (node);
+  g_object_ref (operation);
+  g_object_unref (node);
+
+  return operation;
+}
+
 GimpLayerModeFunc
 gimp_layer_mode_get_function (GimpLayerMode mode)
 {
diff --git a/app/operations/layer-modes/gimp-layer-modes.h b/app/operations/layer-modes/gimp-layer-modes.h
index 30c5e152a4..c98a392c61 100644
--- a/app/operations/layer-modes/gimp-layer-modes.h
+++ b/app/operations/layer-modes/gimp-layer-modes.h
@@ -40,7 +40,8 @@ GimpLayerColorSpace        gimp_layer_mode_get_composite_space        (GimpLayer
 GimpLayerCompositeMode     gimp_layer_mode_get_composite_mode         (GimpLayerMode           mode);
 GimpLayerCompositeMode     gimp_layer_mode_get_paint_composite_mode   (GimpLayerMode           mode);
 
-const gchar              * gimp_layer_mode_get_operation              (GimpLayerMode           mode);
+const gchar              * gimp_layer_mode_get_operation_name         (GimpLayerMode           mode);
+GeglOperation            * gimp_layer_mode_get_operation              (GimpLayerMode           mode);
 
 GimpLayerModeFunc          gimp_layer_mode_get_function               (GimpLayerMode           mode);
 GimpLayerModeBlendFunc     gimp_layer_mode_get_blend_function         (GimpLayerMode           mode);
diff --git a/app/paint/gimppaintcore-loops.cc b/app/paint/gimppaintcore-loops.cc
index 4e2686853b..8aec8ca8fe 100644
--- a/app/paint/gimppaintcore-loops.cc
+++ b/app/paint/gimppaintcore-loops.cc
@@ -1876,30 +1876,44 @@ struct DoLayerBlend : Base
 
   static constexpr gint max_n_iterators = Base::max_n_iterators + 2;
 
-  const Babl             *iterator_format;
-  GimpOperationLayerMode  layer_mode;
+  const Babl                     *iterator_format;
+  GimpOperationLayerMode         *layer_mode = NULL;
+  const GimpPaintCoreLoopsParams *params;
 
   explicit
   DoLayerBlend (const GimpPaintCoreLoopsParams *params) :
-    Base (params)
+    Base (params), params(params)
   {
-    layer_mode.layer_mode      = params->paint_mode;
-    layer_mode.opacity         = params->image_opacity;
-    layer_mode.function        = gimp_layer_mode_get_function (params->paint_mode);
-    layer_mode.blend_function  = gimp_layer_mode_get_blend_function (params->paint_mode);
-    layer_mode.blend_space     = gimp_layer_mode_get_blend_space (params->paint_mode);
-    layer_mode.composite_space = gimp_layer_mode_get_composite_space (params->paint_mode);
-    layer_mode.composite_mode  = gimp_layer_mode_get_paint_composite_mode (params->paint_mode);
+    layer_mode = GIMP_OPERATION_LAYER_MODE (gimp_layer_mode_get_operation (params->paint_mode));
+    layer_mode->layer_mode      = params->paint_mode;
+    layer_mode->opacity         = params->image_opacity;
+    layer_mode->function        = gimp_layer_mode_get_function (params->paint_mode);
+    layer_mode->blend_function  = gimp_layer_mode_get_blend_function (params->paint_mode);
+    layer_mode->blend_space     = gimp_layer_mode_get_blend_space (params->paint_mode);
+    layer_mode->composite_space = gimp_layer_mode_get_composite_space (params->paint_mode);
+    layer_mode->composite_mode  = gimp_layer_mode_get_paint_composite_mode (params->paint_mode);
 
     iterator_format = gimp_layer_mode_get_format (params->paint_mode,
-                                                  layer_mode.blend_space,
-                                                  layer_mode.composite_space,
-                                                  layer_mode.composite_mode,
+                                                  layer_mode->blend_space,
+                                                  layer_mode->composite_space,
+                                                  layer_mode->composite_mode,
                                                   gimp_temp_buf_get_format (params->paint_buf));
 
     g_return_if_fail (gimp_temp_buf_get_format (params->paint_buf) == iterator_format);
   }
 
+  DoLayerBlend (const DoLayerBlend &algorithm) :
+    Base (algorithm.params), params(algorithm.params)
+  {
+    layer_mode = GIMP_OPERATION_LAYER_MODE (g_object_ref (algorithm.layer_mode));
+    iterator_format = algorithm.iterator_format;
+  }
+
+  ~DoLayerBlend ()
+  {
+    g_clear_object (&layer_mode);
+  }
+
   template <class Derived>
   struct State : Base::template State<Derived>
   {
@@ -2006,14 +2020,14 @@ struct DoLayerBlend : Base
 
     state->process_roi.y = y;
 
-    layer_mode.function ((GeglOperation*) &layer_mode,
-                         state->in_pixel,
-                         state->paint_pixel,
-                         mask_pixel,
-                         out_pixel,
-                         rect->width,
-                         &state->process_roi,
-                         0);
+    layer_mode->function ((GeglOperation*) layer_mode,
+                          state->in_pixel,
+                          state->paint_pixel,
+                          mask_pixel,
+                          out_pixel,
+                          rect->width,
+                          &state->process_roi,
+                          0);
 
     state->in_pixel     += rect->width * 4;
     state->paint_pixel  += this->paint_stride;


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