Issue #14985: prevent loading recursive linked layers.

This is part of the fix for #14985, only relative to loading. It assumes
that we already have a XCF with cycling in it and will cleanly load it
(instead of forever cycling). For this to happen, I split a bit some of
the header loading code in separate functions to quickly load the header
of every link recursively until we either reach a parent file (i.e. a
cycle was discovered) or we read them all. It means we don't discover
any level of cycling (however many successive links end up to a previous
file!)

File identity will follow symbolic links as well as verify hard links.

When a cycling link is discovered, the link is downgraded to a raster
layer (showing the last render of this layer).
This commit is contained in:
Jehan 2025-12-13 22:48:11 +01:00
parent c8cce02504
commit c1d2ee744e
3 changed files with 901 additions and 526 deletions

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,12 @@
#pragma once
GimpImage * xcf_load_image (Gimp *gimp,
XcfInfo *info,
GError **error);
GimpImage * xcf_load_image (Gimp *gimp,
XcfInfo *info,
GError **error);
gboolean xcf_load_magic_version (Gimp *gimp,
GInputStream *input,
GFile *input_file,
GimpProgress *progress,
XcfInfo *info);

View file

@ -245,7 +245,6 @@ xcf_load_stream (Gimp *gimp,
XcfInfo info = { 0, };
const gchar *filename;
GimpImage *image = NULL;
gchar id[14];
gboolean success;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
@ -259,41 +258,10 @@ xcf_load_stream (Gimp *gimp,
else
filename = _("Memory Stream");
info.gimp = gimp;
info.input = input;
info.seekable = G_SEEKABLE (input);
info.bytes_per_offset = 4;
info.progress = progress;
info.file = input_file;
info.compression = COMPRESS_NONE;
if (progress)
gimp_progress_start (progress, FALSE, _("Opening '%s'"), filename);
success = TRUE;
xcf_read_int8 (&info, (guint8 *) id, 14);
if (! g_str_has_prefix (id, "gimp xcf "))
{
success = FALSE;
}
else if (strcmp (id + 9, "file") == 0)
{
info.file_version = 0;
}
else if (id[9] == 'v' &&
id[13] == '\0')
{
info.file_version = atoi (id + 10);
}
else
{
success = FALSE;
}
if (info.file_version >= 11)
info.bytes_per_offset = 8;
success = xcf_load_magic_version (gimp, input, input_file, progress, &info);
if (success)
{