[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

Török Edvin edwin at clamav.net
Sun Apr 4 01:05:03 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit 52dd3a6bdabe194deb6c996928b1a6b5d925cc5b
Author: Török Edvin <edwin at clamav.net>
Date:   Mon Sep 21 19:24:16 2009 +0300

    Initial support for loading .cbc files from DB.

diff --git a/clamd/clamd.c b/clamd/clamd.c
index 26e032f..ed4fadf 100644
--- a/clamd/clamd.c
+++ b/clamd/clamd.c
@@ -400,6 +400,9 @@ int main(int argc, char **argv)
     else
 	logg("#Not loading phishing signatures.\n");
 
+    if(optget(opts,"Bytecode")->enabled)
+	dboptions |= CL_DB_BYTECODE;
+
     if(optget(opts,"PhishingScanURLs")->enabled)
 	dboptions |= CL_DB_PHISHING_URLS;
     else
diff --git a/clamscan/manager.c b/clamscan/manager.c
index 38aba5a..0891cc7 100644
--- a/clamscan/manager.c
+++ b/clamscan/manager.c
@@ -352,6 +352,9 @@ int scanmanager(const struct optstruct *opts)
     if(optget(opts,"phishing-scan-urls")->enabled)
 	dboptions |= CL_DB_PHISHING_URLS;
 
+    if(optget(opts,"bytecode")->enabled)
+	dboptions |= CL_DB_BYTECODE;
+
     if((ret = cl_init(CL_INIT_DEFAULT))) {
 	logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
 	return 50;
diff --git a/libclamav/bytecode.c b/libclamav/bytecode.c
index 7dde5e6..9cada5a 100644
--- a/libclamav/bytecode.c
+++ b/libclamav/bytecode.c
@@ -420,7 +420,7 @@ static int parseLSig(struct cli_bc *bc, unsigned char *buffer)
 	return CL_EMALFDB;
     }
     bc->lsig = NULL;
-    bc->lsig = cli_strdup(buffer[1]);
+    bc->lsig = cli_strdup(buffer + 1);
     return CL_SUCCESS;
 }
 
@@ -890,26 +890,26 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
 	    cli_errmsg("Invalid type or operand\n");
 	    return CL_EMALFDB;
 	}
-	if (inst.opcode >= OP_INVALID) {
+	if (inst.opcode >= OP_BC_INVALID) {
 	    cli_errmsg("Invalid opcode: %u\n", inst.opcode);
 	    return CL_EMALFDB;
 	}
 
 	switch (inst.opcode) {
-	    case OP_JMP:
+	    case OP_BC_JMP:
 		inst.u.jump = readBBID(bcfunc, buffer, &offset, len, &ok);
 		break;
-	    case OP_RET:
+	    case OP_BC_RET:
 		inst.type = readNumber(buffer, &offset, len, &ok);
 		inst.u.unaryop = readOperand(bcfunc, buffer, &offset, len, &ok);
 		break;
-	    case OP_BRANCH:
+	    case OP_BC_BRANCH:
 		inst.u.branch.condition = readOperand(bcfunc, buffer, &offset, len, &ok);
 		inst.u.branch.br_true = readBBID(bcfunc, buffer, &offset, len, &ok);
 		inst.u.branch.br_false = readBBID(bcfunc, buffer, &offset, len, &ok);
 		break;
-	    case OP_CALL_API:/* fall-through */
-	    case OP_CALL_DIRECT:
+	    case OP_BC_CALL_API:/* fall-through */
+	    case OP_BC_CALL_DIRECT:
 		numOp = readFixedNumber(buffer, &offset, len, &ok, 1);
 		if (ok) {
 		    inst.u.ops.numOps = numOp;
@@ -919,7 +919,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
 			cli_errmsg("Out of memory allocating operands\n");
 			return CL_EMALFDB;
 		    }
-		    if (inst.opcode == OP_CALL_DIRECT)
+		    if (inst.opcode == OP_BC_CALL_DIRECT)
 			inst.u.ops.funcid = readFuncID(bc, buffer, &offset, len, &ok);
 		    else
 			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
 		    }
 		}
 		break;
-	    case OP_ZEXT:
-	    case OP_SEXT:
-	    case OP_TRUNC:
+	    case OP_BC_ZEXT:
+	    case OP_BC_SEXT:
+	    case OP_BC_TRUNC:
 		inst.u.cast.source = readOperand(bcfunc, buffer, &offset, len, &ok);
 		inst.u.cast.mask = bcfunc->types[inst.u.cast.source];
 		if (inst.u.cast.mask == 1)
@@ -944,21 +944,21 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
 		else if (inst.u.cast.mask <= 64)
 		    inst.u.cast.size = 4;
 		/* calculate mask */
-		if (inst.opcode != OP_SEXT)
+		if (inst.opcode != OP_BC_SEXT)
 		    inst.u.cast.mask = inst.u.cast.mask != 64 ?
 			(1ull<<inst.u.cast.mask)-1 :
 			~0ull;
 		break;
-	    case OP_ICMP_EQ:
-	    case OP_ICMP_NE:
-	    case OP_ICMP_UGT:
-	    case OP_ICMP_UGE:
-	    case OP_ICMP_ULT:
-	    case OP_ICMP_ULE:
-	    case OP_ICMP_SGT:
-	    case OP_ICMP_SGE:
-	    case OP_ICMP_SLE:
-	    case OP_ICMP_SLT:
+	    case OP_BC_ICMP_EQ:
+	    case OP_BC_ICMP_NE:
+	    case OP_BC_ICMP_UGT:
+	    case OP_BC_ICMP_UGE:
+	    case OP_BC_ICMP_ULT:
+	    case OP_BC_ICMP_ULE:
+	    case OP_BC_ICMP_SGT:
+	    case OP_BC_ICMP_SGE:
+	    case OP_BC_ICMP_SLE:
+	    case OP_BC_ICMP_SLT:
 		/* instruction type must be correct before readOperand! */
 		inst.type = readNumber(buffer, &offset, len, &ok);
 		/* fall-through */
@@ -1160,8 +1160,8 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru
 	func.numBytes = ctx->bytes;
 	memset(ctx->values+ctx->bytes-8, 0, 8);
 
-	inst.opcode = OP_CALL_DIRECT;
-	inst.interp_op = OP_CALL_DIRECT*5;
+	inst.opcode = OP_BC_CALL_DIRECT;
+	inst.interp_op = OP_BC_CALL_DIRECT*5;
 	inst.dest = func.numArgs;
 	inst.type = 0;
 	inst.u.ops.numOps = ctx->numParams;
@@ -1194,7 +1194,7 @@ void cli_bytecode_destroy(struct cli_bc *bc)
 	    for(k=0;k<BB->numInsts;k++) {
 		struct cli_bc_inst *ii = &BB->insts[k];
 		if (operand_counts[ii->opcode] > 3 ||
-		    ii->opcode == OP_CALL_DIRECT || ii->opcode == OP_CALL_API) {
+		    ii->opcode == OP_BC_CALL_DIRECT || ii->opcode == OP_BC_CALL_API) {
 		    free(ii->u.ops.ops);
 		    free(ii->u.ops.opsizes);
 		}
@@ -1251,57 +1251,57 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc)
 	    struct cli_bc_inst *inst = &bcfunc->allinsts[j];
 	    inst->dest = map[inst->dest];
 	    switch (inst->opcode) {
-		case OP_ADD:
-		case OP_SUB:
-		case OP_MUL:
-		case OP_UDIV:
-		case OP_SDIV:
-		case OP_UREM:
-		case OP_SREM:
-		case OP_SHL:
-		case OP_LSHR:
-		case OP_ASHR:
-		case OP_AND:
-		case OP_OR:
-		case OP_XOR:
-		case OP_ICMP_EQ:
-		case OP_ICMP_NE:
-		case OP_ICMP_UGT:
-		case OP_ICMP_UGE:
-		case OP_ICMP_ULT:
-		case OP_ICMP_ULE:
-		case OP_ICMP_SGT:
-		case OP_ICMP_SGE:
-		case OP_ICMP_SLT:
-		case OP_ICMP_SLE:
-		case OP_COPY:
-		case OP_STORE:
+		case OP_BC_ADD:
+		case OP_BC_SUB:
+		case OP_BC_MUL:
+		case OP_BC_UDIV:
+		case OP_BC_SDIV:
+		case OP_BC_UREM:
+		case OP_BC_SREM:
+		case OP_BC_SHL:
+		case OP_BC_LSHR:
+		case OP_BC_ASHR:
+		case OP_BC_AND:
+		case OP_BC_OR:
+		case OP_BC_XOR:
+		case OP_BC_ICMP_EQ:
+		case OP_BC_ICMP_NE:
+		case OP_BC_ICMP_UGT:
+		case OP_BC_ICMP_UGE:
+		case OP_BC_ICMP_ULT:
+		case OP_BC_ICMP_ULE:
+		case OP_BC_ICMP_SGT:
+		case OP_BC_ICMP_SGE:
+		case OP_BC_ICMP_SLT:
+		case OP_BC_ICMP_SLE:
+		case OP_BC_COPY:
+		case OP_BC_STORE:
 		    MAP(inst->u.binop[0]);
 		    MAP(inst->u.binop[1]);
 		    break;
-		case OP_SEXT:
-		case OP_ZEXT:
-		case OP_TRUNC:
+		case OP_BC_SEXT:
+		case OP_BC_ZEXT:
+		case OP_BC_TRUNC:
 		    MAP(inst->u.cast.source);
 		    break;
-		case OP_BRANCH:
+		case OP_BC_BRANCH:
 		    MAP(inst->u.branch.condition);
 		    break;
-		case OP_JMP:
+		case OP_BC_JMP:
 		    break;
-		case OP_RET:
+		case OP_BC_RET:
 		    MAP(inst->u.unaryop);
 		    break;
-		case OP_SELECT:
+		case OP_BC_SELECT:
 		    MAP(inst->u.three[0]);
 		    MAP(inst->u.three[1]);
 		    MAP(inst->u.three[2]);
 		    break;
-		case OP_CALL_API:/* fall-through */
-		case OP_CALL_DIRECT:
+		case OP_BC_CALL_API:/* fall-through */
+		case OP_BC_CALL_DIRECT:
 		{
 		    struct cli_bc_func *target = NULL;
-		    if (inst->opcode == OP_CALL_DIRECT) {
+		    if (inst->opcode == OP_BC_CALL_DIRECT) {
 			target = &bc->funcs[inst->u.ops.funcid];
 			if (inst->u.ops.funcid > bc->num_func) {
 			    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)
 			inst->u.ops.opsizes = NULL;
 		    for (k=0;k<inst->u.ops.numOps;k++) {
 			MAP(inst->u.ops.ops[k]);
-			if (inst->opcode == OP_CALL_DIRECT)
+			if (inst->opcode == OP_BC_CALL_DIRECT)
 			    inst->u.ops.opsizes[k] = typesize(bc, target->types[k]);
 			else
 			    inst->u.ops.opsizes[k] = 32; /*XXX*/
 		    }
 		    break;
 		}
-		case OP_LOAD:
+		case OP_BC_LOAD:
 		    MAP(inst->u.unaryop);
 		    break;
-		case OP_GEP1:
+		case OP_BC_GEP1:
 		    MAP(inst->u.binop[0]);
 		    MAP(inst->u.binop[1]);
 		    break;
-		case OP_GEP2:
+		case OP_BC_GEP2:
 		    MAP(inst->u.three[0]);
 		    MAP(inst->u.three[1]);
 		    MAP(inst->u.three[2]);
diff --git a/libclamav/bytecode_api_decl.c b/libclamav/bytecode_api_decl.c
index 4d88a2f..63680ec 100644
--- a/libclamav/bytecode_api_decl.c
+++ b/libclamav/bytecode_api_decl.c
@@ -28,7 +28,7 @@ uint32_t cli_bcapi_test0(struct cli_bc_ctx *ctx, struct foo*, uint32_t);
 uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
 int32_t cli_bcapi_read(struct cli_bc_ctx *ctx, uint8_t*, int32_t);
 int32_t cli_bcapi_seek(struct cli_bc_ctx *ctx, int32_t, uint32_t);
-uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const uint8_t*, uint32_t);
+uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
 uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
 
 static uint16_t cli_tmp0[]={32, 70, 32};
diff --git a/libclamav/bytecode_vm.c b/libclamav/bytecode_vm.c
index 5786027..aeb2626 100644
--- a/libclamav/bytecode_vm.c
+++ b/libclamav/bytecode_vm.c
@@ -298,7 +298,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
 
 #define BINOP(i) inst->u.binop[i]
 
-#define DEFINE_BINOP_HELPER(opc, OP, W0, W1, W2, W3, W4) \
+#define DEFINE_BINOP_BC_HELPER(opc, OP, W0, W1, W2, W3, W4) \
     case opc*5: {\
 		    uint8_t op0, op1, res;\
 		    int8_t sop0, sop1;\
@@ -350,8 +350,8 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
 		    break;\
 		}
 
-#define DEFINE_BINOP(opc, OP) DEFINE_BINOP_HELPER(opc, OP, WRITE8, WRITE8, WRITE16, WRITE32, WRITE64)
-#define DEFINE_ICMPOP(opc, OP) DEFINE_BINOP_HELPER(opc, OP, WRITE8, WRITE8, WRITE8, WRITE8, WRITE8)
+#define DEFINE_BINOP(opc, OP) DEFINE_BINOP_BC_HELPER(opc, OP, WRITE8, WRITE8, WRITE16, WRITE32, WRITE64)
+#define DEFINE_ICMPOP(opc, OP) DEFINE_BINOP_BC_HELPER(opc, OP, WRITE8, WRITE8, WRITE8, WRITE8, WRITE8)
 
 #define CHECK_OP(cond, msg) if((cond)) { cli_dbgmsg(msg); stop = CL_EBYTECODE; break;}
 
@@ -409,7 +409,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
 	default: CHECK_UNREACHABLE;\
     }
 
-#define DEFINE_OP_RET_N(OP, T, R0, W0) \
+#define DEFINE_OP_BC_RET_N(OP, T, R0, W0) \
     case OP: {\
 		T tmp;\
 		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
     do {
 	pc++;
 	switch (inst->interp_op) {
-	    DEFINE_BINOP(OP_ADD, res = op0 + op1);
-	    DEFINE_BINOP(OP_SUB, res = op0 - op1);
-	    DEFINE_BINOP(OP_MUL, res = op0 * op1);
+	    DEFINE_BINOP(OP_BC_ADD, res = op0 + op1);
+	    DEFINE_BINOP(OP_BC_SUB, res = op0 - op1);
+	    DEFINE_BINOP(OP_BC_MUL, res = op0 * op1);
 
-	    DEFINE_BINOP(OP_UDIV, CHECK_OP(op1 == 0, "bytecode attempted to execute udiv#0\n");
+	    DEFINE_BINOP(OP_BC_UDIV, CHECK_OP(op1 == 0, "bytecode attempted to execute udiv#0\n");
 			 res=op0/op1);
-	    DEFINE_BINOP(OP_SDIV, CHECK_OP(check_sdivops(sop0, sop1), "bytecode attempted to execute sdiv#0\n");
+	    DEFINE_BINOP(OP_BC_SDIV, CHECK_OP(check_sdivops(sop0, sop1), "bytecode attempted to execute sdiv#0\n");
 			 res=sop0/sop1);
-	    DEFINE_BINOP(OP_UREM, CHECK_OP(op1 == 0, "bytecode attempted to execute urem#0\n");
+	    DEFINE_BINOP(OP_BC_UREM, CHECK_OP(op1 == 0, "bytecode attempted to execute urem#0\n");
 			 res=op0 % op1);
-	    DEFINE_BINOP(OP_SREM, CHECK_OP(check_sdivops(sop0,sop1), "bytecode attempted to execute urem#0\n");
+	    DEFINE_BINOP(OP_BC_SREM, CHECK_OP(check_sdivops(sop0,sop1), "bytecode attempted to execute urem#0\n");
 			 res=sop0 % sop1);
 
-	    DEFINE_BINOP(OP_SHL, CHECK_OP(op1 > inst->type, "bytecode attempted to execute shl greater than bitwidth\n");
+	    DEFINE_BINOP(OP_BC_SHL, CHECK_OP(op1 > inst->type, "bytecode attempted to execute shl greater than bitwidth\n");
 			 res = op0 << op1);
-	    DEFINE_BINOP(OP_LSHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute lshr greater than bitwidth\n");
+	    DEFINE_BINOP(OP_BC_LSHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute lshr greater than bitwidth\n");
 			 res = op0 >> op1);
-	    DEFINE_BINOP(OP_ASHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute ashr greater than bitwidth\n");
+	    DEFINE_BINOP(OP_BC_ASHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute ashr greater than bitwidth\n");
 			 res = CLI_SRS(sop0, op1));
 
-	    DEFINE_BINOP(OP_AND, res = op0 & op1);
-	    DEFINE_BINOP(OP_OR, res = op0 | op1);
-	    DEFINE_BINOP(OP_XOR, res = op0 ^ op1);
+	    DEFINE_BINOP(OP_BC_AND, res = op0 & op1);
+	    DEFINE_BINOP(OP_BC_OR, res = op0 | op1);
+	    DEFINE_BINOP(OP_BC_XOR, res = op0 ^ op1);
 
-	    DEFINE_CASTOP(OP_SEXT,
+	    DEFINE_CASTOP(OP_BC_SEXT,
 			  CHOOSE(READ1(sres, inst->u.cast.source); res = sres ? ~0ull : 0,
 				 READ8(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
 				 READ16(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
 				 READ32(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
 				 READ64(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask)));
-	    DEFINE_CASTOP(OP_ZEXT,
+	    DEFINE_CASTOP(OP_BC_ZEXT,
 			  CHOOSE(READ1(res, inst->u.cast.source),
 				 READ8(res, inst->u.cast.source),
 				 READ16(res, inst->u.cast.source),
 				 READ32(res, inst->u.cast.source),
 				 READ64(res, inst->u.cast.source)));
-	    DEFINE_CASTOP(OP_TRUNC,
+	    DEFINE_CASTOP(OP_BC_TRUNC,
 			  CHOOSE(READ1(res, inst->u.cast.source),
 				 READ8(res, inst->u.cast.source),
 				 READ16(res, inst->u.cast.source),
 				 READ32(res, inst->u.cast.source),
 				 READ64(res, inst->u.cast.source)));
 
-	    DEFINE_OP(OP_BRANCH)
+	    DEFINE_OP(OP_BC_BRANCH)
 		stop = jump(func, (values[inst->u.branch.condition]&1) ?
 			  inst->u.branch.br_true : inst->u.branch.br_false,
 			  &bb, &inst, &bb_inst);
 		continue;
 
-	    DEFINE_OP(OP_JMP)
+	    DEFINE_OP(OP_BC_JMP)
 		stop = jump(func, inst->u.jump, &bb, &inst, &bb_inst);
 		continue;
 
-	    DEFINE_OP_RET_N(OP_RET*5, uint8_t, READ1, WRITE8);
-	    DEFINE_OP_RET_N(OP_RET*5+1, uint8_t, READ8, WRITE8);
-	    DEFINE_OP_RET_N(OP_RET*5+2, uint16_t, READ16, WRITE16);
-	    DEFINE_OP_RET_N(OP_RET*5+3, uint32_t, READ32, WRITE32);
-	    DEFINE_OP_RET_N(OP_RET*5+4, uint64_t, READ64, WRITE64);
-
-	    DEFINE_ICMPOP(OP_ICMP_EQ, res = (op0 == op1));
-	    DEFINE_ICMPOP(OP_ICMP_NE, res = (op0 != op1));
-	    DEFINE_ICMPOP(OP_ICMP_UGT, res = (op0 > op1));
-	    DEFINE_ICMPOP(OP_ICMP_UGE, res = (op0 >= op1));
-	    DEFINE_ICMPOP(OP_ICMP_ULT, res = (op0 < op1));
-	    DEFINE_ICMPOP(OP_ICMP_ULE, res = (op0 <= op1));
-	    DEFINE_ICMPOP(OP_ICMP_SGT, res = (sop0 > sop1));
-	    DEFINE_ICMPOP(OP_ICMP_SGE, res = (sop0 >= sop1));
-	    DEFINE_ICMPOP(OP_ICMP_SLE, res = (sop0 <= sop1));
-	    DEFINE_ICMPOP(OP_ICMP_SLT, res = (sop0 < sop1));
-
-	    case OP_SELECT*5:
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5, uint8_t, READ1, WRITE8);
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5+1, uint8_t, READ8, WRITE8);
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5+2, uint16_t, READ16, WRITE16);
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5+3, uint32_t, READ32, WRITE32);
+	    DEFINE_OP_BC_RET_N(OP_BC_RET*5+4, uint64_t, READ64, WRITE64);
+
+	    DEFINE_ICMPOP(OP_BC_ICMP_EQ, res = (op0 == op1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_NE, res = (op0 != op1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_UGT, res = (op0 > op1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_UGE, res = (op0 >= op1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_ULT, res = (op0 < op1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_ULE, res = (op0 <= op1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_SGT, res = (sop0 > sop1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_SGE, res = (sop0 >= sop1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_SLE, res = (sop0 <= sop1));
+	    DEFINE_ICMPOP(OP_BC_ICMP_SLT, res = (sop0 < sop1));
+
+	    case OP_BC_SELECT*5:
 	    {
 		uint8_t t0, t1, t2;
 		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
 		WRITE8(inst->dest, t0 ? t1 : t2);
 		break;
 	    }
-	    case OP_SELECT*5+1:
+	    case OP_BC_SELECT*5+1:
 	    {
 	        uint8_t t0, t1, t2;
 		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
 		WRITE8(inst->dest, t0 ? t1 : t2);
 		break;
 	    }
-	    case OP_SELECT*5+2:
+	    case OP_BC_SELECT*5+2:
 	    {
 	        uint8_t t0;
 		uint16_t t1, t2;
@@ -545,7 +545,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		WRITE16(inst->dest, t0 ? t1 : t2);
 		break;
 	    }
-	    case OP_SELECT*5+3:
+	    case OP_BC_SELECT*5+3:
 	    {
 	        uint8_t t0;
 		uint32_t t1, t2;
@@ -555,7 +555,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		WRITE32(inst->dest, t0 ? t1 : t2);
 		break;
 	    }
-	    case OP_SELECT*5+4:
+	    case OP_BC_SELECT*5+4:
 	    {
 	        uint8_t t0;
 		uint64_t t1, t2;
@@ -566,7 +566,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		break;
 	    }
 
-	    DEFINE_OP(OP_CALL_API) {
+	    DEFINE_OP(OP_BC_CALL_API) {
 		const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid];
 		int32_t res;
 		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
 		break;
 	    }
 
-	    DEFINE_OP(OP_CALL_DIRECT)
+	    DEFINE_OP(OP_BC_CALL_DIRECT)
 		CHECK_FUNCID(inst->u.ops.funcid);
 		func2 = &bc->funcs[inst->u.ops.funcid];
 		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
 		stack_depth++;
 		continue;
 
-	    case OP_COPY*5:
+	    case OP_BC_COPY*5:
 	    {
 		uint8_t op;
 		READ1(op, BINOP(0));
 		WRITE8(BINOP(1), op);
 		break;
 	    }
-	    case OP_COPY*5+1:
+	    case OP_BC_COPY*5+1:
 	    {
 		uint8_t op;
 		READ8(op, BINOP(0));
 		WRITE8(BINOP(1), op);
 		break;
 	    }
-	    case OP_COPY*5+2:
+	    case OP_BC_COPY*5+2:
 	    {
 		uint16_t op;
 		READ16(op, BINOP(0));
 		WRITE16(BINOP(1), op);
 		break;
 	    }
-	    case OP_COPY*5+3:
+	    case OP_BC_COPY*5+3:
 	    {
 		uint32_t op;
 		READ32(op, BINOP(0));
 		WRITE32(BINOP(1), op);
 		break;
 	    }
-	    case OP_COPY*5+4:
+	    case OP_BC_COPY*5+4:
 	    {
 		uint64_t op;
 		READ32(op, BINOP(0));
@@ -693,29 +693,29 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		break;
 	    }
 
-	    case OP_LOAD*5:
-	    case OP_LOAD*5+1:
+	    case OP_BC_LOAD*5:
+	    case OP_BC_LOAD*5+1:
 	    {
 		uint8_t *ptr;
 		READP(ptr, inst->u.unaryop);
 		WRITE8(inst->dest, (*ptr));
 		break;
 	    }
-	    case OP_LOAD*5+2:
+	    case OP_BC_LOAD*5+2:
 	    {
 		const union unaligned_16 *ptr;
 		READP(ptr, inst->u.unaryop);
 		WRITE16(inst->dest, (ptr->una_u16));
 		break;
 	    }
-	    case OP_LOAD*5+3:
+	    case OP_BC_LOAD*5+3:
 	    {
 		const union unaligned_32 *ptr;
 		READP(ptr, inst->u.unaryop);
 		WRITE32(inst->dest, (ptr->una_u32));
 		break;
 	    }
-	    case OP_LOAD*5+4:
+	    case OP_BC_LOAD*5+4:
 	    {
 		const union unaligned_64 *ptr;
 		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
 		break;
 	    }
 
-	    case OP_STORE*5:
+	    case OP_BC_STORE*5:
 	    {
 		uint8_t *ptr;
 		uint8_t v;
@@ -732,7 +732,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		*ptr = v;
 		break;
 	    }
-	    case OP_STORE*5+1:
+	    case OP_BC_STORE*5+1:
 	    {
 		uint8_t *ptr;
 		uint8_t v;
@@ -741,7 +741,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		*ptr = v;
 		break;
 	    }
-	    case OP_STORE*5+2:
+	    case OP_BC_STORE*5+2:
 	    {
 		union unaligned_16 *ptr;
 		uint16_t v;
@@ -750,7 +750,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		ptr->una_s16 = v;
 		break;
 	    }
-	    case OP_STORE*5+3:
+	    case OP_BC_STORE*5+3:
 	    {
 		union unaligned_32 *ptr;
 		uint32_t v;
@@ -759,7 +759,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		ptr->una_u32 = v;
 		break;
 	    }
-	    case OP_STORE*5+4:
+	    case OP_BC_STORE*5+4:
 	    {
 		union unaligned_64 *ptr;
 		uint64_t v;
@@ -768,7 +768,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
 		ptr->una_u64 = v;
 		break;
 	    }
-	    /* TODO: implement OP_GEP1, OP_GEP2, OP_GEPN */
+	    /* TODO: implement OP_BC_GEP1, OP_BC_GEP2, OP_BC_GEPN */
 	    default:
 		cli_errmsg("Opcode %u of type %u is not implemented yet!\n",
 			   inst->interp_op/5, inst->interp_op%5);
diff --git a/libclamav/c++/bytecode2llvm.cpp b/libclamav/c++/bytecode2llvm.cpp
index 2394d69..6202531 100644
--- a/libclamav/c++/bytecode2llvm.cpp
+++ b/libclamav/c++/bytecode2llvm.cpp
@@ -425,20 +425,20 @@ public:
 		    const struct cli_bc_inst *inst = &bb->insts[j];
 		    Value *Op0, *Op1, *Op2;
 		    // libclamav has already validated this.
-		    assert(inst->opcode < OP_INVALID && "Invalid opcode");
+		    assert(inst->opcode < OP_BC_INVALID && "Invalid opcode");
 		    switch (inst->opcode) {
-			case OP_JMP:
-			case OP_BRANCH:
-			case OP_CALL_API:
-			case OP_CALL_DIRECT:
-			case OP_ZEXT:
-			case OP_SEXT:
-			case OP_TRUNC:
-			case OP_GEP1:
-			case OP_GEP2:
-			case OP_GEPN:
-			case OP_STORE:
-			case OP_COPY:
+			case OP_BC_JMP:
+			case OP_BC_BRANCH:
+			case OP_BC_CALL_API:
+			case OP_BC_CALL_DIRECT:
+			case OP_BC_ZEXT:
+			case OP_BC_SEXT:
+			case OP_BC_TRUNC:
+			case OP_BC_GEP1:
+			case OP_BC_GEP2:
+			case OP_BC_GEPN:
+			case OP_BC_STORE:
+			case OP_BC_COPY:
 			    // these instructions represents operands differently
 			    break;
 			default:
@@ -459,23 +459,23 @@ public:
 		    }
 
 		    switch (inst->opcode) {
-			case OP_ADD:
+			case OP_BC_ADD:
 			    Store(inst->dest, Builder.CreateAdd(Op0, Op1));
 			    break;
-			case OP_SUB:
+			case OP_BC_SUB:
 			    Store(inst->dest, Builder.CreateSub(Op0, Op1));
 			    break;
-			case OP_MUL:
+			case OP_BC_MUL:
 			    Store(inst->dest, Builder.CreateMul(Op0, Op1));
 			    break;
-			case OP_UDIV:
+			case OP_BC_UDIV:
 			{
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
 			    InsertVerify(Bad, Fail, FHandler, F);
 			    Store(inst->dest, Builder.CreateUDiv(Op0, Op1));
 			    break;
 			}
-			case OP_SDIV:
+			case OP_BC_SDIV:
 			{
 			    //TODO: also verify Op0 == -1 && Op1 = INT_MIN
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
@@ -483,14 +483,14 @@ public:
 			    Store(inst->dest, Builder.CreateSDiv(Op0, Op1));
 			    break;
 			}
-			case OP_UREM:
+			case OP_BC_UREM:
 			{
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
 			    InsertVerify(Bad, Fail, FHandler, F);
 			    Store(inst->dest, Builder.CreateURem(Op0, Op1));
 			    break;
 			}
-			case OP_SREM:
+			case OP_BC_SREM:
 			{
 			    //TODO: also verify Op0 == -1 && Op1 = INT_MIN
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
@@ -498,46 +498,46 @@ public:
 			    Store(inst->dest, Builder.CreateSRem(Op0, Op1));
 			    break;
 			}
-			case OP_SHL:
+			case OP_BC_SHL:
 			    Store(inst->dest, Builder.CreateShl(Op0, Op1));
 			    break;
-			case OP_LSHR:
+			case OP_BC_LSHR:
 			    Store(inst->dest, Builder.CreateLShr(Op0, Op1));
 			    break;
-			case OP_ASHR:
+			case OP_BC_ASHR:
 			    Store(inst->dest, Builder.CreateAShr(Op0, Op1));
 			    break;
-			case OP_AND:
+			case OP_BC_AND:
 			    Store(inst->dest, Builder.CreateAnd(Op0, Op1));
 			    break;
-			case OP_OR:
+			case OP_BC_OR:
 			    Store(inst->dest, Builder.CreateOr(Op0, Op1));
 			    break;
-			case OP_XOR:
+			case OP_BC_XOR:
 			    Store(inst->dest, Builder.CreateXor(Op0, Op1));
 			    break;
-			case OP_TRUNC:
+			case OP_BC_TRUNC:
 			{
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
 			    const Type *Ty = mapType(func->types[inst->dest]);
 			    Store(inst->dest, Builder.CreateTrunc(Src,  Ty));
 			    break;
 			}
-			case OP_ZEXT:
+			case OP_BC_ZEXT:
 			{
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
 			    const Type *Ty = mapType(func->types[inst->dest]);
 			    Store(inst->dest, Builder.CreateZExt(Src,  Ty));
 			    break;
 			}
-			case OP_SEXT:
+			case OP_BC_SEXT:
 			{
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
 			    const Type *Ty = mapType(func->types[inst->dest]);
 			    Store(inst->dest, Builder.CreateSExt(Src,  Ty));
 			    break;
 			}
-			case OP_BRANCH:
+			case OP_BC_BRANCH:
 			{
 			    Value *Cond = convertOperand(func, inst, inst->u.branch.condition);
 			    BasicBlock *True = BB[inst->u.branch.br_true];
@@ -549,46 +549,46 @@ public:
 			    Builder.CreateCondBr(Cond, True, False);
 			    break;
 			}
-			case OP_JMP:
+			case OP_BC_JMP:
 			{
 			    BasicBlock *Jmp = BB[inst->u.jump];
 			    Builder.CreateBr(Jmp);
 			    break;
 			}
-			case OP_RET:
+			case OP_BC_RET:
 			    Builder.CreateRet(Op0);
 			    break;
-			case OP_ICMP_EQ:
+			case OP_BC_ICMP_EQ:
 			    Store(inst->dest, Builder.CreateICmpEQ(Op0, Op1));
 			    break;
-			case OP_ICMP_NE:
+			case OP_BC_ICMP_NE:
 			    Store(inst->dest, Builder.CreateICmpNE(Op0, Op1));
 			    break;
-			case OP_ICMP_UGT:
+			case OP_BC_ICMP_UGT:
 			    Store(inst->dest, Builder.CreateICmpUGT(Op0, Op1));
 			    break;
-			case OP_ICMP_UGE:
+			case OP_BC_ICMP_UGE:
 			    Store(inst->dest, Builder.CreateICmpUGE(Op0, Op1));
 			    break;
-			case OP_ICMP_ULT:
+			case OP_BC_ICMP_ULT:
 			    Store(inst->dest, Builder.CreateICmpULT(Op0, Op1));
 			    break;
-			case OP_ICMP_ULE:
+			case OP_BC_ICMP_ULE:
 			    Store(inst->dest, Builder.CreateICmpULE(Op0, Op1));
 			    break;
-			case OP_ICMP_SGT:
+			case OP_BC_ICMP_SGT:
 			    Store(inst->dest, Builder.CreateICmpSGT(Op0, Op1));
 			    break;
-			case OP_ICMP_SGE:
+			case OP_BC_ICMP_SGE:
 			    Store(inst->dest, Builder.CreateICmpSGE(Op0, Op1));
 			    break;
-			case OP_ICMP_SLT:
+			case OP_BC_ICMP_SLT:
 			    Store(inst->dest, Builder.CreateICmpSLT(Op0, Op1));
 			    break;
-			case OP_SELECT:
+			case OP_BC_SELECT:
 			    Store(inst->dest, Builder.CreateSelect(Op0, Op1, Op2));
 			    break;
-			case OP_COPY:
+			case OP_BC_COPY:
 			{
 			    Value *Dest = Values[inst->u.binop[1]];
 			    const PointerType *PTy = cast<PointerType>(Dest->getType());
@@ -596,7 +596,7 @@ public:
 			    Builder.CreateStore(Op0, Dest);
 			    break;
 			}
-			case OP_CALL_DIRECT:
+			case OP_BC_CALL_DIRECT:
 			{
 			    Function *DestF = Functions[inst->u.ops.funcid];
 			    SmallVector<Value*, 2> args;
@@ -610,7 +610,7 @@ public:
 			    Store(inst->dest, CI);
 			    break;
 			}
-			case OP_CALL_API:
+			case OP_BC_CALL_API:
 			{
 			    assert(inst->u.ops.funcid < cli_apicall_maxapi && "APICall out of range");
 			    const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid];
@@ -624,14 +624,14 @@ public:
 			    Store(inst->dest, Builder.CreateCall(DestF, args.begin(), args.end()));
 			    break;
 			}
-			case OP_GEP1:
+			case OP_BC_GEP1:
 			{
 			    Value *V = Values[inst->u.binop[0]];
 			    Value *Op = convertOperand(func, I32Ty, inst->u.binop[1]);
 			    Store(inst->dest, Builder.CreateGEP(V, Op));
 			    break;
 			}
-			case OP_GEP2:
+			case OP_BC_GEP2:
 			{
 			    std::vector<Value*> Idxs;
 			    Value *V = Values[inst->u.three[0]];
@@ -640,7 +640,7 @@ public:
 			    Store(inst->dest, Builder.CreateGEP(V, Idxs.begin(), Idxs.end()));
 			    break;
 			}
-			case OP_GEPN:
+			case OP_BC_GEPN:
 			{
 			    std::vector<Value*> Idxs;
 			    assert(inst->u.ops.numOps > 1);
@@ -650,7 +650,7 @@ public:
 			    Store(inst->dest, Builder.CreateGEP(V, Idxs.begin(), Idxs.end()));
 			    break;
 			}
-			case OP_STORE:
+			case OP_BC_STORE:
 			{
 			    Value *Dest = convertOperand(func, inst, inst->u.binop[1]);
 			    const Type *ETy = cast<PointerType>(Dest->getType())->getElementType();
@@ -658,7 +658,7 @@ public:
 						Dest);
 			    break;
 			}
-			case OP_LOAD:
+			case OP_BC_LOAD:
 			    Op0 = Builder.CreateLoad(Op0);
 			    Store(inst->dest, Op0);
 			    break;
@@ -858,7 +858,9 @@ int bytecode_init(void)
     if (llvm_is_multithreaded())
 	return 0;
     llvm_install_error_handler(llvm_error_handler);
+#ifdef CL_DEBUG
     sys::PrintStackTraceOnErrorSignal();
+#endif
     atexit(do_shutdown);
 
     llvm_start_multithreaded();
@@ -876,6 +878,7 @@ int cli_bytecode_init_jit(struct cli_all_bc *bcs)
     bcs->engine = new(std::nothrow) struct cli_bcengine;
     if (!bcs->engine)
 	return CL_EMEM;
+    bcs->engine->EE = 0;
     return 0;
 }
 
diff --git a/libclamav/clamav.h b/libclamav/clamav.h
index 80134f7..9d310e0 100644
--- a/libclamav/clamav.h
+++ b/libclamav/clamav.h
@@ -80,9 +80,10 @@ typedef enum {
 #define CL_DB_PUA_EXCLUDE   0x200
 #define CL_DB_COMPILED	    0x400   /* internal */
 #define CL_DB_DIRECTORY	    0x800   /* internal */
+#define CL_DB_BYTECODE      0x1000
 
 /* recommended db settings */
-#define CL_DB_STDOPT	    (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_CVDNOTMP)
+#define CL_DB_STDOPT	    (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_CVDNOTMP | CL_DB_BYTECODE)
 
 /* scan options */
 #define CL_SCAN_RAW			0x0
diff --git a/libclamav/clambc.h b/libclamav/clambc.h
index 4f10023..b2a468f 100644
--- a/libclamav/clambc.h
+++ b/libclamav/clambc.h
@@ -32,49 +32,49 @@ struct bytecode_metadata {
 #define BC_HEADER "ClamBC"
 
 enum bc_opcode {
-  OP_ADD=1,
-  OP_SUB,
-  OP_MUL,
-  OP_UDIV,
-  OP_SDIV,
-  OP_UREM,
-  OP_SREM,
-  OP_SHL,
-  OP_LSHR,
-  OP_ASHR,
-  OP_AND,
-  OP_OR,
-  OP_XOR,
+  OP_BC_ADD=1,
+  OP_BC_SUB,
+  OP_BC_MUL,
+  OP_BC_UDIV,
+  OP_BC_SDIV,
+  OP_BC_UREM,
+  OP_BC_SREM,
+  OP_BC_SHL,
+  OP_BC_LSHR,
+  OP_BC_ASHR,
+  OP_BC_AND,
+  OP_BC_OR,
+  OP_BC_XOR,
 
-  OP_TRUNC,
-  OP_SEXT,
-  OP_ZEXT,
+  OP_BC_TRUNC,
+  OP_BC_SEXT,
+  OP_BC_ZEXT,
 
-  OP_BRANCH,
-  OP_JMP,
-  OP_RET,
-  OP_RET_VOID,
+  OP_BC_BRANCH,
+  OP_BC_JMP,
+  OP_BC_RET,
+  OP_BC_RET_VOID,
 
-  OP_ICMP_EQ,
-  OP_ICMP_NE,
-  OP_ICMP_UGT,
-  OP_ICMP_UGE,
-  OP_ICMP_ULT,
-  OP_ICMP_ULE,
-  OP_ICMP_SGT,
-  OP_ICMP_SGE,
-  OP_ICMP_SLE,
-  OP_ICMP_SLT,
-  OP_SELECT,
-  OP_CALL_DIRECT,
-  OP_CALL_API,
-  OP_COPY,
-  OP_GEP1,
-  OP_GEP2,
-  OP_GEPN,
-  OP_STORE,
-  OP_LOAD,
-  OP_INVALID /* last */
+  OP_BC_ICMP_EQ,
+  OP_BC_ICMP_NE,
+  OP_BC_ICMP_UGT,
+  OP_BC_ICMP_UGE,
+  OP_BC_ICMP_ULT,
+  OP_BC_ICMP_ULE,
+  OP_BC_ICMP_SGT,
+  OP_BC_ICMP_SGE,
+  OP_BC_ICMP_SLE,
+  OP_BC_ICMP_SLT,
+  OP_BC_SELECT,
+  OP_BC_CALL_DIRECT,
+  OP_BC_CALL_API,
+  OP_BC_COPY,
+  OP_BC_GEP1,
+  OP_BC_GEP2,
+  OP_BC_GEPN,
+  OP_BC_STORE,
+  OP_BC_LOAD,
+  OP_BC_INVALID /* last */
 };
 
 static const unsigned char operand_counts[] = {
@@ -91,9 +91,9 @@ static const unsigned char operand_counts[] = {
   3,
   /* CALLs have variable number of operands */
   0, 0,
-  /* OP_COPY */
+  /* OP_BC_COPY */
   2,
-  /* OP_GEP1, OP_GEP2, OP_GEPN, OP_STORE, OP_LOAD*/
+  /* OP_BC_GEP1, OP_BC_GEP2, OP_BC_GEPN, OP_BC_STORE, OP_BC_LOAD*/
   2, 3, 0, 2, 1
 };
 
diff --git a/libclamav/dconf.c b/libclamav/dconf.c
index d3581b5..6f3d8a6 100644
--- a/libclamav/dconf.c
+++ b/libclamav/dconf.c
@@ -114,6 +114,11 @@ static struct dconf_module modules[] = {
     { "PHISHING",   "ENGINE",       PHISHING_CONF_ENGINE,   1 },
     { "PHISHING",   "ENTCONV",      PHISHING_CONF_ENTCONV,  1 },
 
+    { "BYTECODE",   "INTERPRETER",  BYTECODE_INTERPRETER,   1 },
+    { "BYTECODE",   "JIT X86",      BYTECODE_JIT_X86,       1 },
+    { "BYTECODE",   "JIT PPC",      BYTECODE_JIT_PPC,       1 },
+    { "BYTECODE",   "JIT ARM",      BYTECODE_JIT_ARM,       0 },
+
     { NULL,	    NULL,	    0,			    0 }
 };
 
@@ -161,6 +166,9 @@ struct cli_dconf *cli_dconf_init(void)
 	} else if(!strcmp(modules[i].mname, "PHISHING")) {
 	    if(modules[i].state)
 		dconf->phishing |= modules[i].bflag;
+	} else if(!strcmp(modules[i].mname, "BYTECODE")) {
+	    if (modules[i].state)
+		dconf->bytecode |= modules[i].bflag;
 	}
     }
 
@@ -170,7 +178,7 @@ struct cli_dconf *cli_dconf_init(void)
 void cli_dconf_print(struct cli_dconf *dconf)
 {
 	unsigned int pe = 0, elf = 0, macho = 0, arch = 0, doc = 0, mail = 0;
-	unsigned int other = 0, phishing = 0, i;
+	unsigned int other = 0, phishing = 0, i, bytecode=0;
 
 
     cli_dbgmsg("Dynamic engine configuration settings:\n");
@@ -247,6 +255,15 @@ void cli_dconf_print(struct cli_dconf *dconf)
 		cli_dbgmsg("   * Submodule %10s:\t%s\n", modules[i].sname, (dconf->phishing & modules[i].bflag) ? "On" : "** Off **");
 	    else
 		continue;
+	} else if(!strcmp(modules[i].mname, "BYTECODE")) {
+	    if(!bytecode) {
+		cli_dbgmsg("Module BYTECODE %s\n", dconf->phishing ? "On" : "Off");
+		bytecode = 1;
+	    }
+	    if(dconf->bytecode)
+		cli_dbgmsg("   * Submodule %10s:\t%s\n", modules[i].sname, (dconf->bytecode & modules[i].bflag) ? "On" : "** Off **");
+	    else
+		continue;
 	}
     }
 }
@@ -370,6 +387,15 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
 		break;
 	    }
 	}
+
+	if(!strncmp(buffer, "BYTECODE:", 9) && chkflevel(buffer, 2)) {
+	    if(sscanf(buffer + 9, "0x%x", &val) == 1) {
+		engine->dconf->bytecode = val;
+	    } else {
+		ret = CL_EMALFDB;
+		break;
+	    }
+	}
     }
 
     if(ret) {
diff --git a/libclamav/dconf.h b/libclamav/dconf.h
index 25d84d5..806c498 100644
--- a/libclamav/dconf.h
+++ b/libclamav/dconf.h
@@ -39,6 +39,7 @@ struct cli_dconf {
     uint32_t mail;
     uint32_t other;
     uint32_t phishing;
+    uint32_t bytecode;
 };
 
 /* PE flags */
@@ -103,6 +104,14 @@ struct cli_dconf {
 #define PHISHING_CONF_ENGINE   0x1
 #define PHISHING_CONF_ENTCONV  0x2
 
+/* Bytecode flags */
+#define BYTECODE_INTERPRETER 0x1
+#define BYTECODE_JIT_X86 0x2
+#define BYTECODE_JIT_PPC 0x4
+#define BYTECODE_JIT_ARM 0x8
+
+#define BYTECODE_ENGINE_MASK (BYTECODE_INTERPRETER | BYTECODE_JIT_X86 | BYTECODE_JIT_PPC | BYTECODE_JIT_ARM)
+
 #ifdef USE_MPOOL
 struct cli_dconf *cli_dconf_init(mpool_t *);
 #define cli_mpool_dconf_init(a) cli_dconf_init(a)
diff --git a/libclamav/others.h b/libclamav/others.h
index 1b3e91c..aee6ef3 100644
--- a/libclamav/others.h
+++ b/libclamav/others.h
@@ -39,6 +39,7 @@
 #include "dconf.h"
 #include "libclamunrar_iface/unrar_iface.h"
 #include "regex/regex.h"
+#include "bytecode.h"
 
 /*
  * CL_FLEVEL is the signature f-level specific to the current code and
@@ -175,6 +176,9 @@ struct cl_engine {
 
     /* Used for memory pools */
     mpool_t *mempool;
+
+    /* Used for bytecode */
+    struct cli_all_bc bcs;
 };
 
 struct cl_settings {
diff --git a/libclamav/readdb.c b/libclamav/readdb.c
index a91441b..f067d41 100644
--- a/libclamav/readdb.c
+++ b/libclamav/readdb.c
@@ -70,7 +70,8 @@
 #endif
 
 #include "mpool.h"
-
+#include "bytecode.h"
+#include "bytecode_priv.h"
 #ifdef CL_THREAD_SAFE
 #  include <pthread.h>
 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,
     return CL_SUCCESS;
 }
 
+static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
+{
+    int rc;
+    struct cli_all_bc *bcs = &engine->bcs;
+    struct cli_bc *bc;
+    if(!(engine->dconf->bytecode & BYTECODE_ENGINE_MASK)) {
+	return CL_SUCCESS;
+    }
+    bcs->all_bcs = cli_realloc2(bcs->all_bcs, sizeof(*bcs->all_bcs)*(bcs->count+1));
+    if (!bcs->all_bcs) {
+	cli_errmsg("cli_loadcbc: Can't allocate memory for bytecode entry\n");
+	return CL_EMEM;
+    }
+    bcs->count++;
+    bc = &bcs->all_bcs[bcs->count-1];
+    rc = cli_bytecode_load(bc, fs, dbio);
+    if (rc != CL_SUCCESS) {
+	fprintf(stderr,"Unable to load %s bytecode: %s\n", dbname, cl_strerror(rc));
+	return rc;
+    }
+    return CL_SUCCESS;
+}
+
 #define FTM_TOKENS 8
 static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio)
 {
@@ -1608,7 +1632,11 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo
 	    ret = cli_loadldb(fs, engine, signo, options | CL_DB_PUA_MODE, dbio, dbname);
 	else
 	    skipped = 1;
-
+    } else if(cli_strbcasestr(filename, ".cbc")) {
+	if(options & CL_DB_BYTECODE)
+	    ret = cli_loadcbc(fs, engine, signo, options, dbio, dbname);
+	else
+	    skipped = 1;
     } else if(cli_strbcasestr(dbname, ".sdb")) {
 	ret = cli_loadndb(fs, engine, signo, 1, options, dbio, dbname);
 
@@ -1782,10 +1810,17 @@ int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, uns
 	if((ret = phishing_init(engine)))
 	    return ret;
 
+    if((dboptions & CL_DB_BYTECODE) && !engine->bcs.engine && (engine->dconf->bytecode & BYTECODE_ENGINE_MASK)) {
+	if((ret = cli_bytecode_init(&engine->bcs)))
+	    return ret;
+    } else {
+	cli_dbgmsg("Bytecode engine disabled\n");
+    }
+
     engine->dboptions |= dboptions;
 
     switch(sb.st_mode & S_IFMT) {
-	case S_IFREG: 
+	case S_IFREG:
 	    ret = cli_load(path, engine, signo, dboptions, NULL);
 	    break;
 
@@ -2092,6 +2127,14 @@ int cl_engine_free(struct cl_engine *engine)
 	mpool_free(engine->mempool, metah);
     }
 
+    if(engine->dconf->bytecode & BYTECODE_ENGINE_MASK) {
+	unsigned i;
+	if (engine->bcs.all_bcs)
+	    for(i=0;i<engine->bcs.count;i++)
+		cli_bytecode_destroy(&engine->bcs.all_bcs[i]);
+	cli_bytecode_done(&engine->bcs);
+	free(engine->bcs.all_bcs);
+    }
     if(engine->dconf->phishing & PHISHING_CONF_ENGINE)
 	phishing_done(engine);
     if(engine->dconf)
@@ -2168,6 +2211,12 @@ int cl_engine_compile(struct cl_engine *engine)
     cli_dconf_print(engine->dconf);
     mpool_flush(engine->mempool);
 
+    /* Compile bytecode */
+    if((ret = cli_bytecode_prepare(&engine->bcs))) {
+	fprintf(stderr,"Unable to compile/load bytecode: %s\n", cl_strerror(ret));
+	return ret;
+    }
+
     engine->dboptions |= CL_DB_COMPILED;
     return CL_SUCCESS;
 }
diff --git a/libclamav/readdb.h b/libclamav/readdb.h
index 696e55e..1e09936 100644
--- a/libclamav/readdb.h
+++ b/libclamav/readdb.h
@@ -47,6 +47,7 @@
 	cli_strbcasestr(ext, ".pdb")   ||	\
 	cli_strbcasestr(ext, ".gdb")   ||	\
 	cli_strbcasestr(ext, ".wdb")   ||	\
+	cli_strbcasestr(ext, ".cbc")   ||	\
 	cli_strbcasestr(ext, ".ftm")   ||	\
 	cli_strbcasestr(ext, ".ign")   ||	\
 	cli_strbcasestr(ext, ".cfg")   ||	\
diff --git a/shared/optparser.c b/shared/optparser.c
index 388df25..a63a778 100644
--- a/shared/optparser.c
+++ b/shared/optparser.c
@@ -233,7 +233,7 @@ const struct clam_option clam_options[] = {
     { "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" },
 
     /* Scan options */
-
+    { "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" },
     { "DetectPUA", "detect-pua", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Detect Potentially Unwanted Applications.", "yes" },
 
     { "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" },
diff --git a/unit_tests/check_bytecode.c b/unit_tests/check_bytecode.c
index 0016d5f..5c40b3a 100644
--- a/unit_tests/check_bytecode.c
+++ b/unit_tests/check_bytecode.c
@@ -129,6 +129,14 @@ START_TEST (test_div0)
 }
 END_TEST
 
+START_TEST (test_lsig)
+{
+    cl_init(CL_INIT_DEFAULT);
+    runtest("input/lsig.cbc", 0, CL_EBYTECODE, 0);
+//  runtest("input/lsig.cbc", 0, CL_EBYTECODE, 1);
+}
+END_TEST
+
 Suite *test_bytecode_suite(void)
 {
     Suite *s = suite_create("bytecode");

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list