Browse code

cache target file info in pattern matchers

git-svn: trunk@2511

Tomasz Kojm authored on 2006/11/20 09:03:16
Showing 7 changed files
... ...
@@ -1,3 +1,7 @@
1
+Mon Nov 20 00:58:57 CET 2006 (tk)
2
+---------------------------------
3
+  * libclamav: cache target file info in pattern matchers
4
+
1 5
 Sat Nov 18 22:44:37 GMT 2006 (njh)
2 6
 ----------------------------------
3 7
  * libclamav:	Don't implement the sleep function
... ...
@@ -513,6 +513,8 @@ int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
513 513
     section_hdr = (struct elf_section_hdr32 *) cli_calloc(shnum, shentsize);
514 514
     if(!section_hdr) {
515 515
 	cli_errmsg("ELF: Can't allocate memory for section headers\n");
516
+	free(elfinfo->section);
517
+	elfinfo->section = NULL;
516 518
 	return -1;
517 519
     }
518 520
 
... ...
@@ -521,6 +523,7 @@ int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
521 521
 	if(read(desc, &section_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32)) {
522 522
             free(section_hdr);
523 523
 	    free(elfinfo->section);
524
+	    elfinfo->section = NULL;
524 525
             return -1;
525 526
         }
526 527
 
... ...
@@ -412,6 +412,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char
412 412
         unsigned int i, position, curroff;
413 413
 	uint8_t offnum, found;
414 414
 	struct cli_matched_type *tnode;
415
+	struct cli_target_info info;
415 416
 
416 417
 
417 418
     if(!root->ac_root)
... ...
@@ -422,6 +423,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char
422 422
 	return CL_ENULLARG;
423 423
     }
424 424
 
425
+    memset(&info, 0, sizeof(info));
425 426
     current = root->ac_root;
426 427
 
427 428
     for(i = 0; i < length; i++)  {
... ...
@@ -441,7 +443,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char
441 441
 			else
442 442
 			    t = ftype;
443 443
 
444
-			if((fd == -1 && !t) || !cli_validatesig(t, pt->offset, curroff, fd, pt->virname)) {
444
+			if((fd == -1 && !t) || !cli_validatesig(t, pt->offset, curroff, &info, fd, pt->virname)) {
445 445
 			    pt = pt->next;
446 446
 			    continue;
447 447
 			}
... ...
@@ -497,6 +499,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char
497 497
 						if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < SFX_MAX_TESTS) && ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) {
498 498
 						    if(!(tnode = cli_calloc(1, sizeof(struct cli_matched_type)))) {
499 499
 							cli_errmsg("cli_ac_scanbuff(): Can't allocate memory for new type node\n");
500
+							if(info.exeinfo.section)
501
+							    free(info.exeinfo.section);
500 502
 							return CL_EMEM;
501 503
 						    }
502 504
 
... ...
@@ -517,6 +521,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char
517 517
 					if(virname)
518 518
 					    *virname = pt->virname;
519 519
 
520
+					if(info.exeinfo.section)
521
+					    free(info.exeinfo.section);
520 522
 					return CL_VIRUS;
521 523
 				    }
522 524
 				}
... ...
@@ -532,6 +538,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char
532 532
 				    if(ftoffset && (!*ftoffset ||(*ftoffset)->cnt < SFX_MAX_TESTS) && ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) {
533 533
 					if(!(tnode = cli_calloc(1, sizeof(struct cli_matched_type)))) {
534 534
 					    cli_errmsg("cli_ac_scanbuff(): Can't allocate memory for new type node\n");
535
+					    if(info.exeinfo.section)
536
+						free(info.exeinfo.section);
535 537
 					    return CL_EMEM;
536 538
 					}
537 539
 					tnode->type = type;
... ...
@@ -551,6 +559,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char
551 551
 			    if(virname)
552 552
 				*virname = pt->virname;
553 553
 
554
+			    if(info.exeinfo.section)
555
+				free(info.exeinfo.section);
554 556
 			    return CL_VIRUS;
555 557
 			}
556 558
 		    }
... ...
@@ -563,6 +573,9 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char
563 563
 	}
564 564
     }
565 565
 
566
+    if(info.exeinfo.section)
567
+	free(info.exeinfo.section);
568
+
566 569
     return otfrec ? type : CL_CLEAN;
567 570
 }
568 571
 
... ...
@@ -136,6 +136,7 @@ int cli_bm_scanbuff(const unsigned char *buffer, unsigned int length, const char
136 136
 	struct cli_bm_patt *p;
137 137
 	const unsigned char *bp;
138 138
 	unsigned char prefix;
139
+	struct cli_target_info info;
139 140
 
140 141
 
141 142
     if(!root->bm_shift)
... ...
@@ -144,6 +145,8 @@ int cli_bm_scanbuff(const unsigned char *buffer, unsigned int length, const char
144 144
     if(length < BM_MIN_LENGTH)
145 145
 	return CL_CLEAN;
146 146
 
147
+    memset(&info, 0, sizeof(info));
148
+
147 149
     for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length - BM_BLOCK_SIZE + 1; ) {
148 150
 	idx = HASH(buffer[i], buffer[i + 1], buffer[i + 2]);
149 151
 
... ...
@@ -189,7 +192,7 @@ int cli_bm_scanbuff(const unsigned char *buffer, unsigned int length, const char
189 189
 		    if(p->target || p->offset) {
190 190
 			off = offset + i - BM_MIN_LENGTH + BM_BLOCK_SIZE;
191 191
 
192
-			if((fd == -1 && !ftype) || !cli_validatesig(ftype, p->offset, off, fd, p->virname)) {
192
+			if((fd == -1 && !ftype) || !cli_validatesig(ftype, p->offset, off, &info, fd, p->virname)) {
193 193
 			    p = p->next;
194 194
 			    continue;
195 195
 			}
... ...
@@ -198,6 +201,9 @@ int cli_bm_scanbuff(const unsigned char *buffer, unsigned int length, const char
198 198
 		    if(virname)
199 199
 			*virname = p->virname;
200 200
 
201
+		    if(info.exeinfo.section)
202
+			free(info.exeinfo.section);
203
+
201 204
 		    return CL_VIRUS;
202 205
 		}
203 206
 
... ...
@@ -210,5 +216,8 @@ int cli_bm_scanbuff(const unsigned char *buffer, unsigned int length, const char
210 210
 	i += shift;
211 211
     }
212 212
 
213
-    return 0;
213
+    if(info.exeinfo.section)
214
+	free(info.exeinfo.section);
215
+
216
+    return CL_CLEAN;
214 217
 }
... ...
@@ -98,38 +98,38 @@ int cli_scanbuff(const unsigned char *buffer, unsigned int length, const char **
98 98
 		int targettype = 0;
99 99
 
100 100
 	    if((hret = sn_sigscan_resultget_name(resulthandle, i, &matchname) < 0)) {
101
-		cli_errmsg("cli_scanbuff: sn_sigscan_resultget_name failed for result %d: %d\n", i, hret);
101
+		cli_errmsg("cli_scanbuff: sn_sigscan_resultget_name failed for result %u: %d\n", i, hret);
102 102
 		sn_sigscan_resultfree(resulthandle);
103 103
 		return CL_ENCIO;
104 104
 	    }
105 105
 	    if(!matchname) {
106
-		cli_errmsg("cli_scanbuff: HW Result[%d]: Signature without name\n", i);
106
+		cli_errmsg("cli_scanbuff: HW Result[%u]: Signature without name\n", i);
107 107
 		sn_sigscan_resultfree(resulthandle);
108 108
 		return CL_EMALFDB;
109 109
 	    }
110 110
 
111 111
 	    if((hret = sn_sigscan_resultget_targettype(resulthandle, i, &targettype) < 0)) {
112
-		cli_errmsg("cli_scanbuff: sn_sigscan_resultget_targettype failed for result %d, signature %s: %d\n", i, matchname, hret);
112
+		cli_errmsg("cli_scanbuff: sn_sigscan_resultget_targettype failed for result %u, signature %s: %d\n", i, matchname, hret);
113 113
 		sn_sigscan_resultfree(resulthandle);
114 114
 		return CL_ENCIO;
115 115
 	    }
116 116
 	    if(targettype && targettab[targettype] != (int) ftype) {
117
-		cli_dbgmsg("cli_scanbuff: HW Result[%d]: %s: Target type: %d, expected: %d\n", i, matchname, targettab[targettype], ftype);
117
+		cli_dbgmsg("cli_scanbuff: HW Result[%u]: %s: Target type: %u, expected: %u\n", i, matchname, targettab[targettype], ftype);
118 118
 		continue;
119 119
 	    }
120 120
 
121 121
 	    if((hret = sn_sigscan_resultget_offsetstring(resulthandle, i, &offsetstring) < 0)) {
122
-		cli_errmsg("cli_scanbuff: sn_sigscan_resultget_offsetstring failed for result %d, signature %s: %d\n", i, matchname, hret);
122
+		cli_errmsg("cli_scanbuff: sn_sigscan_resultget_offsetstring failed for result %u, signature %s: %d\n", i, matchname, hret);
123 123
 		sn_sigscan_resultfree(resulthandle);
124 124
 		return CL_ENCIO;
125 125
 	    }
126 126
 	    if(offsetstring) {
127
-		cli_dbgmsg("cli_scanbuff: HW Result[%d]: %s: Offset based signature not supported in buffer mode\n", i, matchname);
127
+		cli_dbgmsg("cli_scanbuff: HW Result[%u]: %s: Offset based signature not supported in buffer mode\n", i, matchname);
128 128
 		continue;
129 129
 	    }
130 130
 
131 131
 	    if((hret = sn_sigscan_resultget_extradata(resulthandle, i, &optionalsigdata) < 0)) {
132
-		cli_errmsg("cli_scanbuff: sn_sigscan_resultget_extradata failed for result %d, signature %s: %d\n", i, matchname, hret);
132
+		cli_errmsg("cli_scanbuff: sn_sigscan_resultget_extradata failed for result %u, signature %s: %d\n", i, matchname, hret);
133 133
 		sn_sigscan_resultfree(resulthandle);
134 134
 		return CL_ENCIO;
135 135
 	    }
... ...
@@ -137,13 +137,13 @@ int cli_scanbuff(const unsigned char *buffer, unsigned int length, const char **
137 137
 		if((pt = cli_strtok(optionalsigdata, 1, ":"))) { /* max version */
138 138
 		    if(!isdigit(*pt)) {
139 139
 			free(pt);
140
-			cli_errmsg("cli_scanbuff: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
140
+			cli_errmsg("cli_scanbuff: HW Result[%u]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
141 141
 			sn_sigscan_resultfree(resulthandle);
142 142
 			return CL_EMALFDB;
143 143
 		    }
144 144
 
145 145
 		    if(atoi(pt) < cl_retflevel()) {
146
-			cli_dbgmsg("cli_scanbuff: HW Result[%d]: %s: Signature max flevel: %d, current: %d\n", i, matchname, atoi(pt), cl_retflevel());
146
+			cli_dbgmsg("cli_scanbuff: HW Result[%u]: %s: Signature max flevel: %u, current: %u\n", i, matchname, atoi(pt), cl_retflevel());
147 147
 			free(pt);
148 148
 			continue;
149 149
 		    }
... ...
@@ -152,13 +152,13 @@ int cli_scanbuff(const unsigned char *buffer, unsigned int length, const char **
152 152
 		    if((pt = cli_strtok(optionalsigdata, 0, ":"))) { /* min version */
153 153
 			if(!isdigit(*pt)) {
154 154
 			    free(pt);
155
-			    cli_errmsg("cli_scanbuff: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
155
+			    cli_errmsg("cli_scanbuff: HW Result[%u]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
156 156
 			    sn_sigscan_resultfree(resulthandle);
157 157
 			    return CL_EMALFDB;
158 158
 			}
159 159
 
160 160
 			if(atoi(pt) > cl_retflevel()) {
161
-			    cli_dbgmsg("cli_scanbuff: HW Result[%d]: %s: Signature required flevel: %d, current: %d\n", i, matchname, atoi(pt), cl_retflevel());
161
+			    cli_dbgmsg("cli_scanbuff: HW Result[%u]: %s: Signature required flevel: %u, current: %u\n", i, matchname, atoi(pt), cl_retflevel());
162 162
 			    free(pt);
163 163
 			    continue;
164 164
 			}
... ...
@@ -167,13 +167,13 @@ int cli_scanbuff(const unsigned char *buffer, unsigned int length, const char **
167 167
 
168 168
 		} else {
169 169
 		    if(!isdigit(*optionalsigdata)) {
170
-			cli_errmsg("cli_scanbuff: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
170
+			cli_errmsg("cli_scanbuff: HW Result[%u]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
171 171
 			sn_sigscan_resultfree(resulthandle);
172 172
 			return CL_EMALFDB;
173 173
 		    }
174 174
 
175 175
 		    if(atoi(optionalsigdata) > cl_retflevel()) {
176
-			cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Signature required flevel: %d, current: %d\n", i, matchname, atoi(optionalsigdata), cl_retflevel());
176
+			cli_dbgmsg("cli_scandesc: HW Result[%u]: %s: Signature required flevel: %u, current: %u\n", i, matchname, atoi(optionalsigdata), cl_retflevel());
177 177
 			continue;
178 178
 		    }
179 179
 		}
... ...
@@ -250,89 +250,101 @@ static struct cli_md5_node *cli_vermd5(const unsigned char *md5, const struct cl
250 250
     return NULL;
251 251
 }
252 252
 
253
-static long int cli_caloff(const char *offstr, int fd, unsigned short ftype)
253
+static off_t cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned short ftype, int *ret)
254 254
 {
255
-	struct cli_exe_info exeinfo;
256 255
 	int (*einfo)(int, struct cli_exe_info *) = NULL;
257
-	long int offset = -1;
258
-	int n;
256
+	unsigned int n;
257
+	off_t pos, offset;
259 258
 
260 259
 
261
-    if(ftype == CL_TYPE_MSEXE)
262
-	einfo = cli_peheader;
263
-    else if(ftype == CL_TYPE_ELF)
264
-	einfo = cli_elfheader;
260
+    *ret = 0;
261
+
262
+    if(!strncmp(offstr, "EP", 2) || offstr[0] == 'S') {
263
+
264
+	if(info->status == -1) {
265
+	    *ret = -1;
266
+	    return 0;
267
+
268
+	} else if(!info->status) {
269
+
270
+	    if(ftype == CL_TYPE_MSEXE)
271
+		einfo = cli_peheader;
272
+	    else if(ftype == CL_TYPE_ELF)
273
+		einfo = cli_elfheader;
274
+
275
+	    if(einfo) {
276
+		if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
277
+		    cli_dbgmsg("Invalid descriptor\n");
278
+		    info->status = *ret = -1;
279
+		    return 0;
280
+		}
281
+
282
+		lseek(fd, 0, SEEK_SET);
283
+		if(einfo(fd, &info->exeinfo)) {
284
+		    lseek(fd, pos, SEEK_SET);
285
+		    info->status = *ret = -1;
286
+		    return 0;
287
+		}
288
+		lseek(fd, pos, SEEK_SET);
289
+		info->status = 1;
290
+	    }
291
+	}
292
+    }
265 293
 
266 294
     if(isdigit(offstr[0])) {
267 295
 	return atoi(offstr);
268 296
 
269
-    } else if(einfo && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
270
-	if((n = lseek(fd, 0, SEEK_CUR)) == -1) {
271
-	    cli_dbgmsg("Invalid descriptor\n");
272
-	    return -1;
273
-	}
274
-	lseek(fd, 0, SEEK_SET);
275
-	if(einfo(fd, &exeinfo)) {
276
-	    lseek(fd, n, SEEK_SET);
277
-	    return -1;
278
-	}
279
-	free(exeinfo.section);
280
-	lseek(fd, n, SEEK_SET);
297
+    } else if(info->status == 1 && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
281 298
 
282 299
 	if(offstr[2] == '+')
283
-	    return exeinfo.ep + atoi(offstr + 3);
300
+	    return info->exeinfo.ep + atoi(offstr + 3);
284 301
 	else
285
-	    return exeinfo.ep - atoi(offstr + 3);
302
+	    return info->exeinfo.ep - atoi(offstr + 3);
286 303
 
287
-    } else if(einfo && offstr[0] == 'S') {
288
-	if((n = lseek(fd, 0, SEEK_CUR)) == -1) {
289
-	    cli_dbgmsg("Invalid descriptor\n");
290
-	    return -1;
291
-	}
292
-	lseek(fd, 0, SEEK_SET);
293
-	if(einfo(fd, &exeinfo)) {
294
-	    lseek(fd, n, SEEK_SET);
295
-	    return -1;
296
-	}
297
-	lseek(fd, n, SEEK_SET);
304
+    } else if(info->status == 1 && offstr[0] == 'S') {
298 305
 
299 306
 	if(!strncmp(offstr, "SL", 2)) {
300 307
 
301
-	    if(sscanf(offstr, "SL+%ld", &offset) != 1) {
302
-		free(exeinfo.section);
303
-		return -1;
308
+	    if(sscanf(offstr, "SL+%lu", &offset) != 1) {
309
+		*ret = -1;
310
+		return 0;
304 311
 	    }
305 312
 
306
-	    offset += exeinfo.section[exeinfo.nsections - 1].raw;
313
+	    offset += info->exeinfo.section[info->exeinfo.nsections - 1].raw;
307 314
 
308 315
 	} else {
309 316
 
310
-	    if(sscanf(offstr, "S%d+%ld", &n, &offset) != 2) {
311
-		free(exeinfo.section);
312
-		return -1;
317
+	    if(sscanf(offstr, "S%u+%lu", &n, &offset) != 2) {
318
+		*ret = -1;
319
+		return 0;
313 320
 	    }
314 321
 
315
-	    if(n >= exeinfo.nsections) {
316
-		free(exeinfo.section);
317
-		return -1;
322
+	    if(n >= info->exeinfo.nsections) {
323
+		*ret = -1;
324
+		return 0;
318 325
 	    }
319 326
 
320
-	    offset += exeinfo.section[n].raw;
327
+	    offset += info->exeinfo.section[n].raw;
321 328
 	}
322 329
 
323
-	free(exeinfo.section);
324 330
 	return offset;
325 331
 
326 332
     } else if(!strncmp(offstr, "EOF-", 4)) {
327 333
 	    struct stat sb;
328 334
 
329
-	if(fstat(fd, &sb) == -1)
330
-	    return -1;
335
+	if(!info->fsize) {
336
+	    if(fstat(fd, &sb) == -1) {
337
+		info->status = *ret = -1;
338
+		return 0;
339
+	    }
340
+	    info->fsize = sb.st_size;
341
+	}
331 342
 
332
-	return sb.st_size - atoi(offstr + 4);
343
+	return info->fsize - atoi(offstr + 4);
333 344
     }
334 345
 
335
-    return -1;
346
+    *ret = -1;
347
+    return 0;
336 348
 }
337 349
 
338 350
 static int cli_checkfp(int fd, const struct cl_engine *engine)
... ...
@@ -369,19 +381,22 @@ static int cli_checkfp(int fd, const struct cl_engine *engine)
369 369
     return 0;
370 370
 }
371 371
 
372
-int cli_validatesig(unsigned short ftype, const char *offstr, unsigned long int fileoff, int desc, const char *virname)
372
+int cli_validatesig(unsigned short ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname)
373 373
 {
374
+	off_t offset;
375
+	int ret;
376
+
374 377
 
375 378
     if(offstr && desc != -1) {
376
-	    long int off = cli_caloff(offstr, desc, ftype);
379
+	offset = cli_caloff(offstr, info, desc, ftype, &ret);
377 380
 
378
-	if(off == -1) {
379
-	    cli_dbgmsg("Bad offset in signature (%s)\n", virname);
381
+	if(ret == -1) {
382
+	    cli_dbgmsg("cli_validatesig: Can't calculate offset for signature %s\n", virname);
380 383
 	    return 0;
381 384
 	}
382 385
 
383
-	if(fileoff != (unsigned long int) off) {
384
-	    cli_dbgmsg("Virus offset: %ld, expected: %ld (%s)\n", fileoff, off, virname);
386
+	if(fileoff != offset) {
387
+	    cli_dbgmsg("Signature offset: %lu, expected: %lu (%s)\n", fileoff, offset, virname);
385 388
 	    return 0;
386 389
 	}
387 390
     }
... ...
@@ -408,6 +423,7 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f
408 408
 	int count, hret;
409 409
 	off_t origoff;
410 410
 	char *pt;
411
+	struct cli_target_info info;
411 412
 #endif
412 413
 
413 414
 
... ...
@@ -461,74 +477,93 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f
461 461
 
462 462
 	count = sn_sigscan_resultcount(resulthandle);
463 463
 
464
+	memset(&info, 0, sizeof(info));
465
+
464 466
 	for(i = 0; i < count; i++) {
465 467
 		const char *matchname = NULL, *offsetstring = NULL, *optionalsigdata = NULL;
466 468
 		unsigned long long startoffset = 0;
469
+		off_t offset;
467 470
 		int targettype = 0;
468 471
 
469 472
 	    if((hret = sn_sigscan_resultget_name(resulthandle, i, &matchname) < 0)) {
470
-		cli_errmsg("cli_scandesc: sn_sigscan_resultget_name failed for result %d: %d\n", i, hret);
473
+		cli_errmsg("cli_scandesc: sn_sigscan_resultget_name failed for result %u: %d\n", i, hret);
471 474
 		sn_sigscan_resultfree(resulthandle);
475
+		if(info.exeinfo.section)
476
+		    free(info.exeinfo.section);
472 477
 		return CL_ENCIO;
473 478
 	    }
474 479
 
475 480
 	    if(!matchname) {
476
-		cli_errmsg("cli_scandesc: HW Result[%d]: Signature without name\n", i);
481
+		cli_errmsg("cli_scandesc: HW Result[%u]: Signature without name\n", i);
477 482
 		sn_sigscan_resultfree(resulthandle);
483
+		if(info.exeinfo.section)
484
+		    free(info.exeinfo.section);
478 485
 		return CL_EMALFDB;
479 486
 	    }
480 487
 
481 488
 	    if((hret = sn_sigscan_resultget_targettype(resulthandle, i, &targettype) < 0)) {
482
-		cli_errmsg("cli_scandesc: sn_sigscan_resultget_targettype failed for result %d, signature %s: %d\n", i, matchname, hret);
489
+		cli_errmsg("cli_scandesc: sn_sigscan_resultget_targettype failed for result %u, signature %s: %d\n", i, matchname, hret);
483 490
 		sn_sigscan_resultfree(resulthandle);
491
+		if(info.exeinfo.section)
492
+		    free(info.exeinfo.section);
484 493
 		return CL_ENCIO;
485 494
 	    }
486 495
 	    if(targettype && targettab[targettype] != (int) ftype) {
487
-		cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Target type: %d, expected: %d\n", i, matchname, targettab[targettype], ftype);
496
+		cli_dbgmsg("cli_scandesc: HW Result[%u]: %s: Target type: %u, expected: %u\n", i, matchname, targettab[targettype], ftype);
488 497
 		continue;
489 498
 	    }
490 499
 
491 500
 	    if((hret = sn_sigscan_resultget_offsetstring(resulthandle, i, &offsetstring) < 0)) {
492
-		cli_errmsg("cli_scandesc: sn_sigscan_resultget_offsetstring failed for result %d, signature %s: %d\n", i, matchname, hret);
501
+		cli_errmsg("cli_scandesc: sn_sigscan_resultget_offsetstring failed for result %u, signature %s: %d\n", i, matchname, hret);
493 502
 		sn_sigscan_resultfree(resulthandle);
503
+		if(info.exeinfo.section)
504
+		    free(info.exeinfo.section);
494 505
 		return CL_ENCIO;
495 506
 	    }
496 507
 	    if((hret = sn_sigscan_resultget_startoffset(resulthandle, i, &startoffset) < 0)) {
497
-		cli_errmsg("cli_scandesc: sn_sigscan_resultget_startoffset failed for result %d, signature %s: %d\n", i, matchname, hret);
508
+		cli_errmsg("cli_scandesc: sn_sigscan_resultget_startoffset failed for result %u, signature %s: %d\n", i, matchname, hret);
498 509
 		sn_sigscan_resultfree(resulthandle);
510
+		if(info.exeinfo.section)
511
+		    free(info.exeinfo.section);
499 512
 		return CL_ENCIO;
500 513
 	    }
501 514
 	    if(offsetstring && strcmp(offsetstring, "*")) {
502
-		    long int off = cli_caloff(offsetstring, desc, ftype);
515
+		    off_t off = cli_caloff(offsetstring, &info, desc, ftype, &hret);
503 516
 
504
-		if(off == -1) {
505
-		    cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Bad offset in signature\n", i, matchname);
517
+		if(hret == -1) {
518
+		    cli_dbgmsg("cli_scandesc: HW Result[%u]: %s: Bad offset in signature\n", i, matchname);
506 519
 		    sn_sigscan_resultfree(resulthandle);
520
+		    if(info.exeinfo.section)
521
+			free(info.exeinfo.section);
507 522
 		    return CL_EMALFDB;
508 523
 		}
509 524
 
510 525
 		if(startoffset != (unsigned long long) off) {
511
-		    cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Virus offset: %Lu, expected: %ld\n", i, matchname, startoffset, off);
526
+		    cli_dbgmsg("cli_scandesc: HW Result[%u]: %s: Virus offset: %lu, expected: %lu\n", i, matchname, startoffset, off);
512 527
 		    continue;
513 528
 		}
514 529
 	    }
515 530
 
516 531
 	    if((hret = sn_sigscan_resultget_extradata(resulthandle, i, &optionalsigdata) < 0)) {
517
-		cli_errmsg("cli_scandesc: sn_sigscan_resultget_extradata failed for result %d, signature %s: %d\n", i, matchname, hret);
532
+		cli_errmsg("cli_scandesc: sn_sigscan_resultget_extradata failed for result %u, signature %s: %u\n", i, matchname, hret);
518 533
 		sn_sigscan_resultfree(resulthandle);
534
+		if(info.exeinfo.section)
535
+		    free(info.exeinfo.section);
519 536
 		return CL_ENCIO;
520 537
 	    }
521 538
 	    if(optionalsigdata && strlen(optionalsigdata)) {
522 539
 		if((pt = cli_strtok(optionalsigdata, 1, ":"))) { /* max version */
523 540
 		    if(!isdigit(*pt)) {
524 541
 			free(pt);
525
-			cli_errmsg("cli_scandesc: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
542
+			cli_errmsg("cli_scandesc: HW Result[%u]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
526 543
 			sn_sigscan_resultfree(resulthandle);
544
+			if(info.exeinfo.section)
545
+			    free(info.exeinfo.section);
527 546
 			return CL_EMALFDB;
528 547
 		    }
529 548
 
530 549
 		    if(atoi(pt) < cl_retflevel()) {
531
-			cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Signature max flevel: %d, current: %d\n", i, matchname, atoi(pt), cl_retflevel());
550
+			cli_dbgmsg("cli_scandesc: HW Result[%u]: %s: Signature max flevel: %u, current: %u\n", i, matchname, atoi(pt), cl_retflevel());
532 551
 			free(pt);
533 552
 			continue;
534 553
 		    }
... ...
@@ -537,13 +572,15 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f
537 537
 		    if((pt = cli_strtok(optionalsigdata, 0, ":"))) { /* min version */
538 538
 			if(!isdigit(*pt)) {
539 539
 			    free(pt);
540
-			    cli_errmsg("cli_scandesc: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
540
+			    cli_errmsg("cli_scandesc: HW Result[%u]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
541 541
 			    sn_sigscan_resultfree(resulthandle);
542
+			    if(info.exeinfo.section)
543
+				free(info.exeinfo.section);
542 544
 			    return CL_EMALFDB;
543 545
 			}
544 546
 
545 547
 			if(atoi(pt) > cl_retflevel()) {
546
-			    cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Signature required flevel: %d, current: %d\n", i, matchname, atoi(pt), cl_retflevel());
548
+			    cli_dbgmsg("cli_scandesc: HW Result[%u]: %s: Signature required flevel: %u, current: %u\n", i, matchname, atoi(pt), cl_retflevel());
547 549
 			    free(pt);
548 550
 			    continue;
549 551
 			}
... ...
@@ -552,13 +589,15 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f
552 552
 
553 553
 		} else {
554 554
 		    if(!isdigit(*optionalsigdata)) {
555
-			cli_errmsg("cli_scandesc: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
555
+			cli_errmsg("cli_scandesc: HW Result[%u]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata);
556 556
 			sn_sigscan_resultfree(resulthandle);
557
+			if(info.exeinfo.section)
558
+			    free(info.exeinfo.section);
557 559
 			return CL_EMALFDB;
558 560
 		    }
559 561
 
560 562
 		    if(atoi(optionalsigdata) > cl_retflevel()) {
561
-			cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Signature required flevel: %d, current: %d\n", i, matchname, atoi(optionalsigdata), cl_retflevel());
563
+			cli_dbgmsg("cli_scandesc: HW Result[%u]: %s: Signature required flevel: %u, current: %u\n", i, matchname, atoi(optionalsigdata), cl_retflevel());
562 564
 			continue;
563 565
 		    }
564 566
 		}
... ...
@@ -569,6 +608,9 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f
569 569
 	    break;
570 570
 	}
571 571
 
572
+	if(info.exeinfo.section)
573
+	    free(info.exeinfo.section);
574
+
572 575
 	if((hret = sn_sigscan_resultfree(resulthandle)) < 0) {
573 576
 	    cli_errmsg("cli_scandesc: can't free results: %d\n", ret);
574 577
 	    return CL_ENCIO;
... ...
@@ -630,7 +672,7 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f
630 630
     /* prepare the buffer */
631 631
     buffersize = maxpatlen + SCANBUFF;
632 632
     if(!(buffer = (unsigned char *) cli_calloc(buffersize, sizeof(unsigned char)))) {
633
-	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d)\n", buffersize);
633
+	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%u)\n", buffersize);
634 634
 	return CL_EMEM;
635 635
     }
636 636
 
... ...
@@ -20,16 +20,26 @@
20 20
 #ifndef __MATCHER_H
21 21
 #define __MATCHER_H
22 22
 
23
+#include <sys/types.h>
24
+
23 25
 #include "clamav.h"
24 26
 #include "filetypes.h"
25 27
 #include "others.h"
28
+#include "execs.h"
29
+#include "cltypes.h"
26 30
 
27 31
 #define CL_TARGET_TABLE_SIZE 7
28 32
 
33
+struct cli_target_info {
34
+    off_t fsize;
35
+    struct cli_exe_info exeinfo;
36
+    int8_t status; /* 0 == not initialised, 1 == initialised OK, -1 == error */
37
+};
38
+
29 39
 int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset);
30 40
 
31 41
 int cli_scanbuff(const unsigned char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine, unsigned short ftype);
32 42
 
33
-int cli_validatesig(unsigned short ftype, const char *offstr, unsigned long int fileoff, int desc, const char *virname);
43
+int cli_validatesig(unsigned short ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname);
34 44
 
35 45
 #endif
... ...
@@ -2436,6 +2436,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
2436 2436
     if(fstat(desc, &sb) == -1) {
2437 2437
 	cli_dbgmsg("fstat failed\n");
2438 2438
 	free(peinfo->section);
2439
+	peinfo->section = NULL;
2439 2440
 	return -1;
2440 2441
     }
2441 2442
 
... ...
@@ -2444,6 +2445,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
2444 2444
     if(!section_hdr) {
2445 2445
 	cli_dbgmsg("Can't allocate memory for section headers\n");
2446 2446
 	free(peinfo->section);
2447
+	peinfo->section = NULL;
2447 2448
 	return -1;
2448 2449
     }
2449 2450
 
... ...
@@ -2454,6 +2456,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
2454 2454
 	    cli_dbgmsg("Possibly broken PE file\n");
2455 2455
 	    free(section_hdr);
2456 2456
 	    free(peinfo->section);
2457
+	    peinfo->section = NULL;
2457 2458
 	    return -1;
2458 2459
 	}
2459 2460
 
... ...
@@ -2483,6 +2486,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
2483 2483
 	cli_dbgmsg("Possibly broken PE file\n");
2484 2484
 	free(section_hdr);
2485 2485
 	free(peinfo->section);
2486
+	peinfo->section = NULL;
2486 2487
 	return -1;
2487 2488
     }
2488 2489