mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
8195a56261
commit
9b56ca8c1d
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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) ||
|
||||
|
|
|
@ -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) ||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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++)
|
||||
|
|
Loading…
Reference in New Issue