Issue #14014: fix removing parasite using already freed parasite's name.

gimp_image_set_simulation_intent() attachs a "image-simulation-intent"
parasite which means that it first detaches and frees the one which was
deserialized from the XCF. When calling gimp_parasite_get_name() on this
later on, we were working on a dangling pointer. It means that the fact
we didn't have crashes most of the time was the unexpected part, not the
crash itself!

Same for gimp_image_set_simulation_bpc() and "image-simulation-bpc"
parasite.

The fix is to swap the order of statements to first detach the parasite.
This commit is contained in:
Jehan 2025-10-28 15:48:57 +01:00
parent db8310a545
commit 95d580aa3a

View file

@ -376,28 +376,32 @@ xcf_load_image (Gimp *gimp,
"image-simulation-intent");
if (parasite)
{
guint32 parasite_size;
const guint8 *intent;
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
guint32 parasite_size;
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
const guint8 *data;
GimpColorRenderingIntent intent;
intent = (const guint8 *) gimp_parasite_get_data (parasite, &parasite_size);
data = (const guint8 *) gimp_parasite_get_data (parasite, &parasite_size);
intent = (GimpColorRenderingIntent) *data;
gimp_parasite_list_remove (private->parasites,
gimp_parasite_get_name (parasite));
if (parasite_size == 1)
{
if (*intent != GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL &&
*intent != GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC &&
*intent != GIMP_COLOR_RENDERING_INTENT_SATURATION &&
*intent != GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC)
if (intent != GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL &&
intent != GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC &&
intent != GIMP_COLOR_RENDERING_INTENT_SATURATION &&
intent != GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC)
{
gimp_message (info->gimp, G_OBJECT (info->progress),
GIMP_MESSAGE_ERROR,
"Unknown simulation rendering intent: %d",
*intent);
intent);
}
else
{
gimp_image_set_simulation_intent (image,
(GimpColorRenderingIntent) *intent);
gimp_image_set_simulation_intent (image, intent);
}
}
else
@ -406,9 +410,6 @@ xcf_load_image (Gimp *gimp,
GIMP_MESSAGE_ERROR,
"Invalid simulation intent data");
}
gimp_parasite_list_remove (private->parasites,
gimp_parasite_get_name (parasite));
}
@ -418,18 +419,19 @@ xcf_load_image (Gimp *gimp,
if (parasite)
{
guint32 parasite_size;
const guint8 *bpc;
gboolean status = FALSE;
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
const guint8 *data;
gboolean bpc;
bpc = (const guint8 *) gimp_parasite_get_data (parasite, &parasite_size);
data = (const guint8 *) gimp_parasite_get_data (parasite, &parasite_size);
bpc = *data ? TRUE : FALSE;
gimp_parasite_list_remove (private->parasites,
gimp_parasite_get_name (parasite));
if (parasite_size == 1)
{
if (*bpc)
status = TRUE;
gimp_image_set_simulation_bpc (image, status);
gimp_image_set_simulation_bpc (image, bpc);
}
else
{
@ -437,9 +439,6 @@ xcf_load_image (Gimp *gimp,
GIMP_MESSAGE_ERROR,
"Invalid simulation bpc data");
}
gimp_parasite_list_remove (private->parasites,
gimp_parasite_get_name (parasite));
}
/* check for a GimpGrid parasite */
@ -479,6 +478,9 @@ xcf_load_image (Gimp *gimp,
g_free (meta_string);
}
gimp_parasite_list_remove (private->parasites,
gimp_parasite_get_name (parasite));
if (metadata)
{
has_metadata = TRUE;
@ -486,9 +488,6 @@ xcf_load_image (Gimp *gimp,
gimp_image_set_metadata (image, metadata, FALSE);
g_object_unref (metadata);
}
gimp_parasite_list_remove (private->parasites,
gimp_parasite_get_name (parasite));
}
/* check for symmetry parasites */