Browse code

Fix fd leak on empty objects

git-svn: trunk@2928

Nigel Horne authored on 2007/03/10 10:18:38
Showing 2 changed files
... ...
@@ -1,3 +1,8 @@
1
+Fri Mar  9 23:24:24 GMT 2007 (njh)
2
+----------------------------------
3
+  * libclamav/pdf.c:	Fix fd leak on empty objects
4
+			Scan in user memory
5
+
1 6
 Fri Mar  9 22:39:36 GMT 2007 (njh)
2 7
 ----------------------------------
3 8
   * libclamav/pdf.c:	When flatedecoder fails point out that the encoder
... ...
@@ -71,10 +71,9 @@ static	const	char	*cli_pmemstr(const char *haystack, size_t hs, const char *need
71 71
 int
72 72
 cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
73 73
 {
74
-	struct stat statb;
75 74
 	off_t size;	/* total number of bytes in the file */
76 75
 	long bytesleft, trailerlength;
77
-	char *buf;	/* start of memory mapped area */
76
+	char *buf, *alloced;	/* start of memory mapped area */
78 77
 	const char *p, *q, *trailerstart;
79 78
 	const char *xrefstart;	/* cross reference table */
80 79
 	/*size_t xreflength;*/
... ...
@@ -82,6 +81,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
82 82
 	struct table *md5table;
83 83
 	int printed_predictor_message;
84 84
 	int printed_embedded_font_message;
85
+	struct stat statb;
85 86
 
86 87
 	cli_dbgmsg("in cli_pdf(%s)\n", dir);
87 88
 
... ...
@@ -100,20 +100,37 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
100 100
 	if(buf == MAP_FAILED)
101 101
 		return CL_EMEM;
102 102
 
103
+	alloced = cli_malloc(size);
104
+	if(alloced) {
105
+		/*
106
+		 * FIXME: now I have this, there's no need for the lack of
107
+		 *	support on systems without mmap, e.g. cygwin
108
+		 */
109
+		memcpy(alloced, buf, size);
110
+		munmap(buf, size);
111
+		p = alloced;
112
+	}
113
+
103 114
 	cli_dbgmsg("cli_pdf: scanning %lu bytes\n", (unsigned long)size);
104 115
 
105 116
 	/* Lines are terminated by \r, \n or both */
106 117
 
107 118
 	/* File Header */
108 119
 	if(memcmp(p, "%PDF-1.", 7) != 0) {
109
-		munmap(buf, size);
120
+		if(alloced)
121
+			free(alloced);
122
+		else
123
+			munmap(buf, size);
110 124
 		return CL_EFORMAT;
111 125
 	}
112 126
 
113 127
 #if	0
114 128
 	q = pdf_nextlinestart(&p[6], size - 6);
115 129
 	if(q == NULL) {
116
-		munmap(buf, size);
130
+		if(alloced)
131
+			free(alloced);
132
+		else
133
+			munmap(buf, size);
117 134
 		return CL_EFORMAT;
118 135
 	}
119 136
 	bytesleft = size - (long)(q - p);
... ...
@@ -129,7 +146,10 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
129 129
 			break;
130 130
 
131 131
 	if(q == p) {
132
-		munmap(buf, size);
132
+		if(alloced)
133
+			free(alloced);
134
+		else
135
+			munmap(buf, size);
133 136
 		return CL_EFORMAT;
134 137
 	}
135 138
 
... ...
@@ -145,7 +165,10 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
145 145
 		/*
146 146
 		 * This tends to mean that the file is, in effect, read-only
147 147
 		 */
148
-		munmap(buf, size);
148
+		if(alloced)
149
+			free(alloced);
150
+		else
151
+			munmap(buf, size);
149 152
 		cli_warnmsg("Encrypted PDF files not yet supported\n");
150 153
 		return CL_EFORMAT;
151 154
 	}
... ...
@@ -168,7 +191,10 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
168 168
 				break;
169 169
 
170 170
 	if(xrefstart == p) {
171
-		munmap(buf, size);
171
+		if(alloced)
172
+			free(alloced);
173
+		else
174
+			munmap(buf, size);
172 175
 		return CL_EFORMAT;
173 176
 	}
174 177
 
... ...
@@ -185,8 +211,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
185 185
 	 * The body section consists of a sequence of indirect objects
186 186
 	 */
187 187
 	while((p < xrefstart) &&
188
-	      ((q = pdf_nextobject(p, bytesleft)) != NULL) &&
189
-	      (rc == CL_CLEAN)) {
188
+	      ((q = pdf_nextobject(p, bytesleft)) != NULL)) {
190 189
 		int is_ascii85decode, is_flatedecode, fout, len, has_cr;
191 190
 		/*int object_number, generation_number;*/
192 191
 		const char *objstart, *objend, *streamstart, *streamend;
... ...
@@ -274,8 +299,8 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
274 274
 						snprintf(b, sizeof(b),
275 275
 							"%d 0 obj", length);
276 276
 						length = strlen(b);
277
-						r = cli_pmemstr(buf, size, b,
278
-							length);
277
+						r = cli_pmemstr(alloced ? alloced : buf,
278
+							size, b, length);
279 279
 						if(r) {
280 280
 							r += length - 1;
281 281
 							r = pdf_nextobject(r, bytesleft - (r - q));
... ...
@@ -393,6 +418,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
393 393
 			streamend++;
394 394
 
395 395
 		if(streamend <= streamstart) {
396
+			close(fout);
396 397
 			cli_dbgmsg("Empty stream\n");
397 398
 			continue;
398 399
 		}
... ...
@@ -473,7 +499,10 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
473 473
 		cli_dbgmsg("cli_pdf: extracted to %s\n", fullname);
474 474
 	}
475 475
 
476
-	munmap(buf, size);
476
+	if(alloced)
477
+		free(alloced);
478
+	else
479
+		munmap(buf, size);
477 480
 
478 481
 	tableDestroy(md5table);
479 482
 
... ...
@@ -498,7 +527,7 @@ try_flatedecode(unsigned char *buf, off_t real_len, off_t calculated_len, int fo
498 498
 		return Z_OK;
499 499
 
500 500
 	/* i.e. the PDF file is broken :-( */
501
-	cli_warnmsg("cli_pdf: Bad uncompressed block length in flate stream\n");
501
+	cli_warnmsg("cli_pdf: Bad compressed block length in flate stream\n");
502 502
 
503 503
 	return ret;
504 504
 }