Browse code

Initial support for loading .cbc files from DB.

Török Edvin authored on 2009/09/22 01:24:16
Showing 15 changed files
... ...
@@ -400,6 +400,9 @@ int main(int argc, char **argv)
400 400
     else
401 401
 	logg("#Not loading phishing signatures.\n");
402 402
 
403
+    if(optget(opts,"Bytecode")->enabled)
404
+	dboptions |= CL_DB_BYTECODE;
405
+
403 406
     if(optget(opts,"PhishingScanURLs")->enabled)
404 407
 	dboptions |= CL_DB_PHISHING_URLS;
405 408
     else
... ...
@@ -352,6 +352,9 @@ int scanmanager(const struct optstruct *opts)
352 352
     if(optget(opts,"phishing-scan-urls")->enabled)
353 353
 	dboptions |= CL_DB_PHISHING_URLS;
354 354
 
355
+    if(optget(opts,"bytecode")->enabled)
356
+	dboptions |= CL_DB_BYTECODE;
357
+
355 358
     if((ret = cl_init(CL_INIT_DEFAULT))) {
356 359
 	logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
357 360
 	return 50;
... ...
@@ -420,7 +420,7 @@ static int parseLSig(struct cli_bc *bc, unsigned char *buffer)
420 420
 	return CL_EMALFDB;
421 421
     }
422 422
     bc->lsig = NULL;
423
-    bc->lsig = cli_strdup(buffer[1]);
423
+    bc->lsig = cli_strdup(buffer + 1);
424 424
     return CL_SUCCESS;
425 425
 }
426 426
 
... ...
@@ -890,26 +890,26 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
890 890
 	    cli_errmsg("Invalid type or operand\n");
891 891
 	    return CL_EMALFDB;
892 892
 	}
893
-	if (inst.opcode >= OP_INVALID) {
893
+	if (inst.opcode >= OP_BC_INVALID) {
894 894
 	    cli_errmsg("Invalid opcode: %u\n", inst.opcode);
895 895
 	    return CL_EMALFDB;
896 896
 	}
897 897
 
898 898
 	switch (inst.opcode) {
899
-	    case OP_JMP:
899
+	    case OP_BC_JMP:
900 900
 		inst.u.jump = readBBID(bcfunc, buffer, &offset, len, &ok);
901 901
 		break;
902
-	    case OP_RET:
902
+	    case OP_BC_RET:
903 903
 		inst.type = readNumber(buffer, &offset, len, &ok);
904 904
 		inst.u.unaryop = readOperand(bcfunc, buffer, &offset, len, &ok);
905 905
 		break;
906
-	    case OP_BRANCH:
906
+	    case OP_BC_BRANCH:
907 907
 		inst.u.branch.condition = readOperand(bcfunc, buffer, &offset, len, &ok);
908 908
 		inst.u.branch.br_true = readBBID(bcfunc, buffer, &offset, len, &ok);
909 909
 		inst.u.branch.br_false = readBBID(bcfunc, buffer, &offset, len, &ok);
910 910
 		break;
911
-	    case OP_CALL_API:/* fall-through */
912
-	    case OP_CALL_DIRECT:
911
+	    case OP_BC_CALL_API:/* fall-through */
912
+	    case OP_BC_CALL_DIRECT:
913 913
 		numOp = readFixedNumber(buffer, &offset, len, &ok, 1);
914 914
 		if (ok) {
915 915
 		    inst.u.ops.numOps = numOp;
... ...
@@ -919,7 +919,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
919 919
 			cli_errmsg("Out of memory allocating operands\n");
920 920
 			return CL_EMALFDB;
921 921
 		    }
922
-		    if (inst.opcode == OP_CALL_DIRECT)
922
+		    if (inst.opcode == OP_BC_CALL_DIRECT)
923 923
 			inst.u.ops.funcid = readFuncID(bc, buffer, &offset, len, &ok);
924 924
 		    else
925 925
 			inst.u.ops.funcid = readAPIFuncID(bc, buffer, &offset, len, &ok);
... ...
@@ -928,9 +928,9 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
928 928
 		    }
929 929
 		}
930 930
 		break;
931
-	    case OP_ZEXT:
932
-	    case OP_SEXT:
933
-	    case OP_TRUNC:
931
+	    case OP_BC_ZEXT:
932
+	    case OP_BC_SEXT:
933
+	    case OP_BC_TRUNC:
934 934
 		inst.u.cast.source = readOperand(bcfunc, buffer, &offset, len, &ok);
935 935
 		inst.u.cast.mask = bcfunc->types[inst.u.cast.source];
936 936
 		if (inst.u.cast.mask == 1)
... ...
@@ -944,21 +944,21 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
944 944
 		else if (inst.u.cast.mask <= 64)
945 945
 		    inst.u.cast.size = 4;
946 946
 		/* calculate mask */
947
-		if (inst.opcode != OP_SEXT)
947
+		if (inst.opcode != OP_BC_SEXT)
948 948
 		    inst.u.cast.mask = inst.u.cast.mask != 64 ?
949 949
 			(1ull<<inst.u.cast.mask)-1 :
950 950
 			~0ull;
951 951
 		break;
952
-	    case OP_ICMP_EQ:
953
-	    case OP_ICMP_NE:
954
-	    case OP_ICMP_UGT:
955
-	    case OP_ICMP_UGE:
956
-	    case OP_ICMP_ULT:
957
-	    case OP_ICMP_ULE:
958
-	    case OP_ICMP_SGT:
959
-	    case OP_ICMP_SGE:
960
-	    case OP_ICMP_SLE:
961
-	    case OP_ICMP_SLT:
952
+	    case OP_BC_ICMP_EQ:
953
+	    case OP_BC_ICMP_NE:
954
+	    case OP_BC_ICMP_UGT:
955
+	    case OP_BC_ICMP_UGE:
956
+	    case OP_BC_ICMP_ULT:
957
+	    case OP_BC_ICMP_ULE:
958
+	    case OP_BC_ICMP_SGT:
959
+	    case OP_BC_ICMP_SGE:
960
+	    case OP_BC_ICMP_SLE:
961
+	    case OP_BC_ICMP_SLT:
962 962
 		/* instruction type must be correct before readOperand! */
963 963
 		inst.type = readNumber(buffer, &offset, len, &ok);
964 964
 		/* fall-through */
... ...
@@ -1160,8 +1160,8 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru
1160 1160
 	func.numBytes = ctx->bytes;
1161 1161
 	memset(ctx->values+ctx->bytes-8, 0, 8);
1162 1162
 
1163
-	inst.opcode = OP_CALL_DIRECT;
1164
-	inst.interp_op = OP_CALL_DIRECT*5;
1163
+	inst.opcode = OP_BC_CALL_DIRECT;
1164
+	inst.interp_op = OP_BC_CALL_DIRECT*5;
1165 1165
 	inst.dest = func.numArgs;
1166 1166
 	inst.type = 0;
1167 1167
 	inst.u.ops.numOps = ctx->numParams;
... ...
@@ -1194,7 +1194,7 @@ void cli_bytecode_destroy(struct cli_bc *bc)
1194 1194
 	    for(k=0;k<BB->numInsts;k++) {
1195 1195
 		struct cli_bc_inst *ii = &BB->insts[k];
1196 1196
 		if (operand_counts[ii->opcode] > 3 ||
1197
-		    ii->opcode == OP_CALL_DIRECT || ii->opcode == OP_CALL_API) {
1197
+		    ii->opcode == OP_BC_CALL_DIRECT || ii->opcode == OP_BC_CALL_API) {
1198 1198
 		    free(ii->u.ops.ops);
1199 1199
 		    free(ii->u.ops.opsizes);
1200 1200
 		}
... ...
@@ -1251,57 +1251,57 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc)
1251 1251
 	    struct cli_bc_inst *inst = &bcfunc->allinsts[j];
1252 1252
 	    inst->dest = map[inst->dest];
1253 1253
 	    switch (inst->opcode) {
1254
-		case OP_ADD:
1255
-		case OP_SUB:
1256
-		case OP_MUL:
1257
-		case OP_UDIV:
1258
-		case OP_SDIV:
1259
-		case OP_UREM:
1260
-		case OP_SREM:
1261
-		case OP_SHL:
1262
-		case OP_LSHR:
1263
-		case OP_ASHR:
1264
-		case OP_AND:
1265
-		case OP_OR:
1266
-		case OP_XOR:
1267
-		case OP_ICMP_EQ:
1268
-		case OP_ICMP_NE:
1269
-		case OP_ICMP_UGT:
1270
-		case OP_ICMP_UGE:
1271
-		case OP_ICMP_ULT:
1272
-		case OP_ICMP_ULE:
1273
-		case OP_ICMP_SGT:
1274
-		case OP_ICMP_SGE:
1275
-		case OP_ICMP_SLT:
1276
-		case OP_ICMP_SLE:
1277
-		case OP_COPY:
1278
-		case OP_STORE:
1254
+		case OP_BC_ADD:
1255
+		case OP_BC_SUB:
1256
+		case OP_BC_MUL:
1257
+		case OP_BC_UDIV:
1258
+		case OP_BC_SDIV:
1259
+		case OP_BC_UREM:
1260
+		case OP_BC_SREM:
1261
+		case OP_BC_SHL:
1262
+		case OP_BC_LSHR:
1263
+		case OP_BC_ASHR:
1264
+		case OP_BC_AND:
1265
+		case OP_BC_OR:
1266
+		case OP_BC_XOR:
1267
+		case OP_BC_ICMP_EQ:
1268
+		case OP_BC_ICMP_NE:
1269
+		case OP_BC_ICMP_UGT:
1270
+		case OP_BC_ICMP_UGE:
1271
+		case OP_BC_ICMP_ULT:
1272
+		case OP_BC_ICMP_ULE:
1273
+		case OP_BC_ICMP_SGT:
1274
+		case OP_BC_ICMP_SGE:
1275
+		case OP_BC_ICMP_SLT:
1276
+		case OP_BC_ICMP_SLE:
1277
+		case OP_BC_COPY:
1278
+		case OP_BC_STORE:
1279 1279
 		    MAP(inst->u.binop[0]);
1280 1280
 		    MAP(inst->u.binop[1]);
1281 1281
 		    break;
1282
-		case OP_SEXT:
1283
-		case OP_ZEXT:
1284
-		case OP_TRUNC:
1282
+		case OP_BC_SEXT:
1283
+		case OP_BC_ZEXT:
1284
+		case OP_BC_TRUNC:
1285 1285
 		    MAP(inst->u.cast.source);
1286 1286
 		    break;
1287
-		case OP_BRANCH:
1287
+		case OP_BC_BRANCH:
1288 1288
 		    MAP(inst->u.branch.condition);
1289 1289
 		    break;
1290
-		case OP_JMP:
1290
+		case OP_BC_JMP:
1291 1291
 		    break;
1292
-		case OP_RET:
1292
+		case OP_BC_RET:
1293 1293
 		    MAP(inst->u.unaryop);
1294 1294
 		    break;
1295
-		case OP_SELECT:
1295
+		case OP_BC_SELECT:
1296 1296
 		    MAP(inst->u.three[0]);
1297 1297
 		    MAP(inst->u.three[1]);
1298 1298
 		    MAP(inst->u.three[2]);
1299 1299
 		    break;
1300
-		case OP_CALL_API:/* fall-through */
1301
-		case OP_CALL_DIRECT:
1300
+		case OP_BC_CALL_API:/* fall-through */
1301
+		case OP_BC_CALL_DIRECT:
1302 1302
 		{
1303 1303
 		    struct cli_bc_func *target = NULL;
1304
-		    if (inst->opcode == OP_CALL_DIRECT) {
1304
+		    if (inst->opcode == OP_BC_CALL_DIRECT) {
1305 1305
 			target = &bc->funcs[inst->u.ops.funcid];
1306 1306
 			if (inst->u.ops.funcid > bc->num_func) {
1307 1307
 			    cli_errmsg("bytecode: called function out of range: %u > %u\n", inst->u.ops.funcid, bc->num_func);
... ...
@@ -1328,21 +1328,21 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc)
1328 1328
 			inst->u.ops.opsizes = NULL;
1329 1329
 		    for (k=0;k<inst->u.ops.numOps;k++) {
1330 1330
 			MAP(inst->u.ops.ops[k]);
1331
-			if (inst->opcode == OP_CALL_DIRECT)
1331
+			if (inst->opcode == OP_BC_CALL_DIRECT)
1332 1332
 			    inst->u.ops.opsizes[k] = typesize(bc, target->types[k]);
1333 1333
 			else
1334 1334
 			    inst->u.ops.opsizes[k] = 32; /*XXX*/
1335 1335
 		    }
1336 1336
 		    break;
1337 1337
 		}
1338
-		case OP_LOAD:
1338
+		case OP_BC_LOAD:
1339 1339
 		    MAP(inst->u.unaryop);
1340 1340
 		    break;
1341
-		case OP_GEP1:
1341
+		case OP_BC_GEP1:
1342 1342
 		    MAP(inst->u.binop[0]);
1343 1343
 		    MAP(inst->u.binop[1]);
1344 1344
 		    break;
1345
-		case OP_GEP2:
1345
+		case OP_BC_GEP2:
1346 1346
 		    MAP(inst->u.three[0]);
1347 1347
 		    MAP(inst->u.three[1]);
1348 1348
 		    MAP(inst->u.three[2]);
... ...
@@ -28,7 +28,7 @@ uint32_t cli_bcapi_test0(struct cli_bc_ctx *ctx, struct foo*, uint32_t);
28 28
 uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
29 29
 int32_t cli_bcapi_read(struct cli_bc_ctx *ctx, uint8_t*, int32_t);
30 30
 int32_t cli_bcapi_seek(struct cli_bc_ctx *ctx, int32_t, uint32_t);
31
-uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const uint8_t*, uint32_t);
31
+uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
32 32
 uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
33 33
 
34 34
 static uint16_t cli_tmp0[]={32, 70, 32};
... ...
@@ -298,7 +298,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
298 298
 
299 299
 #define BINOP(i) inst->u.binop[i]
300 300
 
301
-#define DEFINE_BINOP_HELPER(opc, OP, W0, W1, W2, W3, W4) \
301
+#define DEFINE_BINOP_BC_HELPER(opc, OP, W0, W1, W2, W3, W4) \
302 302
     case opc*5: {\
303 303
 		    uint8_t op0, op1, res;\
304 304
 		    int8_t sop0, sop1;\
... ...
@@ -350,8 +350,8 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
350 350
 		    break;\
351 351
 		}
352 352
 
353
-#define DEFINE_BINOP(opc, OP) DEFINE_BINOP_HELPER(opc, OP, WRITE8, WRITE8, WRITE16, WRITE32, WRITE64)
354
-#define DEFINE_ICMPOP(opc, OP) DEFINE_BINOP_HELPER(opc, OP, WRITE8, WRITE8, WRITE8, WRITE8, WRITE8)
353
+#define DEFINE_BINOP(opc, OP) DEFINE_BINOP_BC_HELPER(opc, OP, WRITE8, WRITE8, WRITE16, WRITE32, WRITE64)
354
+#define DEFINE_ICMPOP(opc, OP) DEFINE_BINOP_BC_HELPER(opc, OP, WRITE8, WRITE8, WRITE8, WRITE8, WRITE8)
355 355
 
356 356
 #define CHECK_OP(cond, msg) if((cond)) { cli_dbgmsg(msg); stop = CL_EBYTECODE; break;}
357 357
 
... ...
@@ -409,7 +409,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
409 409
 	default: CHECK_UNREACHABLE;\
410 410
     }
411 411
 
412
-#define DEFINE_OP_RET_N(OP, T, R0, W0) \
412
+#define DEFINE_OP_BC_RET_N(OP, T, R0, W0) \
413 413
     case OP: {\
414 414
 		T tmp;\
415 415
 		R0(tmp, inst->u.unaryop);\
... ...
@@ -447,77 +447,77 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
447 447
     do {
448 448
 	pc++;
449 449
 	switch (inst->interp_op) {
450
-	    DEFINE_BINOP(OP_ADD, res = op0 + op1);
451
-	    DEFINE_BINOP(OP_SUB, res = op0 - op1);
452
-	    DEFINE_BINOP(OP_MUL, res = op0 * op1);
450
+	    DEFINE_BINOP(OP_BC_ADD, res = op0 + op1);
451
+	    DEFINE_BINOP(OP_BC_SUB, res = op0 - op1);
452
+	    DEFINE_BINOP(OP_BC_MUL, res = op0 * op1);
453 453
 
454
-	    DEFINE_BINOP(OP_UDIV, CHECK_OP(op1 == 0, "bytecode attempted to execute udiv#0\n");
454
+	    DEFINE_BINOP(OP_BC_UDIV, CHECK_OP(op1 == 0, "bytecode attempted to execute udiv#0\n");
455 455
 			 res=op0/op1);
456
-	    DEFINE_BINOP(OP_SDIV, CHECK_OP(check_sdivops(sop0, sop1), "bytecode attempted to execute sdiv#0\n");
456
+	    DEFINE_BINOP(OP_BC_SDIV, CHECK_OP(check_sdivops(sop0, sop1), "bytecode attempted to execute sdiv#0\n");
457 457
 			 res=sop0/sop1);
458
-	    DEFINE_BINOP(OP_UREM, CHECK_OP(op1 == 0, "bytecode attempted to execute urem#0\n");
458
+	    DEFINE_BINOP(OP_BC_UREM, CHECK_OP(op1 == 0, "bytecode attempted to execute urem#0\n");
459 459
 			 res=op0 % op1);
460
-	    DEFINE_BINOP(OP_SREM, CHECK_OP(check_sdivops(sop0,sop1), "bytecode attempted to execute urem#0\n");
460
+	    DEFINE_BINOP(OP_BC_SREM, CHECK_OP(check_sdivops(sop0,sop1), "bytecode attempted to execute urem#0\n");
461 461
 			 res=sop0 % sop1);
462 462
 
463
-	    DEFINE_BINOP(OP_SHL, CHECK_OP(op1 > inst->type, "bytecode attempted to execute shl greater than bitwidth\n");
463
+	    DEFINE_BINOP(OP_BC_SHL, CHECK_OP(op1 > inst->type, "bytecode attempted to execute shl greater than bitwidth\n");
464 464
 			 res = op0 << op1);
465
-	    DEFINE_BINOP(OP_LSHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute lshr greater than bitwidth\n");
465
+	    DEFINE_BINOP(OP_BC_LSHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute lshr greater than bitwidth\n");
466 466
 			 res = op0 >> op1);
467
-	    DEFINE_BINOP(OP_ASHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute ashr greater than bitwidth\n");
467
+	    DEFINE_BINOP(OP_BC_ASHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute ashr greater than bitwidth\n");
468 468
 			 res = CLI_SRS(sop0, op1));
469 469
 
470
-	    DEFINE_BINOP(OP_AND, res = op0 & op1);
471
-	    DEFINE_BINOP(OP_OR, res = op0 | op1);
472
-	    DEFINE_BINOP(OP_XOR, res = op0 ^ op1);
470
+	    DEFINE_BINOP(OP_BC_AND, res = op0 & op1);
471
+	    DEFINE_BINOP(OP_BC_OR, res = op0 | op1);
472
+	    DEFINE_BINOP(OP_BC_XOR, res = op0 ^ op1);
473 473
 
474
-	    DEFINE_CASTOP(OP_SEXT,
474
+	    DEFINE_CASTOP(OP_BC_SEXT,
475 475
 			  CHOOSE(READ1(sres, inst->u.cast.source); res = sres ? ~0ull : 0,
476 476
 				 READ8(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
477 477
 				 READ16(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
478 478
 				 READ32(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
479 479
 				 READ64(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask)));
480
-	    DEFINE_CASTOP(OP_ZEXT,
480
+	    DEFINE_CASTOP(OP_BC_ZEXT,
481 481
 			  CHOOSE(READ1(res, inst->u.cast.source),
482 482
 				 READ8(res, inst->u.cast.source),
483 483
 				 READ16(res, inst->u.cast.source),
484 484
 				 READ32(res, inst->u.cast.source),
485 485
 				 READ64(res, inst->u.cast.source)));
486
-	    DEFINE_CASTOP(OP_TRUNC,
486
+	    DEFINE_CASTOP(OP_BC_TRUNC,
487 487
 			  CHOOSE(READ1(res, inst->u.cast.source),
488 488
 				 READ8(res, inst->u.cast.source),
489 489
 				 READ16(res, inst->u.cast.source),
490 490
 				 READ32(res, inst->u.cast.source),
491 491
 				 READ64(res, inst->u.cast.source)));
492 492
 
493
-	    DEFINE_OP(OP_BRANCH)
493
+	    DEFINE_OP(OP_BC_BRANCH)
494 494
 		stop = jump(func, (values[inst->u.branch.condition]&1) ?
495 495
 			  inst->u.branch.br_true : inst->u.branch.br_false,
496 496
 			  &bb, &inst, &bb_inst);
497 497
 		continue;
498 498
 
499
-	    DEFINE_OP(OP_JMP)
499
+	    DEFINE_OP(OP_BC_JMP)
500 500
 		stop = jump(func, inst->u.jump, &bb, &inst, &bb_inst);
501 501
 		continue;
502 502
 
503
-	    DEFINE_OP_RET_N(OP_RET*5, uint8_t, READ1, WRITE8);
504
-	    DEFINE_OP_RET_N(OP_RET*5+1, uint8_t, READ8, WRITE8);
505
-	    DEFINE_OP_RET_N(OP_RET*5+2, uint16_t, READ16, WRITE16);
506
-	    DEFINE_OP_RET_N(OP_RET*5+3, uint32_t, READ32, WRITE32);
507
-	    DEFINE_OP_RET_N(OP_RET*5+4, uint64_t, READ64, WRITE64);
508
-
509
-	    DEFINE_ICMPOP(OP_ICMP_EQ, res = (op0 == op1));
510
-	    DEFINE_ICMPOP(OP_ICMP_NE, res = (op0 != op1));
511
-	    DEFINE_ICMPOP(OP_ICMP_UGT, res = (op0 > op1));
512
-	    DEFINE_ICMPOP(OP_ICMP_UGE, res = (op0 >= op1));
513
-	    DEFINE_ICMPOP(OP_ICMP_ULT, res = (op0 < op1));
514
-	    DEFINE_ICMPOP(OP_ICMP_ULE, res = (op0 <= op1));
515
-	    DEFINE_ICMPOP(OP_ICMP_SGT, res = (sop0 > sop1));
516
-	    DEFINE_ICMPOP(OP_ICMP_SGE, res = (sop0 >= sop1));
517
-	    DEFINE_ICMPOP(OP_ICMP_SLE, res = (sop0 <= sop1));
518
-	    DEFINE_ICMPOP(OP_ICMP_SLT, res = (sop0 < sop1));
519
-
520
-	    case OP_SELECT*5:
503
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5, uint8_t, READ1, WRITE8);
504
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5+1, uint8_t, READ8, WRITE8);
505
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5+2, uint16_t, READ16, WRITE16);
506
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5+3, uint32_t, READ32, WRITE32);
507
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5+4, uint64_t, READ64, WRITE64);
508
+
509
+	    DEFINE_ICMPOP(OP_BC_ICMP_EQ, res = (op0 == op1));
510
+	    DEFINE_ICMPOP(OP_BC_ICMP_NE, res = (op0 != op1));
511
+	    DEFINE_ICMPOP(OP_BC_ICMP_UGT, res = (op0 > op1));
512
+	    DEFINE_ICMPOP(OP_BC_ICMP_UGE, res = (op0 >= op1));
513
+	    DEFINE_ICMPOP(OP_BC_ICMP_ULT, res = (op0 < op1));
514
+	    DEFINE_ICMPOP(OP_BC_ICMP_ULE, res = (op0 <= op1));
515
+	    DEFINE_ICMPOP(OP_BC_ICMP_SGT, res = (sop0 > sop1));
516
+	    DEFINE_ICMPOP(OP_BC_ICMP_SGE, res = (sop0 >= sop1));
517
+	    DEFINE_ICMPOP(OP_BC_ICMP_SLE, res = (sop0 <= sop1));
518
+	    DEFINE_ICMPOP(OP_BC_ICMP_SLT, res = (sop0 < sop1));
519
+
520
+	    case OP_BC_SELECT*5:
521 521
 	    {
522 522
 		uint8_t t0, t1, t2;
523 523
 		READ1(t0, inst->u.three[0]);
... ...
@@ -526,7 +526,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
526 526
 		WRITE8(inst->dest, t0 ? t1 : t2);
527 527
 		break;
528 528
 	    }
529
-	    case OP_SELECT*5+1:
529
+	    case OP_BC_SELECT*5+1:
530 530
 	    {
531 531
 	        uint8_t t0, t1, t2;
532 532
 		READ1(t0, inst->u.three[0]);
... ...
@@ -535,7 +535,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
535 535
 		WRITE8(inst->dest, t0 ? t1 : t2);
536 536
 		break;
537 537
 	    }
538
-	    case OP_SELECT*5+2:
538
+	    case OP_BC_SELECT*5+2:
539 539
 	    {
540 540
 	        uint8_t t0;
541 541
 		uint16_t t1, t2;
... ...
@@ -545,7 +545,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
545 545
 		WRITE16(inst->dest, t0 ? t1 : t2);
546 546
 		break;
547 547
 	    }
548
-	    case OP_SELECT*5+3:
548
+	    case OP_BC_SELECT*5+3:
549 549
 	    {
550 550
 	        uint8_t t0;
551 551
 		uint32_t t1, t2;
... ...
@@ -555,7 +555,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
555 555
 		WRITE32(inst->dest, t0 ? t1 : t2);
556 556
 		break;
557 557
 	    }
558
-	    case OP_SELECT*5+4:
558
+	    case OP_BC_SELECT*5+4:
559 559
 	    {
560 560
 	        uint8_t t0;
561 561
 		uint64_t t1, t2;
... ...
@@ -566,7 +566,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
566 566
 		break;
567 567
 	    }
568 568
 
569
-	    DEFINE_OP(OP_CALL_API) {
569
+	    DEFINE_OP(OP_BC_CALL_API) {
570 570
 		const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid];
571 571
 		int32_t res;
572 572
 		CHECK_APIID(inst->u.ops.funcid);
... ...
@@ -594,7 +594,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
594 594
 		break;
595 595
 	    }
596 596
 
597
-	    DEFINE_OP(OP_CALL_DIRECT)
597
+	    DEFINE_OP(OP_BC_CALL_DIRECT)
598 598
 		CHECK_FUNCID(inst->u.ops.funcid);
599 599
 		func2 = &bc->funcs[inst->u.ops.funcid];
600 600
 		CHECK_EQ(func2->numArgs, inst->u.ops.numOps);
... ...
@@ -657,35 +657,35 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
657 657
 		stack_depth++;
658 658
 		continue;
659 659
 
660
-	    case OP_COPY*5:
660
+	    case OP_BC_COPY*5:
661 661
 	    {
662 662
 		uint8_t op;
663 663
 		READ1(op, BINOP(0));
664 664
 		WRITE8(BINOP(1), op);
665 665
 		break;
666 666
 	    }
667
-	    case OP_COPY*5+1:
667
+	    case OP_BC_COPY*5+1:
668 668
 	    {
669 669
 		uint8_t op;
670 670
 		READ8(op, BINOP(0));
671 671
 		WRITE8(BINOP(1), op);
672 672
 		break;
673 673
 	    }
674
-	    case OP_COPY*5+2:
674
+	    case OP_BC_COPY*5+2:
675 675
 	    {
676 676
 		uint16_t op;
677 677
 		READ16(op, BINOP(0));
678 678
 		WRITE16(BINOP(1), op);
679 679
 		break;
680 680
 	    }
681
-	    case OP_COPY*5+3:
681
+	    case OP_BC_COPY*5+3:
682 682
 	    {
683 683
 		uint32_t op;
684 684
 		READ32(op, BINOP(0));
685 685
 		WRITE32(BINOP(1), op);
686 686
 		break;
687 687
 	    }
688
-	    case OP_COPY*5+4:
688
+	    case OP_BC_COPY*5+4:
689 689
 	    {
690 690
 		uint64_t op;
691 691
 		READ32(op, BINOP(0));
... ...
@@ -693,29 +693,29 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
693 693
 		break;
694 694
 	    }
695 695
 
696
-	    case OP_LOAD*5:
697
-	    case OP_LOAD*5+1:
696
+	    case OP_BC_LOAD*5:
697
+	    case OP_BC_LOAD*5+1:
698 698
 	    {
699 699
 		uint8_t *ptr;
700 700
 		READP(ptr, inst->u.unaryop);
701 701
 		WRITE8(inst->dest, (*ptr));
702 702
 		break;
703 703
 	    }
704
-	    case OP_LOAD*5+2:
704
+	    case OP_BC_LOAD*5+2:
705 705
 	    {
706 706
 		const union unaligned_16 *ptr;
707 707
 		READP(ptr, inst->u.unaryop);
708 708
 		WRITE16(inst->dest, (ptr->una_u16));
709 709
 		break;
710 710
 	    }
711
-	    case OP_LOAD*5+3:
711
+	    case OP_BC_LOAD*5+3:
712 712
 	    {
713 713
 		const union unaligned_32 *ptr;
714 714
 		READP(ptr, inst->u.unaryop);
715 715
 		WRITE32(inst->dest, (ptr->una_u32));
716 716
 		break;
717 717
 	    }
718
-	    case OP_LOAD*5+4:
718
+	    case OP_BC_LOAD*5+4:
719 719
 	    {
720 720
 		const union unaligned_64 *ptr;
721 721
 		READP(ptr, inst->u.unaryop);
... ...
@@ -723,7 +723,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
723 723
 		break;
724 724
 	    }
725 725
 
726
-	    case OP_STORE*5:
726
+	    case OP_BC_STORE*5:
727 727
 	    {
728 728
 		uint8_t *ptr;
729 729
 		uint8_t v;
... ...
@@ -732,7 +732,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
732 732
 		*ptr = v;
733 733
 		break;
734 734
 	    }
735
-	    case OP_STORE*5+1:
735
+	    case OP_BC_STORE*5+1:
736 736
 	    {
737 737
 		uint8_t *ptr;
738 738
 		uint8_t v;
... ...
@@ -741,7 +741,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
741 741
 		*ptr = v;
742 742
 		break;
743 743
 	    }
744
-	    case OP_STORE*5+2:
744
+	    case OP_BC_STORE*5+2:
745 745
 	    {
746 746
 		union unaligned_16 *ptr;
747 747
 		uint16_t v;
... ...
@@ -750,7 +750,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
750 750
 		ptr->una_s16 = v;
751 751
 		break;
752 752
 	    }
753
-	    case OP_STORE*5+3:
753
+	    case OP_BC_STORE*5+3:
754 754
 	    {
755 755
 		union unaligned_32 *ptr;
756 756
 		uint32_t v;
... ...
@@ -759,7 +759,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
759 759
 		ptr->una_u32 = v;
760 760
 		break;
761 761
 	    }
762
-	    case OP_STORE*5+4:
762
+	    case OP_BC_STORE*5+4:
763 763
 	    {
764 764
 		union unaligned_64 *ptr;
765 765
 		uint64_t v;
... ...
@@ -768,7 +768,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
768 768
 		ptr->una_u64 = v;
769 769
 		break;
770 770
 	    }
771
-	    /* TODO: implement OP_GEP1, OP_GEP2, OP_GEPN */
771
+	    /* TODO: implement OP_BC_GEP1, OP_BC_GEP2, OP_BC_GEPN */
772 772
 	    default:
773 773
 		cli_errmsg("Opcode %u of type %u is not implemented yet!\n",
774 774
 			   inst->interp_op/5, inst->interp_op%5);
... ...
@@ -425,20 +425,20 @@ public:
425 425
 		    const struct cli_bc_inst *inst = &bb->insts[j];
426 426
 		    Value *Op0, *Op1, *Op2;
427 427
 		    // libclamav has already validated this.
428
-		    assert(inst->opcode < OP_INVALID && "Invalid opcode");
428
+		    assert(inst->opcode < OP_BC_INVALID && "Invalid opcode");
429 429
 		    switch (inst->opcode) {
430
-			case OP_JMP:
431
-			case OP_BRANCH:
432
-			case OP_CALL_API:
433
-			case OP_CALL_DIRECT:
434
-			case OP_ZEXT:
435
-			case OP_SEXT:
436
-			case OP_TRUNC:
437
-			case OP_GEP1:
438
-			case OP_GEP2:
439
-			case OP_GEPN:
440
-			case OP_STORE:
441
-			case OP_COPY:
430
+			case OP_BC_JMP:
431
+			case OP_BC_BRANCH:
432
+			case OP_BC_CALL_API:
433
+			case OP_BC_CALL_DIRECT:
434
+			case OP_BC_ZEXT:
435
+			case OP_BC_SEXT:
436
+			case OP_BC_TRUNC:
437
+			case OP_BC_GEP1:
438
+			case OP_BC_GEP2:
439
+			case OP_BC_GEPN:
440
+			case OP_BC_STORE:
441
+			case OP_BC_COPY:
442 442
 			    // these instructions represents operands differently
443 443
 			    break;
444 444
 			default:
... ...
@@ -459,23 +459,23 @@ public:
459 459
 		    }
460 460
 
461 461
 		    switch (inst->opcode) {
462
-			case OP_ADD:
462
+			case OP_BC_ADD:
463 463
 			    Store(inst->dest, Builder.CreateAdd(Op0, Op1));
464 464
 			    break;
465
-			case OP_SUB:
465
+			case OP_BC_SUB:
466 466
 			    Store(inst->dest, Builder.CreateSub(Op0, Op1));
467 467
 			    break;
468
-			case OP_MUL:
468
+			case OP_BC_MUL:
469 469
 			    Store(inst->dest, Builder.CreateMul(Op0, Op1));
470 470
 			    break;
471
-			case OP_UDIV:
471
+			case OP_BC_UDIV:
472 472
 			{
473 473
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
474 474
 			    InsertVerify(Bad, Fail, FHandler, F);
475 475
 			    Store(inst->dest, Builder.CreateUDiv(Op0, Op1));
476 476
 			    break;
477 477
 			}
478
-			case OP_SDIV:
478
+			case OP_BC_SDIV:
479 479
 			{
480 480
 			    //TODO: also verify Op0 == -1 && Op1 = INT_MIN
481 481
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
... ...
@@ -483,14 +483,14 @@ public:
483 483
 			    Store(inst->dest, Builder.CreateSDiv(Op0, Op1));
484 484
 			    break;
485 485
 			}
486
-			case OP_UREM:
486
+			case OP_BC_UREM:
487 487
 			{
488 488
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
489 489
 			    InsertVerify(Bad, Fail, FHandler, F);
490 490
 			    Store(inst->dest, Builder.CreateURem(Op0, Op1));
491 491
 			    break;
492 492
 			}
493
-			case OP_SREM:
493
+			case OP_BC_SREM:
494 494
 			{
495 495
 			    //TODO: also verify Op0 == -1 && Op1 = INT_MIN
496 496
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
... ...
@@ -498,46 +498,46 @@ public:
498 498
 			    Store(inst->dest, Builder.CreateSRem(Op0, Op1));
499 499
 			    break;
500 500
 			}
501
-			case OP_SHL:
501
+			case OP_BC_SHL:
502 502
 			    Store(inst->dest, Builder.CreateShl(Op0, Op1));
503 503
 			    break;
504
-			case OP_LSHR:
504
+			case OP_BC_LSHR:
505 505
 			    Store(inst->dest, Builder.CreateLShr(Op0, Op1));
506 506
 			    break;
507
-			case OP_ASHR:
507
+			case OP_BC_ASHR:
508 508
 			    Store(inst->dest, Builder.CreateAShr(Op0, Op1));
509 509
 			    break;
510
-			case OP_AND:
510
+			case OP_BC_AND:
511 511
 			    Store(inst->dest, Builder.CreateAnd(Op0, Op1));
512 512
 			    break;
513
-			case OP_OR:
513
+			case OP_BC_OR:
514 514
 			    Store(inst->dest, Builder.CreateOr(Op0, Op1));
515 515
 			    break;
516
-			case OP_XOR:
516
+			case OP_BC_XOR:
517 517
 			    Store(inst->dest, Builder.CreateXor(Op0, Op1));
518 518
 			    break;
519
-			case OP_TRUNC:
519
+			case OP_BC_TRUNC:
520 520
 			{
521 521
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
522 522
 			    const Type *Ty = mapType(func->types[inst->dest]);
523 523
 			    Store(inst->dest, Builder.CreateTrunc(Src,  Ty));
524 524
 			    break;
525 525
 			}
526
-			case OP_ZEXT:
526
+			case OP_BC_ZEXT:
527 527
 			{
528 528
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
529 529
 			    const Type *Ty = mapType(func->types[inst->dest]);
530 530
 			    Store(inst->dest, Builder.CreateZExt(Src,  Ty));
531 531
 			    break;
532 532
 			}
533
-			case OP_SEXT:
533
+			case OP_BC_SEXT:
534 534
 			{
535 535
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
536 536
 			    const Type *Ty = mapType(func->types[inst->dest]);
537 537
 			    Store(inst->dest, Builder.CreateSExt(Src,  Ty));
538 538
 			    break;
539 539
 			}
540
-			case OP_BRANCH:
540
+			case OP_BC_BRANCH:
541 541
 			{
542 542
 			    Value *Cond = convertOperand(func, inst, inst->u.branch.condition);
543 543
 			    BasicBlock *True = BB[inst->u.branch.br_true];
... ...
@@ -549,46 +549,46 @@ public:
549 549
 			    Builder.CreateCondBr(Cond, True, False);
550 550
 			    break;
551 551
 			}
552
-			case OP_JMP:
552
+			case OP_BC_JMP:
553 553
 			{
554 554
 			    BasicBlock *Jmp = BB[inst->u.jump];
555 555
 			    Builder.CreateBr(Jmp);
556 556
 			    break;
557 557
 			}
558
-			case OP_RET:
558
+			case OP_BC_RET:
559 559
 			    Builder.CreateRet(Op0);
560 560
 			    break;
561
-			case OP_ICMP_EQ:
561
+			case OP_BC_ICMP_EQ:
562 562
 			    Store(inst->dest, Builder.CreateICmpEQ(Op0, Op1));
563 563
 			    break;
564
-			case OP_ICMP_NE:
564
+			case OP_BC_ICMP_NE:
565 565
 			    Store(inst->dest, Builder.CreateICmpNE(Op0, Op1));
566 566
 			    break;
567
-			case OP_ICMP_UGT:
567
+			case OP_BC_ICMP_UGT:
568 568
 			    Store(inst->dest, Builder.CreateICmpUGT(Op0, Op1));
569 569
 			    break;
570
-			case OP_ICMP_UGE:
570
+			case OP_BC_ICMP_UGE:
571 571
 			    Store(inst->dest, Builder.CreateICmpUGE(Op0, Op1));
572 572
 			    break;
573
-			case OP_ICMP_ULT:
573
+			case OP_BC_ICMP_ULT:
574 574
 			    Store(inst->dest, Builder.CreateICmpULT(Op0, Op1));
575 575
 			    break;
576
-			case OP_ICMP_ULE:
576
+			case OP_BC_ICMP_ULE:
577 577
 			    Store(inst->dest, Builder.CreateICmpULE(Op0, Op1));
578 578
 			    break;
579
-			case OP_ICMP_SGT:
579
+			case OP_BC_ICMP_SGT:
580 580
 			    Store(inst->dest, Builder.CreateICmpSGT(Op0, Op1));
581 581
 			    break;
582
-			case OP_ICMP_SGE:
582
+			case OP_BC_ICMP_SGE:
583 583
 			    Store(inst->dest, Builder.CreateICmpSGE(Op0, Op1));
584 584
 			    break;
585
-			case OP_ICMP_SLT:
585
+			case OP_BC_ICMP_SLT:
586 586
 			    Store(inst->dest, Builder.CreateICmpSLT(Op0, Op1));
587 587
 			    break;
588
-			case OP_SELECT:
588
+			case OP_BC_SELECT:
589 589
 			    Store(inst->dest, Builder.CreateSelect(Op0, Op1, Op2));
590 590
 			    break;
591
-			case OP_COPY:
591
+			case OP_BC_COPY:
592 592
 			{
593 593
 			    Value *Dest = Values[inst->u.binop[1]];
594 594
 			    const PointerType *PTy = cast<PointerType>(Dest->getType());
... ...
@@ -596,7 +596,7 @@ public:
596 596
 			    Builder.CreateStore(Op0, Dest);
597 597
 			    break;
598 598
 			}
599
-			case OP_CALL_DIRECT:
599
+			case OP_BC_CALL_DIRECT:
600 600
 			{
601 601
 			    Function *DestF = Functions[inst->u.ops.funcid];
602 602
 			    SmallVector<Value*, 2> args;
... ...
@@ -610,7 +610,7 @@ public:
610 610
 			    Store(inst->dest, CI);
611 611
 			    break;
612 612
 			}
613
-			case OP_CALL_API:
613
+			case OP_BC_CALL_API:
614 614
 			{
615 615
 			    assert(inst->u.ops.funcid < cli_apicall_maxapi && "APICall out of range");
616 616
 			    const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid];
... ...
@@ -624,14 +624,14 @@ public:
624 624
 			    Store(inst->dest, Builder.CreateCall(DestF, args.begin(), args.end()));
625 625
 			    break;
626 626
 			}
627
-			case OP_GEP1:
627
+			case OP_BC_GEP1:
628 628
 			{
629 629
 			    Value *V = Values[inst->u.binop[0]];
630 630
 			    Value *Op = convertOperand(func, I32Ty, inst->u.binop[1]);
631 631
 			    Store(inst->dest, Builder.CreateGEP(V, Op));
632 632
 			    break;
633 633
 			}
634
-			case OP_GEP2:
634
+			case OP_BC_GEP2:
635 635
 			{
636 636
 			    std::vector<Value*> Idxs;
637 637
 			    Value *V = Values[inst->u.three[0]];
... ...
@@ -640,7 +640,7 @@ public:
640 640
 			    Store(inst->dest, Builder.CreateGEP(V, Idxs.begin(), Idxs.end()));
641 641
 			    break;
642 642
 			}
643
-			case OP_GEPN:
643
+			case OP_BC_GEPN:
644 644
 			{
645 645
 			    std::vector<Value*> Idxs;
646 646
 			    assert(inst->u.ops.numOps > 1);
... ...
@@ -650,7 +650,7 @@ public:
650 650
 			    Store(inst->dest, Builder.CreateGEP(V, Idxs.begin(), Idxs.end()));
651 651
 			    break;
652 652
 			}
653
-			case OP_STORE:
653
+			case OP_BC_STORE:
654 654
 			{
655 655
 			    Value *Dest = convertOperand(func, inst, inst->u.binop[1]);
656 656
 			    const Type *ETy = cast<PointerType>(Dest->getType())->getElementType();
... ...
@@ -658,7 +658,7 @@ public:
658 658
 						Dest);
659 659
 			    break;
660 660
 			}
661
-			case OP_LOAD:
661
+			case OP_BC_LOAD:
662 662
 			    Op0 = Builder.CreateLoad(Op0);
663 663
 			    Store(inst->dest, Op0);
664 664
 			    break;
... ...
@@ -858,7 +858,9 @@ int bytecode_init(void)
858 858
     if (llvm_is_multithreaded())
859 859
 	return 0;
860 860
     llvm_install_error_handler(llvm_error_handler);
861
+#ifdef CL_DEBUG
861 862
     sys::PrintStackTraceOnErrorSignal();
863
+#endif
862 864
     atexit(do_shutdown);
863 865
 
864 866
     llvm_start_multithreaded();
... ...
@@ -876,6 +878,7 @@ int cli_bytecode_init_jit(struct cli_all_bc *bcs)
876 876
     bcs->engine = new(std::nothrow) struct cli_bcengine;
877 877
     if (!bcs->engine)
878 878
 	return CL_EMEM;
879
+    bcs->engine->EE = 0;
879 880
     return 0;
880 881
 }
881 882
 
... ...
@@ -80,9 +80,10 @@ typedef enum {
80 80
 #define CL_DB_PUA_EXCLUDE   0x200
81 81
 #define CL_DB_COMPILED	    0x400   /* internal */
82 82
 #define CL_DB_DIRECTORY	    0x800   /* internal */
83
+#define CL_DB_BYTECODE      0x1000
83 84
 
84 85
 /* recommended db settings */
85
-#define CL_DB_STDOPT	    (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_CVDNOTMP)
86
+#define CL_DB_STDOPT	    (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_CVDNOTMP | CL_DB_BYTECODE)
86 87
 
87 88
 /* scan options */
88 89
 #define CL_SCAN_RAW			0x0
... ...
@@ -32,49 +32,49 @@ struct bytecode_metadata {
32 32
 #define BC_HEADER "ClamBC"
33 33
 
34 34
 enum bc_opcode {
35
-  OP_ADD=1,
36
-  OP_SUB,
37
-  OP_MUL,
38
-  OP_UDIV,
39
-  OP_SDIV,
40
-  OP_UREM,
41
-  OP_SREM,
42
-  OP_SHL,
43
-  OP_LSHR,
44
-  OP_ASHR,
45
-  OP_AND,
46
-  OP_OR,
47
-  OP_XOR,
35
+  OP_BC_ADD=1,
36
+  OP_BC_SUB,
37
+  OP_BC_MUL,
38
+  OP_BC_UDIV,
39
+  OP_BC_SDIV,
40
+  OP_BC_UREM,
41
+  OP_BC_SREM,
42
+  OP_BC_SHL,
43
+  OP_BC_LSHR,
44
+  OP_BC_ASHR,
45
+  OP_BC_AND,
46
+  OP_BC_OR,
47
+  OP_BC_XOR,
48 48
 
49
-  OP_TRUNC,
50
-  OP_SEXT,
51
-  OP_ZEXT,
49
+  OP_BC_TRUNC,
50
+  OP_BC_SEXT,
51
+  OP_BC_ZEXT,
52 52
 
53
-  OP_BRANCH,
54
-  OP_JMP,
55
-  OP_RET,
56
-  OP_RET_VOID,
53
+  OP_BC_BRANCH,
54
+  OP_BC_JMP,
55
+  OP_BC_RET,
56
+  OP_BC_RET_VOID,
57 57
 
58
-  OP_ICMP_EQ,
59
-  OP_ICMP_NE,
60
-  OP_ICMP_UGT,
61
-  OP_ICMP_UGE,
62
-  OP_ICMP_ULT,
63
-  OP_ICMP_ULE,
64
-  OP_ICMP_SGT,
65
-  OP_ICMP_SGE,
66
-  OP_ICMP_SLE,
67
-  OP_ICMP_SLT,
68
-  OP_SELECT,
69
-  OP_CALL_DIRECT,
70
-  OP_CALL_API,
71
-  OP_COPY,
72
-  OP_GEP1,
73
-  OP_GEP2,
74
-  OP_GEPN,
75
-  OP_STORE,
76
-  OP_LOAD,
77
-  OP_INVALID /* last */
58
+  OP_BC_ICMP_EQ,
59
+  OP_BC_ICMP_NE,
60
+  OP_BC_ICMP_UGT,
61
+  OP_BC_ICMP_UGE,
62
+  OP_BC_ICMP_ULT,
63
+  OP_BC_ICMP_ULE,
64
+  OP_BC_ICMP_SGT,
65
+  OP_BC_ICMP_SGE,
66
+  OP_BC_ICMP_SLE,
67
+  OP_BC_ICMP_SLT,
68
+  OP_BC_SELECT,
69
+  OP_BC_CALL_DIRECT,
70
+  OP_BC_CALL_API,
71
+  OP_BC_COPY,
72
+  OP_BC_GEP1,
73
+  OP_BC_GEP2,
74
+  OP_BC_GEPN,
75
+  OP_BC_STORE,
76
+  OP_BC_LOAD,
77
+  OP_BC_INVALID /* last */
78 78
 };
79 79
 
80 80
 static const unsigned char operand_counts[] = {
... ...
@@ -91,9 +91,9 @@ static const unsigned char operand_counts[] = {
91 91
   3,
92 92
   /* CALLs have variable number of operands */
93 93
   0, 0,
94
-  /* OP_COPY */
94
+  /* OP_BC_COPY */
95 95
   2,
96
-  /* OP_GEP1, OP_GEP2, OP_GEPN, OP_STORE, OP_LOAD*/
96
+  /* OP_BC_GEP1, OP_BC_GEP2, OP_BC_GEPN, OP_BC_STORE, OP_BC_LOAD*/
97 97
   2, 3, 0, 2, 1
98 98
 };
99 99
 
... ...
@@ -114,6 +114,11 @@ static struct dconf_module modules[] = {
114 114
     { "PHISHING",   "ENGINE",       PHISHING_CONF_ENGINE,   1 },
115 115
     { "PHISHING",   "ENTCONV",      PHISHING_CONF_ENTCONV,  1 },
116 116
 
117
+    { "BYTECODE",   "INTERPRETER",  BYTECODE_INTERPRETER,   1 },
118
+    { "BYTECODE",   "JIT X86",      BYTECODE_JIT_X86,       1 },
119
+    { "BYTECODE",   "JIT PPC",      BYTECODE_JIT_PPC,       1 },
120
+    { "BYTECODE",   "JIT ARM",      BYTECODE_JIT_ARM,       0 },
121
+
117 122
     { NULL,	    NULL,	    0,			    0 }
118 123
 };
119 124
 
... ...
@@ -161,6 +166,9 @@ struct cli_dconf *cli_dconf_init(void)
161 161
 	} else if(!strcmp(modules[i].mname, "PHISHING")) {
162 162
 	    if(modules[i].state)
163 163
 		dconf->phishing |= modules[i].bflag;
164
+	} else if(!strcmp(modules[i].mname, "BYTECODE")) {
165
+	    if (modules[i].state)
166
+		dconf->bytecode |= modules[i].bflag;
164 167
 	}
165 168
     }
166 169
 
... ...
@@ -170,7 +178,7 @@ struct cli_dconf *cli_dconf_init(void)
170 170
 void cli_dconf_print(struct cli_dconf *dconf)
171 171
 {
172 172
 	unsigned int pe = 0, elf = 0, macho = 0, arch = 0, doc = 0, mail = 0;
173
-	unsigned int other = 0, phishing = 0, i;
173
+	unsigned int other = 0, phishing = 0, i, bytecode=0;
174 174
 
175 175
 
176 176
     cli_dbgmsg("Dynamic engine configuration settings:\n");
... ...
@@ -247,6 +255,15 @@ void cli_dconf_print(struct cli_dconf *dconf)
247 247
 		cli_dbgmsg("   * Submodule %10s:\t%s\n", modules[i].sname, (dconf->phishing & modules[i].bflag) ? "On" : "** Off **");
248 248
 	    else
249 249
 		continue;
250
+	} else if(!strcmp(modules[i].mname, "BYTECODE")) {
251
+	    if(!bytecode) {
252
+		cli_dbgmsg("Module BYTECODE %s\n", dconf->phishing ? "On" : "Off");
253
+		bytecode = 1;
254
+	    }
255
+	    if(dconf->bytecode)
256
+		cli_dbgmsg("   * Submodule %10s:\t%s\n", modules[i].sname, (dconf->bytecode & modules[i].bflag) ? "On" : "** Off **");
257
+	    else
258
+		continue;
250 259
 	}
251 260
     }
252 261
 }
... ...
@@ -370,6 +387,15 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
370 370
 		break;
371 371
 	    }
372 372
 	}
373
+
374
+	if(!strncmp(buffer, "BYTECODE:", 9) && chkflevel(buffer, 2)) {
375
+	    if(sscanf(buffer + 9, "0x%x", &val) == 1) {
376
+		engine->dconf->bytecode = val;
377
+	    } else {
378
+		ret = CL_EMALFDB;
379
+		break;
380
+	    }
381
+	}
373 382
     }
374 383
 
375 384
     if(ret) {
... ...
@@ -39,6 +39,7 @@ struct cli_dconf {
39 39
     uint32_t mail;
40 40
     uint32_t other;
41 41
     uint32_t phishing;
42
+    uint32_t bytecode;
42 43
 };
43 44
 
44 45
 /* PE flags */
... ...
@@ -103,6 +104,14 @@ struct cli_dconf {
103 103
 #define PHISHING_CONF_ENGINE   0x1
104 104
 #define PHISHING_CONF_ENTCONV  0x2
105 105
 
106
+/* Bytecode flags */
107
+#define BYTECODE_INTERPRETER 0x1
108
+#define BYTECODE_JIT_X86 0x2
109
+#define BYTECODE_JIT_PPC 0x4
110
+#define BYTECODE_JIT_ARM 0x8
111
+
112
+#define BYTECODE_ENGINE_MASK (BYTECODE_INTERPRETER | BYTECODE_JIT_X86 | BYTECODE_JIT_PPC | BYTECODE_JIT_ARM)
113
+
106 114
 #ifdef USE_MPOOL
107 115
 struct cli_dconf *cli_dconf_init(mpool_t *);
108 116
 #define cli_mpool_dconf_init(a) cli_dconf_init(a)
... ...
@@ -39,6 +39,7 @@
39 39
 #include "dconf.h"
40 40
 #include "libclamunrar_iface/unrar_iface.h"
41 41
 #include "regex/regex.h"
42
+#include "bytecode.h"
42 43
 
43 44
 /*
44 45
  * CL_FLEVEL is the signature f-level specific to the current code and
... ...
@@ -175,6 +176,9 @@ struct cl_engine {
175 175
 
176 176
     /* Used for memory pools */
177 177
     mpool_t *mempool;
178
+
179
+    /* Used for bytecode */
180
+    struct cli_all_bc bcs;
178 181
 };
179 182
 
180 183
 struct cl_settings {
... ...
@@ -70,7 +70,8 @@
70 70
 #endif
71 71
 
72 72
 #include "mpool.h"
73
-
73
+#include "bytecode.h"
74
+#include "bytecode_priv.h"
74 75
 #ifdef CL_THREAD_SAFE
75 76
 #  include <pthread.h>
76 77
 static pthread_mutex_t cli_ref_mutex = PTHREAD_MUTEX_INITIALIZER;
... ...
@@ -1013,6 +1014,29 @@ static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1013 1013
     return CL_SUCCESS;
1014 1014
 }
1015 1015
 
1016
+static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1017
+{
1018
+    int rc;
1019
+    struct cli_all_bc *bcs = &engine->bcs;
1020
+    struct cli_bc *bc;
1021
+    if(!(engine->dconf->bytecode & BYTECODE_ENGINE_MASK)) {
1022
+	return CL_SUCCESS;
1023
+    }
1024
+    bcs->all_bcs = cli_realloc2(bcs->all_bcs, sizeof(*bcs->all_bcs)*(bcs->count+1));
1025
+    if (!bcs->all_bcs) {
1026
+	cli_errmsg("cli_loadcbc: Can't allocate memory for bytecode entry\n");
1027
+	return CL_EMEM;
1028
+    }
1029
+    bcs->count++;
1030
+    bc = &bcs->all_bcs[bcs->count-1];
1031
+    rc = cli_bytecode_load(bc, fs, dbio);
1032
+    if (rc != CL_SUCCESS) {
1033
+	fprintf(stderr,"Unable to load %s bytecode: %s\n", dbname, cl_strerror(rc));
1034
+	return rc;
1035
+    }
1036
+    return CL_SUCCESS;
1037
+}
1038
+
1016 1039
 #define FTM_TOKENS 8
1017 1040
 static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio)
1018 1041
 {
... ...
@@ -1608,7 +1632,11 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo
1608 1608
 	    ret = cli_loadldb(fs, engine, signo, options | CL_DB_PUA_MODE, dbio, dbname);
1609 1609
 	else
1610 1610
 	    skipped = 1;
1611
-
1611
+    } else if(cli_strbcasestr(filename, ".cbc")) {
1612
+	if(options & CL_DB_BYTECODE)
1613
+	    ret = cli_loadcbc(fs, engine, signo, options, dbio, dbname);
1614
+	else
1615
+	    skipped = 1;
1612 1616
     } else if(cli_strbcasestr(dbname, ".sdb")) {
1613 1617
 	ret = cli_loadndb(fs, engine, signo, 1, options, dbio, dbname);
1614 1618
 
... ...
@@ -1782,10 +1810,17 @@ int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, uns
1782 1782
 	if((ret = phishing_init(engine)))
1783 1783
 	    return ret;
1784 1784
 
1785
+    if((dboptions & CL_DB_BYTECODE) && !engine->bcs.engine && (engine->dconf->bytecode & BYTECODE_ENGINE_MASK)) {
1786
+	if((ret = cli_bytecode_init(&engine->bcs)))
1787
+	    return ret;
1788
+    } else {
1789
+	cli_dbgmsg("Bytecode engine disabled\n");
1790
+    }
1791
+
1785 1792
     engine->dboptions |= dboptions;
1786 1793
 
1787 1794
     switch(sb.st_mode & S_IFMT) {
1788
-	case S_IFREG: 
1795
+	case S_IFREG:
1789 1796
 	    ret = cli_load(path, engine, signo, dboptions, NULL);
1790 1797
 	    break;
1791 1798
 
... ...
@@ -2092,6 +2127,14 @@ int cl_engine_free(struct cl_engine *engine)
2092 2092
 	mpool_free(engine->mempool, metah);
2093 2093
     }
2094 2094
 
2095
+    if(engine->dconf->bytecode & BYTECODE_ENGINE_MASK) {
2096
+	unsigned i;
2097
+	if (engine->bcs.all_bcs)
2098
+	    for(i=0;i<engine->bcs.count;i++)
2099
+		cli_bytecode_destroy(&engine->bcs.all_bcs[i]);
2100
+	cli_bytecode_done(&engine->bcs);
2101
+	free(engine->bcs.all_bcs);
2102
+    }
2095 2103
     if(engine->dconf->phishing & PHISHING_CONF_ENGINE)
2096 2104
 	phishing_done(engine);
2097 2105
     if(engine->dconf)
... ...
@@ -2168,6 +2211,12 @@ int cl_engine_compile(struct cl_engine *engine)
2168 2168
     cli_dconf_print(engine->dconf);
2169 2169
     mpool_flush(engine->mempool);
2170 2170
 
2171
+    /* Compile bytecode */
2172
+    if((ret = cli_bytecode_prepare(&engine->bcs))) {
2173
+	fprintf(stderr,"Unable to compile/load bytecode: %s\n", cl_strerror(ret));
2174
+	return ret;
2175
+    }
2176
+
2171 2177
     engine->dboptions |= CL_DB_COMPILED;
2172 2178
     return CL_SUCCESS;
2173 2179
 }
... ...
@@ -47,6 +47,7 @@
47 47
 	cli_strbcasestr(ext, ".pdb")   ||	\
48 48
 	cli_strbcasestr(ext, ".gdb")   ||	\
49 49
 	cli_strbcasestr(ext, ".wdb")   ||	\
50
+	cli_strbcasestr(ext, ".cbc")   ||	\
50 51
 	cli_strbcasestr(ext, ".ftm")   ||	\
51 52
 	cli_strbcasestr(ext, ".ign")   ||	\
52 53
 	cli_strbcasestr(ext, ".cfg")   ||	\
... ...
@@ -233,7 +233,7 @@ const struct clam_option clam_options[] = {
233 233
     { "AllowSupplementaryGroups", NULL, 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Initialize a supplementary group access (the process must be started by root).", "no" },
234 234
 
235 235
     /* Scan options */
236
-
236
+    { "Bytecode", "bytecode", 0, TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "With this option enabled ClamAV will load bytecode from the database. It is highly recommended you keep this option on, otherwise you'll miss detections for many new viruses.", "yes" },
237 237
     { "DetectPUA", "detect-pua", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Detect Potentially Unwanted Applications.", "yes" },
238 238
 
239 239
     { "ExcludePUA", "exclude-pua", 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_CLAMSCAN, "Exclude a specific PUA category. This directive can be used multiple times.\nSee http://www.clamav.net/support/pua for the complete list of PUA\ncategories.", "NetTool\nPWTool" },
... ...
@@ -129,6 +129,14 @@ START_TEST (test_div0)
129 129
 }
130 130
 END_TEST
131 131
 
132
+START_TEST (test_lsig)
133
+{
134
+    cl_init(CL_INIT_DEFAULT);
135
+    runtest("input/lsig.cbc", 0, CL_EBYTECODE, 0);
136
+//  runtest("input/lsig.cbc", 0, CL_EBYTECODE, 1);
137
+}
138
+END_TEST
139
+
132 140
 Suite *test_bytecode_suite(void)
133 141
 {
134 142
     Suite *s = suite_create("bytecode");