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++)