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).
This commit is contained in:
Jehan 2020-11-10 00:43:08 +01:00
parent 93756733ee
commit b3fc24268a
4 changed files with 60 additions and 24 deletions

View File

@ -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,

View File

@ -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)
{

View File

@ -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);

View File

@ -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;