Browse code

Zip module failure in pdf files - bb#617

git-svn: trunk@3547

aCaB authored on 2008/01/27 04:25:29
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Sat Jan 26 20:03:30 CET 2008 (acab)
2
+-----------------------------------
3
+  * libclamav/pdf.c: Zip module failure in pdf files - bb#617
4
+
1 5
 Fri Jan 25 18:03:22 CET 2008 (tk)
2 6
 ---------------------------------
3 7
   * libclamav/cab.c: properly handle stored files
... ...
@@ -76,7 +76,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
76 76
 {
77 77
 	off_t size;	/* total number of bytes in the file */
78 78
 	off_t bytesleft, trailerlength;
79
-	char *buf, *alloced;	/* start of memory mapped area */
79
+	char *buf;	/* start of memory mapped area */
80 80
 	const char *p, *q, *trailerstart;
81 81
 	const char *xrefstart;	/* cross reference table */
82 82
 	const struct cl_limits *limits;
... ...
@@ -88,30 +88,20 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
88 88
 
89 89
 	cli_dbgmsg("in cli_pdf(%s)\n", dir);
90 90
 
91
-	if(fstat(desc, &statb) < 0)
91
+	if(fstat(desc, &statb) < 0) {
92
+		cli_errmsg("cli_pdf: fstat() failed\n");
92 93
 		return CL_EOPEN;
94
+	}
93 95
 
94 96
 	size = statb.st_size;
95 97
 
96
-	if(size == 0)
97
-		return CL_CLEAN;
98
-
99 98
 	if(size <= 7)	/* doesn't even include the file header */
100
-		return CL_EFORMAT;
99
+		return CL_CLEAN;
101 100
 
102 101
 	p = buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0);
103
-	if(buf == MAP_FAILED)
102
+	if(buf == MAP_FAILED) {
103
+		cli_errmsg("cli_pdf: mmap() failed\n");
104 104
 		return CL_EMEM;
105
-
106
-	alloced = cli_malloc(size);
107
-	if(alloced) {
108
-		/*
109
-		 * FIXME: now I have this, there's no need for the lack of
110
-		 *	support on systems without mmap, e.g. cygwin
111
-		 */
112
-		memcpy(alloced, buf, size);
113
-		munmap(buf, size);
114
-		p = alloced;
115 105
 	}
116 106
 
117 107
 	cli_dbgmsg("cli_pdf: scanning %lu bytes\n", (unsigned long)size);
... ...
@@ -120,21 +110,16 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
120 120
 
121 121
 	/* File Header */
122 122
 	if(memcmp(p, "%PDF-1.", 7) != 0) {
123
-		if(alloced)
124
-			free(alloced);
125
-		else
126
-			munmap(buf, size);
127
-		return CL_EFORMAT;
123
+		munmap(buf, size);
124
+		cli_dbgmsg("cli_pdf: file header not found\n");
125
+		return CL_CLEAN;
128 126
 	}
129 127
 
130 128
 #if	0
131 129
 	q = pdf_nextlinestart(&p[6], size - 6);
132 130
 	if(q == NULL) {
133
-		if(alloced)
134
-			free(alloced);
135
-		else
136
-			munmap(buf, size);
137
-		return CL_EFORMAT;
131
+		munmap(buf, size);
132
+		return CL_CLEAN;
138 133
 	}
139 134
 	bytesleft = size - (long)(q - p);
140 135
 	p = q;
... ...
@@ -149,11 +134,9 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
149 149
 			break;
150 150
 
151 151
 	if(q <= p) {
152
-		if(alloced)
153
-			free(alloced);
154
-		else
155
-			munmap(buf, size);
156
-		return CL_EFORMAT;
152
+		munmap(buf, size);
153
+		cli_dbgmsg("cli_pdf: trailer not found\n");
154
+		return CL_CLEAN;
157 155
 	}
158 156
 
159 157
 	for(trailerstart = &q[-7]; trailerstart > p; --trailerstart)
... ...
@@ -170,12 +153,9 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
170 170
 		 * http://www.cs.cmu.edu/~dst/Adobe/Gallery/anon21jul01-pdf-encryption.txt
171 171
 		 * http://www.adobe.com/devnet/pdf/
172 172
 		 */
173
-		if(alloced)
174
-			free(alloced);
175
-		else
176
-			munmap(buf, size);
177
-		cli_warnmsg("Encrypted PDF files not yet supported\n");
178
-		return CL_EFORMAT;
173
+		munmap(buf, size);
174
+		cli_dbgmsg("cli_pdf: Encrypted PDF files not yet supported\n");
175
+		return CL_CLEAN;
179 176
 	}
180 177
 
181 178
 	/*
... ...
@@ -196,11 +176,9 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
196 196
 				break;
197 197
 
198 198
 	if(xrefstart == p) {
199
-		if(alloced)
200
-			free(alloced);
201
-		else
202
-			munmap(buf, size);
203
-		return CL_EFORMAT;
199
+		munmap(buf, size);
200
+		cli_dbgmsg("cli_pdf: xref not found\n");
201
+		return CL_CLEAN;
204 202
 	}
205 203
 
206 204
 	printed_predictor_message = printed_embedded_font_message = 0;
... ...
@@ -241,14 +219,14 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
241 241
 		if(memcmp(q, "endobj", 6) == 0)
242 242
 			continue;
243 243
 		if(!isdigit(*q)) {
244
-			cli_warnmsg("cli_pdf: Object number missing\n");
245
-			rc = CL_EFORMAT;
244
+			cli_dbgmsg("cli_pdf: Object number missing\n");
245
+			rc = CL_CLEAN;
246 246
 			break;
247 247
 		}
248 248
 		q = pdf_nextobject(p, bytesleft);
249 249
 		if((q == NULL) || !isdigit(*q)) {
250
-			cli_warnmsg("cli_pdf: Generation number missing\n");
251
-			rc = CL_EFORMAT;
250
+			cli_dbgmsg("cli_pdf: Generation number missing\n");
251
+			rc = CL_CLEAN;
252 252
 			break;
253 253
 		}
254 254
 		/*generation_number = atoi(q);*/
... ...
@@ -257,8 +235,8 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
257 257
 
258 258
 		q = pdf_nextobject(p, bytesleft);
259 259
 		if((q == NULL) || (memcmp(q, "obj", 3) != 0)) {
260
-			cli_warnmsg("Indirect object missing \"obj\"\n");
261
-			rc = CL_EFORMAT;
260
+			cli_dbgmsg("cli_pdf: Indirect object missing \"obj\"\n");
261
+			rc = CL_CLEAN;
262 262
 			break;
263 263
 		}
264 264
 
... ...
@@ -266,7 +244,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
266 266
 		objstart = p = &q[3];
267 267
 		objend = cli_pmemstr(p, bytesleft, "endobj", 6);
268 268
 		if(objend == NULL) {
269
-			cli_dbgmsg("No matching endobj\n");
269
+			cli_dbgmsg("cli_pdf: No matching endobj\n");
270 270
 			break;
271 271
 		}
272 272
 		bytesleft -= (off_t)((objend - p) + 6);
... ...
@@ -303,17 +281,15 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
303 303
 						char b[14];
304 304
 
305 305
 						q += 4;
306
-						cli_dbgmsg("Length is in indirect obj %lu\n",
306
+						cli_dbgmsg("cli_pdf: Length is in indirect obj %lu\n",
307 307
 							length);
308 308
 						snprintf(b, sizeof(b),
309 309
 							"\n%lu 0 obj", length);
310 310
 						length = (unsigned long)strlen(b);
311
-						r = cli_pmemstr(alloced ? alloced : buf,
312
-							size, b, length);
311
+						r = cli_pmemstr(buf, size, b, length);
313 312
 						if(r == NULL) {
314 313
 							b[0] = '\r';
315
-							r = cli_pmemstr(alloced ? alloced : buf,
316
-								size, b, length);
314
+							r = cli_pmemstr(buf, size, b, length);
317 315
 						}
318 316
 						if(r) {
319 317
 							r += length - 1;
... ...
@@ -322,12 +298,12 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
322 322
 								length = atoi(r);
323 323
 								while(isdigit(*r))
324 324
 									r++;
325
-								cli_dbgmsg("length in '%s' %lu\n",
325
+								cli_dbgmsg("cli_pdf: length in '%s' %lu\n",
326 326
 									&b[1],
327 327
 									length);
328 328
 							}
329 329
 						} else
330
-							cli_warnmsg("Couldn't find '%s'\n",
330
+							cli_dbgmsg("cli_pdf: Couldn't find '%s'\n",
331 331
 								&b[1]);
332 332
 					}
333 333
 					q--;
... ...
@@ -360,7 +336,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
360 360
 			 * (http://safari.adobepress.com/0321304748)
361 361
 			 */
362 362
 			if(!printed_embedded_font_message) {
363
-				cli_dbgmsg("Embedded fonts not yet supported\n");
363
+				cli_dbgmsg("cli_pdf: Embedded fonts not yet supported\n");
364 364
 				printed_embedded_font_message = 1;
365 365
 			}
366 366
 			continue;
... ...
@@ -370,7 +346,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
370 370
 			 * Needs some thought
371 371
 			 */
372 372
 			if(!printed_predictor_message) {
373
-				cli_dbgmsg("Predictor %d not honoured for embedded image\n",
373
+				cli_dbgmsg("cli_pdf: Predictor %d not honoured for embedded image\n",
374 374
 					predictor);
375 375
 				printed_predictor_message = 1;
376 376
 			}
... ...
@@ -389,7 +365,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
389 389
 		if(streamend == NULL) {
390 390
 			streamend = cli_pmemstr(streamstart, len, "endstream\r", 10);
391 391
 			if(streamend == NULL) {
392
-				cli_dbgmsg("No endstream\n");
392
+				cli_dbgmsg("cli_pdf: No endstream\n");
393 393
 				break;
394 394
 			}
395 395
 			has_cr = 1;
... ...
@@ -434,7 +410,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
434 434
 
435 435
 		if(streamend <= streamstart) {
436 436
 			close(fout);
437
-			cli_dbgmsg("Empty stream\n");
437
+			cli_dbgmsg("cli_pdf: Empty stream\n");
438 438
 			unlink(fullname);
439 439
 			continue;
440 440
 		}
... ...
@@ -444,7 +420,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
444 444
 		if(calculated_streamlen != real_streamlen)
445 445
 			cli_dbgmsg("cli_pdf: Incorrect Length field in file attempting to recover\n");
446 446
 
447
-		cli_dbgmsg("length %lu, calculated_streamlen %lu isFlate %d isASCII85 %d\n",
447
+		cli_dbgmsg("cli_pdf: length %lu, calculated_streamlen %lu isFlate %d isASCII85 %d\n",
448 448
 			length, calculated_streamlen,
449 449
 			is_flatedecode, is_ascii85decode);
450 450
 
... ...
@@ -472,7 +448,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
472 472
 				free(tmpbuf);
473 473
 				close(fout);
474 474
 				unlink(fullname);
475
-				rc = CL_EFORMAT;
475
+				rc = CL_CLEAN;
476 476
 				continue;
477 477
 			}
478 478
 			if(ret) {
... ...
@@ -480,8 +456,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
480 480
 
481 481
 				real_streamlen = ret;
482 482
 				/* free unused trailing bytes */
483
-				t = (unsigned char *)cli_realloc(tmpbuf,
484
-					calculated_streamlen);
483
+				t = (unsigned char *)cli_realloc(tmpbuf,calculated_streamlen);
485 484
 				if(t == NULL) {
486 485
 					free(tmpbuf);
487 486
 					close(fout);
... ...
@@ -526,10 +501,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
526 526
 		}
527 527
 	}
528 528
 
529
-	if(alloced)
530
-		free(alloced);
531
-	else
532
-		munmap(buf, size);
529
+	munmap(buf, size);
533 530
 
534 531
 	tableDestroy(md5table);
535 532
 
... ...
@@ -552,8 +524,8 @@ try_flatedecode(unsigned char *buf, off_t real_len, off_t calculated_len, int fo
552 552
 		/*
553 553
 		 * Nothing more we can do to inflate
554 554
 		 */
555
-		cli_warnmsg("Bad compression in flate stream\n");
556
-		return (ret == CL_SUCCESS) ? CL_EFORMAT : ret;
555
+		cli_dbgmsg("cli_pdf: Bad compression in flate stream\n");
556
+		return CL_CLEAN;
557 557
 	}
558 558
 
559 559
 	ret = flatedecode(buf, calculated_len, fout, ctx);
... ...
@@ -561,7 +533,7 @@ try_flatedecode(unsigned char *buf, off_t real_len, off_t calculated_len, int fo
561 561
 		return CL_SUCCESS;
562 562
 
563 563
 	/* i.e. the PDF file is broken :-( */
564
-	cli_warnmsg("cli_pdf: Bad compressed block length in flate stream\n");
564
+	cli_dbgmsg("cli_pdf: Bad compressed block length in flate stream\n");
565 565
 
566 566
 	return ret;
567 567
 }
... ...
@@ -581,7 +553,7 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
581 581
 	cli_dbgmsg("cli_pdf: flatedecode %lu bytes\n", (unsigned long)len);
582 582
 
583 583
 	if(len == 0) {
584
-		cli_warnmsg("cli_pdf: flatedecode len == 0\n");
584
+		cli_dbgmsg("cli_pdf: flatedecode len == 0\n");
585 585
 		return CL_CLEAN;
586 586
 	}
587 587
 
... ...
@@ -597,7 +569,7 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
597 597
 	tmpfd = mkstemp(tmpfilename);
598 598
 	if(tmpfd < 0) {
599 599
 		perror(tmpfilename);
600
-		cli_errmsg("Can't make debugging file\n");
600
+		cli_errmsg("cli_pdf: Can't make debugging file\n");
601 601
 	} else {
602 602
 		FILE *tmpfp = fdopen(tmpfd, "w");
603 603
 
... ...
@@ -621,7 +593,7 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
621 621
 	zstat = inflateInit(&stream);
622 622
 	if(zstat != Z_OK) {
623 623
 		cli_warnmsg("cli_pdf: inflateInit failed");
624
-		return CL_EZIP;
624
+		return CL_EMEM;
625 625
 	}
626 626
 
627 627
 	nbytes = 0;
... ...
@@ -631,20 +603,25 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
631 631
 		switch(zstat) {
632 632
 			case Z_OK:
633 633
 				if(stream.avail_out == 0) {
634
-
635
-					nbytes += cli_writen(fout, output, sizeof(output));
634
+				  	int written;
635
+					if ((written=cli_writen(fout, output, sizeof(output)))!=sizeof(output)) {
636
+						cli_errmsg("cli_pdf: failed to write output file\n");
637
+						inflateEnd(&stream);
638
+						return CL_EIO;
639
+					}
640
+					nbytes += written;
636 641
 
637 642
 					if(ctx->limits &&
638 643
 					   ctx->limits->maxfilesize &&
639 644
 					   (nbytes > (off_t) ctx->limits->maxfilesize)) {
640
-						cli_dbgmsg("cli_pdf: flatedecode size exceeded (%lu)\n",
641
-							(unsigned long)nbytes);
645
+						cli_dbgmsg("cli_pdf: flatedecode size exceeded (%lu > %lu)\n",
646
+							   (unsigned long)nbytes, (unsigned long)ctx->limits->maxfilesize);
642 647
 						inflateEnd(&stream);
643 648
 						if(BLOCKMAX) {
644 649
 							*ctx->virname = "PDF.ExceededFileSize";
645 650
 							return CL_VIRUS;
646 651
 						}
647
-						return CL_EZIP;
652
+						return CL_CLEAN;
648 653
 					}
649 654
 					stream.next_out = output;
650 655
 					stream.avail_out = sizeof(output);
... ...
@@ -654,21 +631,26 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
654 654
 				break;
655 655
 			default:
656 656
 				if(stream.msg)
657
-					cli_dbgmsg("pdf: after writing %lu bytes, got error \"%s\" inflating PDF attachment\n",
657
+					cli_dbgmsg("cli_pdf: after writing %lu bytes, got error \"%s\" inflating PDF attachment\n",
658 658
 						(unsigned long)nbytes,
659 659
 						stream.msg);
660 660
 				else
661
-					cli_dbgmsg("pdf: after writing %lu bytes, got error %d inflating PDF attachment\n",
661
+					cli_dbgmsg("cli_pdf: after writing %lu bytes, got error %d inflating PDF attachment\n",
662 662
 						(unsigned long)nbytes, zstat);
663 663
 				inflateEnd(&stream);
664
-				return CL_EZIP;
664
+				return CL_CLEAN;
665 665
 		}
666 666
 		break;
667 667
 	}
668 668
 
669
-	if(stream.avail_out != sizeof(output))
670
-		if(cli_writen(fout, output, sizeof(output) - stream.avail_out) < 0)
669
+	if(stream.avail_out != sizeof(output)) {
670
+		if(cli_writen(fout, output, sizeof(output) - stream.avail_out) < 0) {
671
+			cli_errmsg("cli_pdf: failed to write output file\n");
672
+			inflateEnd(&stream);
671 673
 			return CL_EIO;
674
+		}
675
+	}
676
+			
672 677
 
673 678
 	/*
674 679
 	 * On BSD systems total_in and total_out are "long long", so these
... ...
@@ -688,13 +670,14 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
688 688
 			*ctx->virname = "Oversized.PDF";
689 689
 			return CL_VIRUS;
690 690
 		}
691
-		return CL_EZIP;
691
+		return CL_CLEAN;
692 692
 	}
693 693
 
694 694
 #ifdef	SAVE_TMP
695 695
 	unlink(tmpfilename);
696 696
 #endif
697
-	return inflateEnd(&stream) == Z_OK ? CL_SUCCESS : CL_EZIP;
697
+	inflateEnd(&stream);
698
+	return CL_CLEAN;
698 699
 }
699 700
 
700 701
 /*
... ...
@@ -711,7 +694,7 @@ ascii85decode(const char *buf, off_t len, unsigned char *output)
711 711
 	int ret = 0;
712 712
 
713 713
 	if(cli_pmemstr(buf, len, "~>", 2) == NULL)
714
-		cli_warnmsg("ascii85decode: no EOF marker found\n");
714
+		cli_dbgmsg("cli_pdf: ascii85decode: no EOF marker found\n");
715 715
 
716 716
 	ptr = buf;
717 717
 
... ...
@@ -736,7 +719,7 @@ ascii85decode(const char *buf, off_t len, unsigned char *output)
736 736
 			}
737 737
 		} else if(byte == 'z') {
738 738
 			if(quintet) {
739
-				cli_warnmsg("ascii85decode: unexpected 'z'\n");
739
+				cli_dbgmsg("ascii85decode: unexpected 'z'\n");
740 740
 				return -1;
741 741
 			}
742 742
 			*output++ = '\0';
... ...
@@ -750,7 +733,7 @@ ascii85decode(const char *buf, off_t len, unsigned char *output)
750 750
 				int i;
751 751
 
752 752
 				if(quintet == 1) {
753
-					cli_warnmsg("ascii85Decode: only 1 byte in last quintet\n");
753
+					cli_dbgmsg("ascii85Decode: only 1 byte in last quintet\n");
754 754
 					return -1;
755 755
 				}
756 756
 				for(i = quintet; i < 5; i++)
... ...
@@ -766,7 +749,7 @@ ascii85decode(const char *buf, off_t len, unsigned char *output)
766 766
 			len = 0;
767 767
 			break;
768 768
 		} else if(!isspace(byte)) {
769
-			cli_warnmsg("ascii85Decode: invalid character 0x%x, len %lu\n",
769
+			cli_dbgmsg("ascii85Decode: invalid character 0x%x, len %lu\n",
770 770
 				byte & 0xFF, (unsigned long)len);
771 771
 			return -1;
772 772
 		}
... ...
@@ -887,7 +870,7 @@ cli_pmemstr(const char *haystack, size_t hs, const char *needle, size_t ns)
887 887
 int
888 888
 cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
889 889
 {
890
-	cli_warnmsg("File not decoded - PDF decoding needs mmap() (for now)\n");
890
+	cli_dbgmsg("File not decoded - PDF decoding needs mmap() (for now)\n");
891 891
 	return CL_CLEAN;
892 892
 }
893 893
 #endif