[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