[gimp] Issue #1730 - pat file that crashes gimp-2.10
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Issue #1730 - pat file that crashes gimp-2.10
- Date: Fri, 6 Jul 2018 11:11:16 +0000 (UTC)
commit 9b56ca8c1d556a051d9a4a04907f08f04da914a6
Author: Michael Natterer <mitch gimp org>
Date: Fri Jul 6 13:07:28 2018 +0200
Issue #1730 - pat file that crashes gimp-2.10
Introduce GIMP_PATTERN_MAX_SIZE (10000) and GIMP_PATTERN_MAX_NAME (256)
and validate pattern dimensions and pattern name length against them.
Add GIMP_BRUSH_MAX_NAME and validate that too.
Also make sure that the names are properly terminated, and some
cleanup.
app/core/gimpbrush-header.h | 1 +
app/core/gimpbrush-load.c | 16 ++++++++++---
app/core/gimppattern-header.h | 5 ++++
app/core/gimppattern-load.c | 29 +++++++++++++++--------
plug-ins/common/file-gbr.c | 19 +++++++++++++---
plug-ins/common/file-gih.c | 10 +++++++-
plug-ins/common/file-pat.c | 53 ++++++++++++++++++++++++++++---------------
7 files changed, 99 insertions(+), 34 deletions(-)
---
diff --git a/app/core/gimpbrush-header.h b/app/core/gimpbrush-header.h
index 62f6840085..9935110c29 100644
--- a/app/core/gimpbrush-header.h
+++ b/app/core/gimpbrush-header.h
@@ -23,6 +23,7 @@
#define GIMP_BRUSH_MAGIC (('G' << 24) + ('I' << 16) + \
('M' << 8) + ('P' << 0))
#define GIMP_BRUSH_MAX_SIZE 10000 /* Max size in either dimension in px */
+#define GIMP_BRUSH_MAX_NAME 256 /* Max length of the brush's name */
/* All field entries are MSB */
diff --git a/app/core/gimpbrush-load.c b/app/core/gimpbrush-load.c
index c065e20d1f..60368181f0 100644
--- a/app/core/gimpbrush-load.c
+++ b/app/core/gimpbrush-load.c
@@ -188,7 +188,7 @@ gimp_brush_load_brush (GimpContext *context,
return NULL;
}
- if (header.width > GIMP_BRUSH_MAX_SIZE ||
+ if (header.width > GIMP_BRUSH_MAX_SIZE ||
header.height > GIMP_BRUSH_MAX_SIZE)
{
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
@@ -247,7 +247,17 @@ gimp_brush_load_brush (GimpContext *context,
{
gchar *utf8;
- name = g_new (gchar, bn_size);
+ if (bn_size > GIMP_BRUSH_MAX_NAME)
+ {
+ g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
+ _("Invalid header data in '%s': "
+ "Brush name is too long: %lu"),
+ gimp_file_get_utf8_name (file),
+ (gulong) bn_size);
+ return NULL;
+ }
+
+ name = g_new0 (gchar, bn_size + 1);
if (! g_input_stream_read_all (input, name, bn_size,
&bytes_read, NULL, error) ||
@@ -264,7 +274,7 @@ gimp_brush_load_brush (GimpContext *context,
name = utf8;
}
- if (!name)
+ if (! name)
name = g_strdup (_("Unnamed"));
brush = g_object_new (GIMP_TYPE_BRUSH,
diff --git a/app/core/gimppattern-header.h b/app/core/gimppattern-header.h
index f6befec163..37dbc983b3 100644
--- a/app/core/gimppattern-header.h
+++ b/app/core/gimppattern-header.h
@@ -18,9 +18,13 @@
#ifndef __GIMP_PATTERN_HEADER_H__
#define __GIMP_PATTERN_HEADER_H__
+
#define GIMP_PATTERN_FILE_VERSION 1
#define GIMP_PATTERN_MAGIC (('G' << 24) + ('P' << 16) + \
('A' << 8) + ('T' << 0))
+#define GIMP_PATTERN_MAX_SIZE 10000 /* Max size in either dimension in px */
+#define GIMP_PATTERN_MAX_NAME 256 /* Max length of the pattern's name */
+
/* All field entries are MSB */
@@ -40,4 +44,5 @@ struct _GimpPatternHeader
* comes the pattern data--width * height * bytes bytes of it...
*/
+
#endif /* __GIMP_PATTERN_HEADER_H__ */
diff --git a/app/core/gimppattern-load.c b/app/core/gimppattern-load.c
index 5f119c5486..85729bf17a 100644
--- a/app/core/gimppattern-load.c
+++ b/app/core/gimppattern-load.c
@@ -45,7 +45,7 @@ gimp_pattern_load (GimpContext *context,
GimpPatternHeader header;
gsize size;
gsize bytes_read;
- gint bn_size;
+ gsize bn_size;
gchar *name = NULL;
g_return_val_if_fail (G_IS_FILE (file), NULL);
@@ -70,8 +70,9 @@ gimp_pattern_load (GimpContext *context,
header.magic_number = g_ntohl (header.magic_number);
/* Check for correct file format */
- if (header.magic_number != GIMP_PATTERN_MAGIC || header.version != 1 ||
- header.header_size <= sizeof (header))
+ if (header.magic_number != GIMP_PATTERN_MAGIC ||
+ header.version != 1 ||
+ header.header_size <= sizeof (header))
{
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
_("Unknown pattern format version %d."),
@@ -90,16 +91,16 @@ gimp_pattern_load (GimpContext *context,
}
/* Validate dimensions */
- if ((header.width == 0) || (header.width > GIMP_MAX_IMAGE_SIZE) ||
- (header.height == 0) || (header.height > GIMP_MAX_IMAGE_SIZE) ||
+ if ((header.width == 0) || (header.width > GIMP_PATTERN_MAX_SIZE) ||
+ (header.height == 0) || (header.height > GIMP_PATTERN_MAX_SIZE) ||
(G_MAXSIZE / header.width / header.height / header.bytes < 1))
{
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
_("Invalid header data in '%s': width=%lu, height=%lu, "
"bytes=%lu"), gimp_file_get_utf8_name (file),
- (unsigned long int)header.width,
- (unsigned long int)header.height,
- (unsigned long int)header.bytes);
+ (gulong) header.width,
+ (gulong) header.height,
+ (gulong) header.bytes);
goto error;
}
@@ -108,7 +109,17 @@ gimp_pattern_load (GimpContext *context,
{
gchar *utf8;
- name = g_new (gchar, bn_size);
+ if (bn_size > GIMP_PATTERN_MAX_NAME)
+ {
+ g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
+ _("Invalid header data in '%s': "
+ "Pattern name is too long: %lu"),
+ gimp_file_get_utf8_name (file),
+ (gulong) bn_size);
+ goto error;
+ }
+
+ name = g_new0 (gchar, bn_size + 1);
if (! g_input_stream_read_all (input, name, bn_size,
&bytes_read, NULL, error) ||
diff --git a/plug-ins/common/file-gbr.c b/plug-ins/common/file-gbr.c
index 38af555ff0..2ebaf78b26 100644
--- a/plug-ins/common/file-gbr.c
+++ b/plug-ins/common/file-gbr.c
@@ -395,8 +395,9 @@ load_image (GFile *file,
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Invalid header data in '%s': width=%lu, height=%lu, "
"bytes=%lu"), g_file_get_parse_name (file),
- (unsigned long int)bh.width, (unsigned long int)bh.height,
- (unsigned long int)bh.bytes);
+ (gulong) bh.width,
+ (gulong) bh.height,
+ (gulong) bh.bytes);
return -1;
}
@@ -459,7 +460,19 @@ load_image (GFile *file,
if ((size = (bh.header_size - sizeof (GimpBrushHeader))) > 0)
{
- gchar *temp = g_new (gchar, size);
+ gchar *temp;
+
+ if (size > GIMP_BRUSH_MAX_NAME)
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Invalid header data in '%s': "
+ "Brush name is too long: %lu"),
+ gimp_file_get_utf8_name (file),
+ (gulong) size);
+ return -1;
+ }
+
+ temp = g_new0 (gchar, size + 1);
if (! g_input_stream_read_all (input, temp, size,
&bytes_read, NULL, error) ||
diff --git a/plug-ins/common/file-gih.c b/plug-ins/common/file-gih.c
index 0d93212d30..8e0255332a 100644
--- a/plug-ins/common/file-gih.c
+++ b/plug-ins/common/file-gih.c
@@ -496,6 +496,14 @@ gih_load_one_brush (GInputStream *input,
if ((size = (bh.header_size - sizeof (bh))) > 0)
{
+ if (size > GIMP_BRUSH_MAX_NAME)
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Brush name is too long: %lu"),
+ (gulong) size);
+ return FALSE;
+ }
+
name = g_new0 (gchar, size + 1);
if (! g_input_stream_read_all (input, name, size,
@@ -704,7 +712,7 @@ gih_load_image (GFile *file,
g_string_free (buffer, FALSE);
- if (!name)
+ if (! name)
{
g_message ("Couldn't read name for brush pipe from '%s'",
g_file_get_parse_name (file));
diff --git a/plug-ins/common/file-pat.c b/plug-ins/common/file-pat.c
index 454fa761c3..c5cbf1a2ba 100644
--- a/plug-ins/common/file-pat.c
+++ b/plug-ins/common/file-pat.c
@@ -332,6 +332,7 @@ load_image (GFile *file,
GimpImageBaseType base_type;
GimpImageType image_type;
gsize bytes_read;
+ gsize size;
gimp_progress_init_printf (_("Opening '%s'"),
g_file_get_parse_name (file));
@@ -364,22 +365,37 @@ load_image (GFile *file,
return -1;
}
- temp = g_new (gchar, ph.header_size - sizeof (GimpPatternHeader));
-
- if (! g_input_stream_read_all (input,
- temp, ph.header_size - sizeof (GimpPatternHeader),
- &bytes_read, NULL, error) ||
- bytes_read != ph.header_size - sizeof (GimpPatternHeader))
+ if ((size = (ph.header_size - sizeof (GimpPatternHeader))) > 0)
{
+ if (size > GIMP_PATTERN_MAX_NAME)
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Invalid header data in '%s': "
+ "Pattern name is too long: %lu"),
+ gimp_file_get_utf8_name (file),
+ (gulong) size);
+ return -1;
+ }
+
+ temp = g_new0 (gchar, size + 1);
+
+ if (! g_input_stream_read_all (input, temp, size,
+ &bytes_read, NULL, error) ||
+ bytes_read != size)
+ {
+ g_free (temp);
+ g_object_unref (input);
+ return -1;
+ }
+
+ name = gimp_any_to_utf8 (temp, size - 1,
+ _("Invalid UTF-8 string in pattern file '%s'."),
+ g_file_get_parse_name (file));
g_free (temp);
- g_object_unref (input);
- return -1;
}
- name = gimp_any_to_utf8 (temp, ph.header_size - sizeof (GimpPatternHeader) - 1,
- _("Invalid UTF-8 string in pattern file '%s'."),
- g_file_get_parse_name (file));
- g_free (temp);
+ if (! name)
+ name = g_strdup (_("Unnamed"));
/* Now there's just raw data left. */
@@ -417,15 +433,16 @@ load_image (GFile *file,
}
/* Sanitize input dimensions and guard against overflows. */
- if ((ph.width == 0) || (ph.width > GIMP_MAX_IMAGE_SIZE) ||
- (ph.height == 0) || (ph.height > GIMP_MAX_IMAGE_SIZE) ||
+ if ((ph.width == 0) || (ph.width > GIMP_PATTERN_MAX_SIZE) ||
+ (ph.height == 0) || (ph.height > GIMP_PATTERN_MAX_SIZE) ||
(G_MAXSIZE / ph.width / ph.bytes < 1))
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Invalid header data in '%s': width=%lu, height=%lu, "
"bytes=%lu"), g_file_get_parse_name (file),
- (unsigned long int)ph.width, (unsigned long int)ph.height,
- (unsigned long int)ph.bytes);
+ (gulong) ph.width,
+ (gulong) ph.height,
+ (gulong) ph.bytes);
g_object_unref (input);
return -1;
}
@@ -449,7 +466,7 @@ load_image (GFile *file,
buffer = gimp_drawable_get_buffer (layer_ID);
- /* this can't overflow because ph.width is <= GIMP_MAX_IMAGE_SIZE */
+ /* this can't overflow because ph.width is <= GIMP_PATTERN_MAX_SIZE */
buf = g_malloc (ph.width * ph.bytes);
for (line = 0; line < ph.height; line++)
@@ -570,7 +587,7 @@ save_image (GFile *file,
line_size = width * babl_format_get_bytes_per_pixel (file_format);
- /* this can't overflow because drawable->width is <= GIMP_MAX_IMAGE_SIZE */
+ /* this can't overflow because drawable->width is <= GIMP_PATTERN_MAX_SIZE */
buf = g_alloca (line_size);
for (line = 0; line < height; line++)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]