[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