[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:52:59 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit c3c97d4af26c1902a9518a7ba31a839e8c598b36
Author: Török Edvin <edwin at clamav.net>
Date:   Mon Jun 29 15:01:01 2009 +0300

    Add support for branches.

diff --git a/libclamav/bytecode.c b/libclamav/bytecode.c
index c887f87..5e90716 100644
--- a/libclamav/bytecode.c
+++ b/libclamav/bytecode.c
@@ -30,18 +30,29 @@
 #include "readdb.h"
 #include <string.h>
 
+typedef uint32_t operand_t;
+
 struct cli_bc_varop {
     uint8_t numOps;
-    uint16_t* ops;
+    operand_t* ops;
+};
+
+struct branch {
+    operand_t condition;
+    struct cli_bc_bb *br_true;
+    struct cli_bc_bb *br_false;
 };
 
 struct cli_bc_inst {
     enum bc_opcode opcode;
     uint16_t type;
     union {
-	uint16_t unaryop;
-	uint16_t binop[2];
+	operand_t unaryop;
+	operand_t binop[2];
+	operand_t three[3];
 	struct cli_bc_varop ops;
+	struct branch branch;
+	struct cli_bc_bb *jump;
     } u;
 };
 
@@ -148,7 +159,7 @@ static inline unsigned readFixedNumber(const unsigned char *p, unsigned *off,
     return n;
 }
 
-static inline char *readData(const unsigned char *p, unsigned *off, unsigned len, char *ok)
+static inline unsigned char *readData(const unsigned char *p, unsigned *off, unsigned len, char *ok, unsigned *datalen)
 {
     unsigned char *dat, *q;
     unsigned l, newoff, i;
@@ -184,10 +195,22 @@ static inline char *readData(const unsigned char *p, unsigned *off, unsigned len
 	*q++ = v;
     }
     *off = newoff;
+    *datalen = l;
     return dat;
 }
 
-static int parseHeader(struct cli_bc *bc, char *buffer)
+static inline char *readString(const unsigned char *p, unsigned *off, unsigned len, char *ok)
+{
+    unsigned stringlen;
+    char *str = (char*)readData(p, off, len, ok, &stringlen);
+    if (*ok && stringlen && str[stringlen-1] != '\0') {
+	free(str);
+	*ok = 0;
+	return NULL;
+    }
+    return str;
+}
+static int parseHeader(struct cli_bc *bc, unsigned char *buffer)
 {
     uint64_t magic1;
     unsigned magic2;
@@ -198,7 +221,7 @@ static int parseHeader(struct cli_bc *bc, char *buffer)
 	return CL_EMALFDB;
     }
     offset = sizeof(BC_HEADER)-1;
-    len = strlen(buffer);
+    len = strlen((const char*)buffer);
     flevel = readNumber(buffer, &offset, len, &ok);
     if (!ok) {
 	cli_errmsg("Unable to parse functionality level in bytecode header\n");
@@ -210,15 +233,15 @@ static int parseHeader(struct cli_bc *bc, char *buffer)
     }
     // Optimistic parsing, check for error only at the end.
     bc->verifier = readNumber(buffer, &offset, len, &ok);
-    bc->sigmaker = readData(buffer, &offset, len, &ok);
+    bc->sigmaker = readString(buffer, &offset, len, &ok);
     bc->id = readNumber(buffer, &offset, len, &ok);
     bc->metadata.maxStack = readNumber(buffer, &offset, len, &ok);
     bc->metadata.maxMem = readNumber(buffer, &offset, len, &ok);
     bc->metadata.maxTime = readNumber(buffer, &offset, len, &ok);
-    bc->metadata.targetExclude = readData(buffer, &offset, len, &ok);
+    bc->metadata.targetExclude = readString(buffer, &offset, len, &ok);
     bc->num_func = readNumber(buffer, &offset, len, &ok);
     if (!ok) {
-	cli_errmsg("Invalid bytecode header\n", offset);
+	cli_errmsg("Invalid bytecode header at %u\n", offset);
 	return CL_EMALFDB;
     }
     magic1 = readNumber(buffer, &offset, len, &ok);
@@ -243,7 +266,7 @@ static int parseHeader(struct cli_bc *bc, char *buffer)
     return CL_SUCCESS;
 }
 
-static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, char *buffer)
+static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *buffer)
 {
     char ok=1;
     unsigned offset, len, all_locals=0, i;
@@ -255,7 +278,7 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, char *buffer)
 	return CL_EMALFDB;
     }
     func = &bc->funcs[fn];
-    len = strlen(buffer);
+    len = strlen((const char*)buffer);
 
     if (buffer[0] != 'A') {
 	cli_errmsg("Invalid function arguments header: %c\n", buffer[0]);
@@ -304,20 +327,32 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, char *buffer)
     return CL_SUCCESS;
 }
 
-static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, char *buffer)
+static struct cli_bc_bb *readBBID(struct cli_bc_func *func, const unsigned char *buffer, unsigned *off, unsigned len, char *ok) {
+    unsigned id = readNumber(buffer, off, len, ok);
+    if (!id || id >= func->numBB) {
+	cli_errmsg("Basic block ID out of range: %u\n", id);
+	*ok = 0;
+    }
+    if (!*ok)
+	return NULL;
+    return &func->BB[id];
+}
+
+static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char *buffer)
 {
     char ok=1;
     unsigned offset, len, last = 0;
     struct cli_bc_bb *BB;
+    struct cli_bc_func *bcfunc = &bc->funcs[func];
     struct cli_bc_inst inst;
 
-    if (bb >= bc->funcs[func].numBB) {
+    if (bb >= bcfunc->numBB) {
 	cli_errmsg("Found too many basic blocks\n");
 	return CL_EMALFDB;
     }
 
-    BB = &bc->funcs[func].BB[bb];
-    len = strlen(buffer);
+    BB = &bcfunc->BB[bb];
+    len = strlen((const char*) buffer);
     if (buffer[0] != 'B') {
 	cli_errmsg("Invalid basic block header: %c\n", buffer[0]);
 	return CL_EMALFDB;
@@ -344,26 +379,42 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, char *buffer)
 	    cli_errmsg("Invalid opcode: %u\n", inst.opcode);
 	    return CL_EMALFDB;
 	}
-	numOp = operand_counts[inst.opcode];
-	switch (numOp) {
-	    case 1:
-		inst.u.unaryop = readOperand(buffer, &offset, len, &ok);
+	switch (inst.opcode) {
+	    case OP_JMP:
+		inst.u.jump = readBBID(bcfunc, buffer, &offset, len, &ok);
 		break;
-	    case 2:
-		inst.u.binop[0] = readOperand(buffer, &offset, len, &ok);
-		inst.u.binop[1] = readOperand(buffer, &offset, len, &ok);
+	    case OP_BRANCH:
+		inst.u.branch.condition = readOperand(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;
 	    default:
-		inst.u.ops.numOps = numOp;
-		inst.u.ops.ops = cli_calloc(numOp, sizeof(*inst.u.ops.ops));
-		if (!inst.u.ops.ops) {
-		    cli_errmsg("Out of memory allocating operands\n");
-		    return CL_EMALFDB;
-		}
-		for (i=0;i<numOp;i++) {
-		    inst.u.ops.ops[i] = readOperand(buffer, &offset, len, &ok);
+		numOp = operand_counts[inst.opcode];
+		switch (numOp) {
+		    case 1:
+			inst.u.unaryop = readOperand(buffer, &offset, len, &ok);
+			break;
+		    case 2:
+			inst.u.binop[0] = readOperand(buffer, &offset, len, &ok);
+			inst.u.binop[1] = readOperand(buffer, &offset, len, &ok);
+			break;
+		    case 3:
+			inst.u.three[0] = readOperand(buffer, &offset, len, &ok);
+			inst.u.three[1] = readOperand(buffer, &offset, len, &ok);
+			inst.u.three[2] = readOperand(buffer, &offset, len, &ok);
+			break;
+		    default:
+			inst.u.ops.numOps = numOp;
+			inst.u.ops.ops = cli_calloc(numOp, sizeof(*inst.u.ops.ops));
+			if (!inst.u.ops.ops) {
+			    cli_errmsg("Out of memory allocating operands\n");
+			    return CL_EMALFDB;
+			}
+			for (i=0;i<numOp;i++) {
+			    inst.u.ops.ops[i] = readOperand(buffer, &offset, len, &ok);
+			}
+			break;
 		}
-		break;
 	}
 	if (!ok) {
 	    cli_errmsg("Invalid instructions or operands\n");
@@ -415,7 +466,7 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio)
 	cli_chomp(buffer);
 	switch (state) {
 	    case PARSE_BC_HEADER:
-		rc = parseHeader(bc, buffer);
+		rc = parseHeader(bc, (unsigned char*)buffer);
 		if (rc == CL_BREAK) /* skip */
 		    return CL_SUCCESS;
 		if (rc != CL_SUCCESS)
@@ -423,14 +474,14 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio)
 		state = PARSE_FUNC_HEADER;
 		break;
 	    case PARSE_FUNC_HEADER:
-		rc = parseFunctionHeader(bc, current_func, buffer);
+		rc = parseFunctionHeader(bc, current_func, (unsigned char*)buffer);
 		if (rc != CL_SUCCESS)
 		    return rc;
 		bb = 0;
 		state = PARSE_BB;
 		break;
 	    case PARSE_BB:
-		rc = parseBB(bc, current_func, bb++, buffer);
+		rc = parseBB(bc, current_func, bb++, (unsigned char*)buffer);
 		if (rc != CL_SUCCESS)
 		    return rc;
 		if (bb >= bc->funcs[current_func].numBB) {
@@ -462,7 +513,7 @@ void cli_bytecode_destroy(struct cli_bc *bc)
 	    struct cli_bc_bb *BB = &f->BB[j];
 	    for(k=0;k<BB->numInsts;k++) {
 		struct cli_bc_inst *i = &BB->insts[k];
-		if (operand_counts[i->opcode] > 2)
+		if (operand_counts[i->opcode] > 3)
 		    free(i->u.ops.ops);
 	    }
 	    free(BB->insts);
diff --git a/libclamav/clambc.h b/libclamav/clambc.h
index 93cd1eb..6b5dcfe 100644
--- a/libclamav/clambc.h
+++ b/libclamav/clambc.h
@@ -49,6 +49,9 @@ enum bc_opcode {
   OP_TRUNC,
   OP_SEXT,
   OP_ZEXT,
+
+  OP_BRANCH,
+  OP_JMP,
   OP_RET,
 
   OP_ICMP_EQ,
@@ -71,8 +74,8 @@ static const unsigned char operand_counts[] = {
   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
   /* TRUNC -> ZEXT */
   2, 2, 2,
-  /* RET */
-  1,
+  /* BRANCH, JMP, RET */
+  3, 1, 1,
   /* ICMP */
   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
   /* SELECT */

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list