[gimp/gimp-2-10] plug-ins: fix #6279 Error loading PSD file: Unexpected end of file.
- From: Jacob Boerema <jboerema src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/gimp-2-10] plug-ins: fix #6279 Error loading PSD file: Unexpected end of file.
- Date: Sun, 17 Jan 2021 21:14:16 +0000 (UTC)
commit 3399ee4d2c95dfa7a488e41bb4f4b5b972265708
Author: Jacob Boerema <jgboerema gmail com>
Date: Sun Jan 17 16:05:12 2021 -0500
plug-ins: fix #6279 Error loading PSD file: Unexpected end of file.
We were not handling all possible record sizes for mask info and
in case it was an unknown size we set everything to 0 instead
of reading the parts we do recognize.
Let's make it more flexible by reading the parts we do know
about and skip the remaining data if any.
Also added a few more g_debug statements to make it
easier to check some values when needed.
(cherry picked from commit 83ab86eb8b5056a358ef0bff10a5a14f8a635c19)
plug-ins/file-psd/psd-load.c | 228 +++++++++++++++++++++++++++----------------
plug-ins/file-psd/psd.h | 7 +-
2 files changed, 147 insertions(+), 88 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 25b08a9fc4..ac5c6cc205 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -661,6 +661,15 @@ read_layer_info (PSDimage *img_a,
return NULL;
}
block_len = GUINT32_FROM_BE (block_len);
+ IFDBG(3) g_debug ("Layer mask record size %u", block_len);
+ if (block_len + 4 > block_rem)
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Unsupported or invalid mask info size: %d"),
+ block_len);
+ return NULL;
+ }
+
block_rem -= (block_len + 4);
IFDBG(3) g_debug ("Remaining length %d", block_rem);
@@ -674,28 +683,28 @@ read_layer_info (PSDimage *img_a,
lyr_a[lidx]->layer_mask.right = 0;
lyr_a[lidx]->layer_mask.def_color = 0;
lyr_a[lidx]->layer_mask.extra_def_color = 0;
+ lyr_a[lidx]->layer_mask.flags = 0;
+ lyr_a[lidx]->layer_mask.extra_flags = 0;
+ lyr_a[lidx]->layer_mask.mask_params = 0;
lyr_a[lidx]->layer_mask.mask_flags.relative_pos = FALSE;
lyr_a[lidx]->layer_mask.mask_flags.disabled = FALSE;
lyr_a[lidx]->layer_mask.mask_flags.invert = FALSE;
+ lyr_a[lidx]->layer_mask.mask_flags.rendered = FALSE;
+ lyr_a[lidx]->layer_mask.mask_flags.params_present = FALSE;
- switch (block_len)
+ if (block_len > 0)
{
- case 0:
- break;
-
- case 20:
if (fread (&lyr_a[lidx]->layer_mask.top, 4, 1, f) < 1
|| fread (&lyr_a[lidx]->layer_mask.left, 4, 1, f) < 1
|| fread (&lyr_a[lidx]->layer_mask.bottom, 4, 1, f) < 1
|| fread (&lyr_a[lidx]->layer_mask.right, 4, 1, f) < 1
|| fread (&lyr_a[lidx]->layer_mask.def_color, 1, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.flags, 1, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.extra_def_color, 1, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.extra_flags, 1, 1, f) < 1)
+ || fread (&lyr_a[lidx]->layer_mask.flags, 1, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return NULL;
}
+
lyr_a[lidx]->layer_mask.top =
GINT32_FROM_BE (lyr_a[lidx]->layer_mask.top);
lyr_a[lidx]->layer_mask.left =
@@ -710,94 +719,141 @@ read_layer_info (PSDimage *img_a,
lyr_a[lidx]->layer_mask.flags & 2 ? TRUE : FALSE;
lyr_a[lidx]->layer_mask.mask_flags.invert =
lyr_a[lidx]->layer_mask.flags & 4 ? TRUE : FALSE;
- break;
- case 36: /* If we have a 36 byte mask record assume second data set is correct */
- if (fread (&lyr_a[lidx]->layer_mask.top, 4, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.left, 4, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.bottom, 4, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.right, 4, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.def_color, 1, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.flags, 1, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.extra_def_color, 1, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask.extra_flags, 1, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask_extra.top, 4, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask_extra.left, 4, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask_extra.bottom, 4, 1, f) < 1
- || fread (&lyr_a[lidx]->layer_mask_extra.right, 4, 1, f) < 1)
+ lyr_a[lidx]->layer_mask.mask_flags.rendered =
+ lyr_a[lidx]->layer_mask.flags & 8 ? TRUE : FALSE;
+ lyr_a[lidx]->layer_mask.mask_flags.params_present =
+ lyr_a[lidx]->layer_mask.flags & 16 ? TRUE : FALSE;
+ IFDBG(3)
{
- psd_set_error (feof (f), errno, error);
- return NULL;
+ if (lyr_a[lidx]->layer_mask.flags & 32) g_debug ("Layer mask flags bit 5 set.");
+ if (lyr_a[lidx]->layer_mask.flags & 64) g_debug ("Layer mask flags bit 6 set.");
+ if (lyr_a[lidx]->layer_mask.flags & 128) g_debug ("Layer mask flags bit 7 set.");
}
- lyr_a[lidx]->layer_mask_extra.top =
- GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.top);
- lyr_a[lidx]->layer_mask_extra.left =
- GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.left);
- lyr_a[lidx]->layer_mask_extra.bottom =
- GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.bottom);
- lyr_a[lidx]->layer_mask_extra.right =
- GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.right);
- lyr_a[lidx]->layer_mask.top =
- GINT32_FROM_BE (lyr_a[lidx]->layer_mask.top);
- lyr_a[lidx]->layer_mask.left =
- GINT32_FROM_BE (lyr_a[lidx]->layer_mask.left);
- lyr_a[lidx]->layer_mask.bottom =
- GINT32_FROM_BE (lyr_a[lidx]->layer_mask.bottom);
- lyr_a[lidx]->layer_mask.right =
- GINT32_FROM_BE (lyr_a[lidx]->layer_mask.right);
- lyr_a[lidx]->layer_mask.mask_flags.relative_pos =
- lyr_a[lidx]->layer_mask.flags & 1 ? TRUE : FALSE;
- lyr_a[lidx]->layer_mask.mask_flags.disabled =
- lyr_a[lidx]->layer_mask.flags & 2 ? TRUE : FALSE;
- lyr_a[lidx]->layer_mask.mask_flags.invert =
- lyr_a[lidx]->layer_mask.flags & 4 ? TRUE : FALSE;
- break;
- default:
- IFDBG(1) g_debug ("Unknown layer mask record size ... skipping");
- if (fseek (f, block_len, SEEK_CUR) < 0)
+ block_len -= 18;
+
+ /* According to psd-tools this part comes before reading the
+ * mask parameters. However if all mask parameter flags are
+ * set the size of that would also be more than 18. I'm not
+ * sure if all those flags could be set at the same time or
+ * how to distinguish them. */
+ if (block_len >= 18)
{
- psd_set_error (feof (f), errno, error);
+ if (fread (&lyr_a[lidx]->layer_mask.extra_flags, 1, 1, f) < 1
+ || fread (&lyr_a[lidx]->layer_mask.extra_def_color, 1, 1, f) < 1
+ || fread (&lyr_a[lidx]->layer_mask_extra.top, 4, 1, f) < 1
+ || fread (&lyr_a[lidx]->layer_mask_extra.left, 4, 1, f) < 1
+ || fread (&lyr_a[lidx]->layer_mask_extra.bottom, 4, 1, f) < 1
+ || fread (&lyr_a[lidx]->layer_mask_extra.right, 4, 1, f) < 1)
+ {
+ psd_set_error (feof (f), errno, error);
+ return NULL;
+ }
+ block_len -= 18;
+
+ lyr_a[lidx]->layer_mask_extra.top =
+ GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.top);
+ lyr_a[lidx]->layer_mask_extra.left =
+ GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.left);
+ lyr_a[lidx]->layer_mask_extra.bottom =
+ GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.bottom);
+ lyr_a[lidx]->layer_mask_extra.right =
+ GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.right);
+
+ IFDBG(2) g_debug ("Rect enclosing Layer mask %d %d %d %d",
+ lyr_a[lidx]->layer_mask_extra.left,
+ lyr_a[lidx]->layer_mask_extra.top,
+ lyr_a[lidx]->layer_mask_extra.right,
+ lyr_a[lidx]->layer_mask_extra.bottom);
+ }
+
+ if (block_len > 2 && lyr_a[lidx]->layer_mask.mask_flags.params_present)
+ {
+ gint extra_bytes = 0;
+
+ if (fread (&lyr_a[lidx]->layer_mask.mask_params, 1, 1, f) < 1)
+ {
+ psd_set_error (feof (f), errno, error);
+ return NULL;
+ }
+ block_len--;
+ IFDBG(3) g_debug ("Mask params: %u", lyr_a[lidx]->layer_mask.mask_params);
+
+ /* FIXME Extra bytes with user/vector mask density and feather follow.
+ * We currently can't handle that so we will skip it. */
+ extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 1 ? 1 : 0);
+ extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 2 ? 8 : 0);
+ extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 4 ? 1 : 0);
+ extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 8 ? 8 : 0);
+ IFDBG(3) g_debug ("Extra bytes according to mask parameters %d", extra_bytes);
+ if (fseek (f, extra_bytes, SEEK_CUR) < 0)
+ {
+ psd_set_error (feof (f), errno, error);
+ return NULL;
+ }
+ block_len -= extra_bytes;
+ }
+
+ if (block_len > 0)
+ {
+ /* We have some remaining unknown mask data.
+ * If size is less than 4 it is most likely padding. */
+ IFDBG(1)
+ {
+ if (block_len > 3)
+ g_debug ("Skipping %u bytes of unknown layer mask data", block_len);
+ }
+
+ if (fseek (f, block_len, SEEK_CUR) < 0)
+ {
+ psd_set_error (feof (f), errno, error);
+ return NULL;
+ }
+ }
+
+ /* sanity checks */
+ if (lyr_a[lidx]->layer_mask.bottom < lyr_a[lidx]->layer_mask.top ||
+ lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top > GIMP_MAX_IMAGE_SIZE)
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Unsupported or invalid layer mask height: %d"),
+ lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top);
+ return NULL;
+ }
+ if (lyr_a[lidx]->layer_mask.right < lyr_a[lidx]->layer_mask.left ||
+ lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left > GIMP_MAX_IMAGE_SIZE)
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Unsupported or invalid layer mask width: %d"),
+ lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left);
return NULL;
}
- }
- /* sanity checks */
- if (lyr_a[lidx]->layer_mask.bottom < lyr_a[lidx]->layer_mask.top ||
- lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top > GIMP_MAX_IMAGE_SIZE)
- {
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
- _("Unsupported or invalid layer mask height: %d"),
- lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top);
- return NULL;
- }
- if (lyr_a[lidx]->layer_mask.right < lyr_a[lidx]->layer_mask.left ||
- lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left > GIMP_MAX_IMAGE_SIZE)
- {
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
- _("Unsupported or invalid layer mask width: %d"),
- lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left);
- return NULL;
- }
+ if ((lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left) >
+ G_MAXINT32 / MAX (lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top, 1))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Unsupported or invalid layer mask size: %dx%d"),
+ lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left,
+ lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top);
+ return NULL;
+ }
- if ((lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left) >
- G_MAXINT32 / MAX (lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top, 1))
- {
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
- _("Unsupported or invalid layer mask size: %dx%d"),
- lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left,
- lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top);
- return NULL;
- }
+ IFDBG(2) g_debug ("Layer mask coords %d %d %d %d",
+ lyr_a[lidx]->layer_mask.left,
+ lyr_a[lidx]->layer_mask.top,
+ lyr_a[lidx]->layer_mask.right,
+ lyr_a[lidx]->layer_mask.bottom);
- IFDBG(2) g_debug ("Layer mask coords %d %d %d %d",
- lyr_a[lidx]->layer_mask.left,
- lyr_a[lidx]->layer_mask.top,
- lyr_a[lidx]->layer_mask.right,
- lyr_a[lidx]->layer_mask.bottom);
+ IFDBG(3) g_debug ("Default mask color %d, real color %d",
+ lyr_a[lidx]->layer_mask.def_color,
+ lyr_a[lidx]->layer_mask.extra_def_color);
- IFDBG(3) g_debug ("Default mask color, %d, %d",
- lyr_a[lidx]->layer_mask.def_color,
- lyr_a[lidx]->layer_mask.extra_def_color);
+ IFDBG(3) g_debug ("Mask flags %u, real flags %u, mask params %u",
+ lyr_a[lidx]->layer_mask.flags,
+ lyr_a[lidx]->layer_mask.extra_flags,
+ lyr_a[lidx]->layer_mask.mask_params);
+ }
/* Layer blending ranges */ /* FIXME */
if (fread (&block_len, 4, 1, f) < 1)
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index 20609c87d5..b2fe6d885f 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -506,7 +506,9 @@ typedef struct
{
gboolean relative_pos; /* Mask position recorded relative to layer */
gboolean disabled; /* Mask disabled */
- gboolean invert; /* Invert mask on blending */
+ gboolean invert; /* Invert mask on blending (obsolete according to online specs) */
+ gboolean rendered; /* User mask actually came from rendering other data */
+ gboolean params_present; /* User and/or vector masks have parameters applied to them */
} MaskFlags;
/* PSD Slices */
@@ -545,8 +547,9 @@ typedef struct
gint32 right; /* Layer right */
guchar def_color; /* Default background color */
guchar flags; /* Layer flags */
- guchar extra_def_color; /* Real default background color */
+ guchar mask_params; /* Mask parameters. Only present if bit 4 of flags is set. */
guchar extra_flags; /* Real layer flags */
+ guchar extra_def_color; /* Real user mask background */
MaskFlags mask_flags; /* Flags */
} LayerMask;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]