[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 00:57:28 UTC 2010
The following commit has been merged in the debian/unstable branch:
commit 8c0933ceabe6574561ad1129282ae8a34e3f0988
Author: Török Edvin <edwin at clamav.net>
Date: Wed Jul 8 12:45:06 2009 +0300
Implement more opcodes and checking.
diff --git a/clambc/bcrun.c b/clambc/bcrun.c
index 52ac64e..858558b 100644
--- a/clambc/bcrun.c
+++ b/clambc/bcrun.c
@@ -126,5 +126,6 @@ int main(int argc, char *argv[])
cli_bytecode_destroy(bc);
free(bc);
optfree(opts);
+ printf("Exiting\n");
return 0;
}
diff --git a/libclamav/bytecode.c b/libclamav/bytecode.c
index b32dce8..c6b9fce 100644
--- a/libclamav/bytecode.c
+++ b/libclamav/bytecode.c
@@ -67,12 +67,12 @@ int cli_bytecode_context_setfuncid(struct cli_bc_ctx *ctx, struct cli_bc *bc, un
ctx->bc = bc;
ctx->numParams = func->numArgs;
ctx->funcid = funcid;
+ ctx->values = cli_malloc(sizeof(*ctx->values)*(func->numArgs+1));
+ if (!ctx->values) {
+ cli_errmsg("bytecode: error allocating memory for parameters\n");
+ return CL_EMEM;
+ }
if (func->numArgs) {
- ctx->values = cli_malloc(sizeof(*ctx->values)*func->numArgs);
- if (!ctx->values) {
- cli_errmsg("bytecode: error allocating memory for parameters\n");
- return CL_EMEM;
- }
ctx->operands = cli_malloc(sizeof(*ctx->operands)*func->numArgs);
if (!ctx->operands) {
cli_errmsg("bytecode: error allocating memory for parameters\n");
@@ -81,7 +81,7 @@ int cli_bytecode_context_setfuncid(struct cli_bc_ctx *ctx, struct cli_bc *bc, un
}
for (i=0;i<func->numArgs;i++) {
ctx->values[i].ref = MAX_OP;
- ctx->operands[i] = i;
+ ctx->operands[i+1] = i;
}
return CL_SUCCESS;
}
@@ -168,7 +168,7 @@ static inline operand_t readOperand(struct cli_bc_func *func, unsigned char *p,
{
uint64_t v;
unsigned numValues = func->numArgs + func->numInsts + func->numConstants;
- if ((p[*off]&0xf0) == 0x40) {
+ if ((p[*off]&0xf0) == 0x40 || p[*off] == 0x50) {
p[*off] |= 0x20;
/* TODO: unique constants */
func->values = cli_realloc2(func->values, (numValues+1)*sizeof(*func->values));
@@ -229,8 +229,10 @@ static inline unsigned char *readData(const unsigned char *p, unsigned *off, uns
}
(*off)++;
l = readNumber(p, off, len, ok);
- if (!l)
+ if (!l) {
+ *datalen = l;
return NULL;
+ }
newoff = *off + l;
if (newoff > len) {
cli_errmsg("Line ended while reading data\n");
@@ -610,7 +612,6 @@ int cli_bytecode_run(struct cli_bc *bc, struct cli_bc_ctx *ctx)
{
struct cli_bc_inst inst;
struct cli_bc_func func;
- struct cli_bc_value value;
unsigned i;
if (!ctx || !ctx->bc || !ctx->func)
return CL_ENULLARG;
@@ -624,13 +625,14 @@ int cli_bytecode_run(struct cli_bc *bc, struct cli_bc_ctx *ctx)
}
memset(&func, 0, sizeof(func));
func.values = ctx->values;
+ func.numInsts = 1;
inst.opcode = OP_CALL_DIRECT;
inst.type = 0;/* TODO: support toplevel functions with return values */
inst.u.ops.numOps = ctx->numParams;
inst.u.ops.funcid = ctx->funcid;
inst.u.ops.ops = ctx->operands;
- return cli_vm_execute(ctx->bc, ctx, &func, &inst, &value);
+ return cli_vm_execute(ctx->bc, ctx, &func, &inst, func.values);
}
void cli_bytecode_destroy(struct cli_bc *bc)
diff --git a/libclamav/bytecode_vm.c b/libclamav/bytecode_vm.c
index 9ae4805..ec1b251 100644
--- a/libclamav/bytecode_vm.c
+++ b/libclamav/bytecode_vm.c
@@ -57,6 +57,35 @@ struct stack_entry {
unsigned bb_inst;
};
+
+/* Get the operand of a binary operator, upper bits
+ * (beyond the size of the operand) may have random values.
+ * Use this when the active bits of the result of a binop are the same
+ * regardless of the state of the inactive (high) bits of their operands.
+ * For example (a + b)&mask == ((a&mask) + (b&mask))
+ * but (a / b)&mask != ((a&mask) / (b&mask))
+ * */
+#define BINOPNOMOD(i) (values[inst->u.binop[i]].v)
+#define UNOPNOMOD(i) (values[inst->u.binop[i]].v)
+
+/* get the operand of a binary operator, upper bits are cleared */
+#define BINOP(i) (BINOPNOMOD(i)&((1 << inst->type)-1))
+#define UNOP(x) (UNOPNOMOD(i)&((1 << inst->type)-1))
+
+/* get the operand as a signed value */
+#define SIGNEXT(a) CLI_SRS(((int64_t)(a)) << (64-inst->type), (64-inst->type))
+#define BINOPS(i) SIGNEXT(BINOPNOMOD(i))
+
+static void jump(struct cli_bc_func *func, uint16_t bbid, struct cli_bc_bb **bb, struct cli_bc_inst **inst,
+ struct cli_bc_value **value, unsigned *bb_inst)
+{
+ CHECK_GT(func->numBB, bbid);
+ *bb = &func->BB[bbid];
+ *inst = (*bb)->insts;
+ *value = &func->values[*inst - func->allinsts];
+ *bb_inst = 0;
+}
+
int cli_vm_execute(struct cli_bc *bc, struct cli_bc_ctx *ctx, struct cli_bc_func *func, struct cli_bc_inst *inst, struct cli_bc_value *value)
{
unsigned i, stack_depth=0, bb_inst=0, stop=0;
@@ -68,33 +97,93 @@ int cli_vm_execute(struct cli_bc *bc, struct cli_bc_ctx *ctx, struct cli_bc_func
do {
switch (inst->opcode) {
case OP_ADD:
- values->v = values[inst->u.binop[0]].v + values[inst->u.binop[1]].v;
+ values->v = BINOPNOMOD(0) + BINOPNOMOD(1);
break;
case OP_SUB:
- values->v = values[inst->u.binop[0]].v - values[inst->u.binop[1]].v;
+ values->v = BINOPNOMOD(0) - BINOPNOMOD(1);
break;
case OP_MUL:
- values->v = values[inst->u.binop[0]].v * values[inst->u.binop[1]].v;
+ values->v = BINOPNOMOD(0) * BINOPNOMOD(1);
+ break;
+ case OP_UDIV:
+ {
+ uint64_t d = BINOP(1);
+ if (UNLIKELY(!d))
+ return CL_EBYTECODE;
+ values->v = BINOP(0) / d;
+ break;
+ }
+ case OP_SDIV:
+ {
+ int64_t a = BINOPS(0);
+ int64_t b = BINOPS(1);
+ if (UNLIKELY(b == 0 || (b == -1 && a == (-9223372036854775807LL-1LL))))
+ return CL_EBYTECODE;
+ values->v = a / b;
+ break;
+ }
+ case OP_UREM:
+ {
+ uint64_t d = BINOP(1);
+ if (UNLIKELY(!d))
+ return CL_EBYTECODE;
+ values->v = BINOP(0) % d;
+ break;
+ }
+ case OP_SREM:
+ {
+ int64_t a = BINOPS(0);
+ int64_t b = BINOPS(1);
+ if (UNLIKELY(b == 0 || (b == -1 && (a == -9223372036854775807LL-1LL))))
+ return CL_EBYTECODE;
+ values->v = a % b;
+ break;
+ }
+ case OP_SHL:
+ values->v = BINOPNOMOD(0) << BINOP(1);
break;
+ case OP_LSHR:
+ values->v = BINOP(0) >> BINOP(1);
+ break;
+ case OP_ASHR:
+ {
+ int64_t v = BINOPS(0);
+ values->v = CLI_SRS(v, BINOP(1));
+ break;
+ }
case OP_AND:
- values->v = values[inst->u.binop[0]].v & values[inst->u.binop[1]].v;
+ values->v = BINOPNOMOD(0) & BINOPNOMOD(1);
break;
case OP_OR:
- values->v = values[inst->u.binop[0]].v | values[inst->u.binop[1]].v;
+ values->v = BINOPNOMOD(0) | BINOPNOMOD(1);
break;
case OP_XOR:
- values->v = values[inst->u.binop[0]].v ^ values[inst->u.binop[1]].v;
+ values->v = BINOPNOMOD(0) ^ BINOPNOMOD(1);
+ break;
+ case OP_SEXT:
+ values->v = SIGNEXT(values[inst->u.cast.source].v);
break;
- case OP_ZEXT:
case OP_TRUNC:
+ /* fall-through */
+ case OP_ZEXT:
values->v = values[inst->u.cast.source].v & values[inst->u.cast.mask].v;
break;
+ case OP_BRANCH:
+ jump(func, (values[inst->u.branch.condition].v&1) ?
+ inst->u.branch.br_true : inst->u.branch.br_false,
+ &bb, &inst, &value, &bb_inst);
+ continue;
+ case OP_JMP:
+ jump(func, inst->u.jump, &bb, &inst, &value, &bb_inst);
+ continue;
case OP_RET:
CHECK_GT(stack_depth, 0);
stack_depth--;
value = stack[stack_depth].ret;
- value->v = values[inst->u.unaryop].v;
func = stack[stack_depth].func;
+ CHECK_GT(func->values + func->numArgs+func->numInsts+func->numConstants, value);
+ CHECK_GT(value, &func->values[-1]);
+ value->v = values[inst->u.unaryop].v;
values = func->values;
if (!stack[stack_depth].bb) {
stop = CL_BREAK;
@@ -106,10 +195,37 @@ int cli_vm_execute(struct cli_bc *bc, struct cli_bc_ctx *ctx, struct cli_bc_func
inst = &bb->insts[bb_inst];
break;
case OP_ICMP_EQ:
- value->v = values[inst->u.binop[0]].v == values[inst->u.binop[1]].v ? 1 : 0;
+ value->v = BINOP(0) == BINOP(1) ? 1 : 0;
+ break;
+ case OP_ICMP_NE:
+ value->v = BINOP(0) != BINOP(1) ? 1 : 0;
+ break;
+ case OP_ICMP_UGT:
+ value->v = BINOP(0) > BINOP(1) ? 1 : 0;
+ break;
+ case OP_ICMP_UGE:
+ value->v = BINOP(0) >= BINOP(1) ? 1 : 0;
+ break;
+ case OP_ICMP_ULT:
+ value->v = BINOP(0) < BINOP(1) ? 1 : 0;
+ break;
+ case OP_ICMP_ULE:
+ value->v = BINOP(0) <= BINOP(1) ? 1 : 0;
+ break;
+ case OP_ICMP_SGT:
+ value->v = BINOPS(0) > BINOPS(1) ? 1 : 0;
+ break;
+ case OP_ICMP_SGE:
+ value->v = BINOPS(0) >= BINOPS(1) ? 1 : 0;
+ break;
+ case OP_ICMP_SLE:
+ value->v = BINOPS(0) <= BINOPS(1) ? 1 : 0;
+ break;
+ case OP_ICMP_SLT:
+ value->v = BINOPS(0) < BINOPS(1) ? 1 : 0;
break;
case OP_SELECT:
- values->v = values[inst->u.three[0]].v ?
+ values->v = (values[inst->u.three[0]].v&1) ?
values[inst->u.three[1]].v : values[inst->u.three[2]].v;
break;
case OP_CALL_DIRECT:
@@ -126,13 +242,15 @@ int cli_vm_execute(struct cli_bc *bc, struct cli_bc_ctx *ctx, struct cli_bc_func
stack[stack_depth].bb = bb;
stack[stack_depth].bb_inst = bb_inst;
stack_depth++;
+ cli_dbgmsg("Executing %d\n", inst->u.ops.funcid);
func = func2;
values = func->values;
CHECK_GT(func->numBB, 0);
- bb = &func->BB[0];
- inst = &bb->insts[0];
- bb_inst = 0;
+ jump(func, 0, &bb, &inst, &value, &bb_inst);
continue;
+ case OP_COPY:
+ BINOPNOMOD(1) = BINOPNOMOD(0);
+ break;
default:
cli_errmsg("Opcode %u is not implemented yet!\n", inst->opcode);
stop = CL_EARG;
diff --git a/libclamav/clamav.h b/libclamav/clamav.h
index 1dc5e38..b64dbaa 100644
--- a/libclamav/clamav.h
+++ b/libclamav/clamav.h
@@ -65,7 +65,8 @@ typedef enum {
CL_EMAXREC,
CL_EMAXSIZE,
CL_EMAXFILES,
- CL_EFORMAT
+ CL_EFORMAT,
+ CL_EBYTECODE
} cl_error_t;
/* db options */
diff --git a/libclamav/others.c b/libclamav/others.c
index a7e5b7c..ac2cc9d 100644
--- a/libclamav/others.c
+++ b/libclamav/others.c
@@ -259,6 +259,8 @@ const char *cl_strerror(int clerror)
return "CL_EMAXFILES";
case CL_EFORMAT:
return "CL_EFORMAT: Bad format or broken data";
+ case CL_EBYTECODE:
+ return "CL_EBYTECODE: error during bytecode execution";
default:
return "Unknown error code";
}
--
Debian repository for ClamAV
More information about the Pkg-clamav-commits
mailing list