Browse code

libclamav: add basic GIF validator

Tomasz Kojm authored on 2011/04/12 00:23:14
Showing 4 changed files
... ...
@@ -1,3 +1,7 @@
1
+Mon Apr 11 17:22:46 CEST 2011 (tk)
2
+----------------------------------
3
+ * libclamav: add basic GIF validator
4
+
1 5
 Sat Apr  9 17:20:35 CEST 2011 (acab)
2 6
 ------------------------------------
3 7
  * libclamav/pe_icons.c: don't sigbus on sparc (bb#2695)
... ...
@@ -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
+}
... ...
@@ -24,5 +24,6 @@
24 24
 #include "others.h"
25 25
 
26 26
 int cli_parsejpeg(cli_ctx *ctx);
27
+int cli_parsegif(cli_ctx *ctx);
27 28
 
28 29
 #endif
... ...
@@ -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! */