media-gfx/gimp: amd64 stable wrt bug #641954
[gentoo.git] / media-gfx / gimp / files / gimp-2.8.22-cve-2017-17785.patch
1 From 1882bac996a20ab5c15c42b0c5e8f49033a1af54 Mon Sep 17 00:00:00 2001
2 From: Tobias Stoeckmann <tobias@stoeckmann.org>
3 Date: Sun, 29 Oct 2017 15:19:41 +0100
4 Subject: Bug 739133 - (CVE-2017-17785) Heap overflow while parsing FLI files.
5
6 It is possible to trigger a heap overflow while parsing FLI files. The
7 RLE decoder is vulnerable to out of boundary writes due to lack of
8 boundary checks.
9
10 The variable "framebuf" points to a memory area which was allocated
11 with fli_header->width * fli_header->height bytes. The RLE decoder
12 therefore must never write beyond that limit.
13
14 If an illegal frame is detected, the parser won't stop, which means
15 that the next valid sequence is properly parsed again. This should
16 allow GIMP to parse FLI files as good as possible even if they are
17 broken by an attacker or by accident.
18
19 While at it, I changed the variable xc to be of type size_t, because
20 the multiplication of width and height could overflow a 16 bit type.
21
22 Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
23 (cherry picked from commit edb251a7ef1602d20a5afcbf23f24afb163de63b)
24 ---
25  plug-ins/file-fli/fli.c | 50 ++++++++++++++++++++++++++++++++++---------------
26  1 file changed, 35 insertions(+), 15 deletions(-)
27
28 diff --git a/plug-ins/file-fli/fli.c b/plug-ins/file-fli/fli.c
29 index 313efeb..ffb651e 100644
30 --- a/plug-ins/file-fli/fli.c
31 +++ b/plug-ins/file-fli/fli.c
32 @@ -25,6 +25,8 @@
33  
34  #include "config.h"
35  
36 +#include <glib/gstdio.h>
37 +
38  #include <string.h>
39  #include <stdio.h>
40  
41 @@ -461,23 +463,27 @@ void fli_read_brun(FILE *f, s_fli_header *fli_header, unsigned char *framebuf)
42         unsigned short yc;
43         unsigned char *pos;
44         for (yc=0; yc < fli_header->height; yc++) {
45 -               unsigned short xc, pc, pcnt;
46 +               unsigned short pc, pcnt;
47 +               size_t n, xc;
48                 pc=fli_read_char(f);
49                 xc=0;
50                 pos=framebuf+(fli_header->width * yc);
51 +               n=(size_t)fli_header->width * (fli_header->height-yc);
52                 for (pcnt=pc; pcnt>0; pcnt--) {
53                         unsigned short ps;
54                         ps=fli_read_char(f);
55                         if (ps & 0x80) {
56                                 unsigned short len;
57 -                               for (len=-(signed char)ps; len>0; len--) {
58 +                               for (len=-(signed char)ps; len>0 && xc<n; len--) {
59                                         pos[xc++]=fli_read_char(f);
60                                 }
61                         } else {
62                                 unsigned char val;
63 +                               size_t len;
64 +                               len=MIN(n-xc,ps);
65                                 val=fli_read_char(f);
66 -                               memset(&(pos[xc]), val, ps);
67 -                               xc+=ps;
68 +                               memset(&(pos[xc]), val, len);
69 +                               xc+=len;
70                         }
71                 }
72         }
73 @@ -564,25 +570,34 @@ void fli_read_lc(FILE *f, s_fli_header *fli_header, unsigned char *old_framebuf,
74         memcpy(framebuf, old_framebuf, fli_header->width * fli_header->height);
75         firstline = fli_read_short(f);
76         numline = fli_read_short(f);
77 +       if (numline > fli_header->height || fli_header->height-numline < firstline)
78 +               return;
79 +
80         for (yc=0; yc < numline; yc++) {
81 -               unsigned short xc, pc, pcnt;
82 +               unsigned short pc, pcnt;
83 +               size_t n, xc;
84                 pc=fli_read_char(f);
85                 xc=0;
86                 pos=framebuf+(fli_header->width * (firstline+yc));
87 +               n=(size_t)fli_header->width * (fli_header->height-firstline-yc);
88                 for (pcnt=pc; pcnt>0; pcnt--) {
89                         unsigned short ps,skip;
90                         skip=fli_read_char(f);
91                         ps=fli_read_char(f);
92 -                       xc+=skip;
93 +                       xc+=MIN(n-xc,skip);
94                         if (ps & 0x80) {
95                                 unsigned char val;
96 +                               size_t len;
97                                 ps=-(signed char)ps;
98                                 val=fli_read_char(f);
99 -                               memset(&(pos[xc]), val, ps);
100 -                               xc+=ps;
101 +                               len=MIN(n-xc,ps);
102 +                               memset(&(pos[xc]), val, len);
103 +                               xc+=len;
104                         } else {
105 -                               fread(&(pos[xc]), ps, 1, f);
106 -                               xc+=ps;
107 +                               size_t len;
108 +                               len=MIN(n-xc,ps);
109 +                               fread(&(pos[xc]), len, 1, f);
110 +                               xc+=len;
111                         }
112                 }
113         }
114 @@ -689,7 +704,8 @@ void fli_read_lc_2(FILE *f, s_fli_header *fli_header, unsigned char *old_framebu
115         yc=0;
116         numline = fli_read_short(f);
117         for (lc=0; lc < numline; lc++) {
118 -               unsigned short xc, pc, pcnt, lpf, lpn;
119 +               unsigned short pc, pcnt, lpf, lpn;
120 +               size_t n, xc;
121                 pc=fli_read_short(f);
122                 lpf=0; lpn=0;
123                 while (pc & 0x8000) {
124 @@ -700,26 +716,30 @@ void fli_read_lc_2(FILE *f, s_fli_header *fli_header, unsigned char *old_framebu
125                         }
126                         pc=fli_read_short(f);
127                 }
128 +               yc=MIN(yc, fli_header->height);
129                 xc=0;
130                 pos=framebuf+(fli_header->width * yc);
131 +               n=(size_t)fli_header->width * (fli_header->height-yc);
132                 for (pcnt=pc; pcnt>0; pcnt--) {
133                         unsigned short ps,skip;
134                         skip=fli_read_char(f);
135                         ps=fli_read_char(f);
136 -                       xc+=skip;
137 +                       xc+=MIN(n-xc,skip);
138                         if (ps & 0x80) {
139                                 unsigned char v1,v2;
140                                 ps=-(signed char)ps;
141                                 v1=fli_read_char(f);
142                                 v2=fli_read_char(f);
143 -                               while (ps>0) {
144 +                               while (ps>0 && xc+1<n) {
145                                         pos[xc++]=v1;
146                                         pos[xc++]=v2;
147                                         ps--;
148                                 }
149                         } else {
150 -                               fread(&(pos[xc]), ps, 2, f);
151 -                               xc+=ps << 1;
152 +                               size_t len;
153 +                               len=MIN((n-xc)/2,ps);
154 +                               fread(&(pos[xc]), len, 2, f);
155 +                               xc+=len << 1;
156                         }
157                 }
158                 if (lpf) pos[xc]=lpn;
159 -- 
160 cgit v0.12
161