... | ... |
@@ -37,18 +37,20 @@ |
37 | 37 |
#include "jpeg.h" |
38 | 38 |
#include "clamav.h" |
39 | 39 |
|
40 |
+#define EC16(x) le16_to_host(x) |
|
41 |
+ |
|
40 | 42 |
#define GETBYTE(v) \ |
41 | 43 |
if(fmap_readn(map, &v, offset, sizeof(v)) == sizeof(v)) { \ |
42 | 44 |
offset += sizeof(v); \ |
43 | 45 |
} else { \ |
44 |
- cli_errmsg("cli_parsejpeg: Can't read file\n"); \ |
|
45 |
- return CL_EREAD; \ |
|
46 |
+ cli_errmsg("cli_parse(jpeg|gif): Can't read file (corrupted?)\n"); \ |
|
47 |
+ return CL_EPARSE; \ |
|
46 | 48 |
} |
47 | 49 |
|
48 | 50 |
int cli_parsejpeg(cli_ctx *ctx) |
49 | 51 |
{ |
50 | 52 |
fmap_t *map = *ctx->fmap; |
51 |
- unsigned char marker, prev_marker, prev_segment = 0, v1, v2, buff[512]; |
|
53 |
+ unsigned char marker, prev_marker, prev_segment = 0, v1, v2, buff[8]; |
|
52 | 54 |
unsigned int offset = 0, i, len, comment = 0, segment = 0, app = 0; |
53 | 55 |
|
54 | 56 |
cli_dbgmsg("in cli_parsejpeg()\n"); |
... | ... |
@@ -202,3 +204,99 @@ int cli_parsejpeg(cli_ctx *ctx) |
202 | 202 |
} |
203 | 203 |
return CL_SUCCESS; |
204 | 204 |
} |
205 |
+ |
|
206 |
+/* GIF */ |
|
207 |
+ |
|
208 |
+struct gif_screen_desc { |
|
209 |
+ uint16_t width; |
|
210 |
+ uint16_t height; |
|
211 |
+ uint8_t flags; |
|
212 |
+ uint8_t bgcolor; |
|
213 |
+ uint8_t aspect; |
|
214 |
+}; |
|
215 |
+ |
|
216 |
+struct gif_graphic_control_ext { |
|
217 |
+ uint8_t blksize; |
|
218 |
+ uint8_t flags; |
|
219 |
+ uint16_t delaytime; |
|
220 |
+ uint8_t tcoloridx; |
|
221 |
+ uint8_t blkterm; |
|
222 |
+}; |
|
223 |
+ |
|
224 |
+struct gif_image_desc { |
|
225 |
+ uint16_t leftpos; |
|
226 |
+ uint16_t toppos; |
|
227 |
+ uint16_t width; |
|
228 |
+ uint16_t height; |
|
229 |
+ uint8_t flags; |
|
230 |
+}; |
|
231 |
+ |
|
232 |
+int cli_parsegif(cli_ctx *ctx) |
|
233 |
+{ |
|
234 |
+ fmap_t *map = *ctx->fmap; |
|
235 |
+ unsigned char magic[6], v; |
|
236 |
+ unsigned int offset = 0, have_gce = 0; |
|
237 |
+ struct gif_screen_desc screen_desc; |
|
238 |
+ struct gif_graphic_control_ext graphic_control_ext; |
|
239 |
+ struct gif_image_desc image_desc; |
|
240 |
+ |
|
241 |
+ cli_dbgmsg("in cli_parsegif()\n"); |
|
242 |
+ |
|
243 |
+ if(fmap_readn(map, magic, offset, 6) != 6) |
|
244 |
+ return CL_SUCCESS; /* Ignore */ |
|
245 |
+ |
|
246 |
+ if(!memcmp(magic, "GIF87a", 6) || !memcmp(magic, "GIF89a", 6)) |
|
247 |
+ offset = 6; |
|
248 |
+ else |
|
249 |
+ return CL_SUCCESS; /* Not a GIF file */ |
|
250 |
+ |
|
251 |
+ if(fmap_readn(map, &screen_desc, offset, sizeof(screen_desc)) != sizeof(screen_desc)) { |
|
252 |
+ cli_warnmsg("cli_parsegif: Can't read Logical Screen Descriptor block\n"); |
|
253 |
+ return CL_EPARSE; |
|
254 |
+ } |
|
255 |
+ offset += 7; |
|
256 |
+ |
|
257 |
+ cli_dbgmsg("GIF: Screen size %ux%u, gctsize: %u\n", EC16(screen_desc.width), EC16(screen_desc.height), screen_desc.flags & 0x7); |
|
258 |
+ if(screen_desc.flags & 0x80) |
|
259 |
+ offset += 3 * (1 << ((screen_desc.flags & 0x7) + 1)); |
|
260 |
+ |
|
261 |
+ while(1) { |
|
262 |
+ GETBYTE(v); |
|
263 |
+ if(v == 0x21) { |
|
264 |
+ GETBYTE(v); |
|
265 |
+ if(v == 0xf9) { |
|
266 |
+ if(fmap_readn(map, &graphic_control_ext, offset, sizeof(graphic_control_ext)) != sizeof(graphic_control_ext)) { |
|
267 |
+ cli_warnmsg("cli_parsegif: Can't read Graphic Control Extension block\n"); |
|
268 |
+ return CL_EPARSE; |
|
269 |
+ } |
|
270 |
+ if(have_gce) { |
|
271 |
+ cli_warnmsg("cli_parsegif: Multiple Graphic Control Extension blocks not allowed\n"); |
|
272 |
+ return CL_EPARSE; |
|
273 |
+ } |
|
274 |
+ have_gce = 1; |
|
275 |
+ offset += sizeof(graphic_control_ext); |
|
276 |
+ if(graphic_control_ext.blksize != 4 || graphic_control_ext.blkterm) { |
|
277 |
+ cli_warnmsg("cli_parsegif: Invalid Graphic Control Extension block\n"); |
|
278 |
+ return CL_EPARSE; |
|
279 |
+ } |
|
280 |
+ } else { |
|
281 |
+ while(1) { |
|
282 |
+ GETBYTE(v); |
|
283 |
+ if(!v) |
|
284 |
+ break; |
|
285 |
+ offset += v; |
|
286 |
+ } |
|
287 |
+ } |
|
288 |
+ } else if(v == 0x2c) { |
|
289 |
+ if(fmap_readn(map, &image_desc, offset, sizeof(image_desc)) != sizeof(image_desc)) { |
|
290 |
+ cli_warnmsg("cli_parsegif: Can't read Image Descriptor block\n"); |
|
291 |
+ return CL_EPARSE; |
|
292 |
+ } |
|
293 |
+ offset += 9; |
|
294 |
+ cli_dbgmsg("GIF: Image size %ux%u, left pos: %u, top pos: %u\n", EC16(image_desc.width), EC16(image_desc.height), EC16(image_desc.leftpos), EC16(image_desc.toppos)); |
|
295 |
+ break; |
|
296 |
+ } |
|
297 |
+ } |
|
298 |
+ |
|
299 |
+ return CL_SUCCESS; |
|
300 |
+} |
... | ... |
@@ -2445,6 +2445,9 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type) |
2445 | 2445 |
|
2446 | 2446 |
if(ctx->img_validate && SCAN_ALGO && ret != CL_VIRUS && ret != CL_EPARSE) |
2447 | 2447 |
ret = cli_parsepng(ctx); |
2448 |
+ |
|
2449 |
+ if(ctx->img_validate && SCAN_ALGO && ret != CL_VIRUS && ret != CL_EPARSE) |
|
2450 |
+ ret = cli_parsegif(ctx); |
|
2448 | 2451 |
break; |
2449 | 2452 |
|
2450 | 2453 |
case CL_TYPE_PDF: /* FIXMELIMITS: pdf should be an archive! */ |