diff mbox

[02/17] big-shift: mark out-of-range OP_{ASR,LSR,SHL} as tainted

Message ID 20180721143322.99163-3-luc.vanoostenryck@gmail.com (mailing list archive)
State Mainlined, archived
Headers show

Commit Message

Luc Van Oostenryck July 21, 2018, 2:33 p.m. UTC
Some undefined operations, like shifting by an amount bigger
than the size, should not raise a warning during the optimization
phase because the corresponding warning has already been issued
during the expand phase.

Mark the corresponding instructions as tainted and don't warn if
already tainted.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 linearize.c | 19 +++++++++++++++++++
 simplify.c  |  3 ++-
 2 files changed, 21 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/linearize.c b/linearize.c
index 194afe664..938dbc07b 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1002,6 +1002,23 @@  static pseudo_t linearize_store_gen(struct entrypoint *ep,
 	return value;
 }
 
+static void taint_undefined_behaviour(struct instruction *insn)
+{
+	pseudo_t src2;
+
+	switch (insn->opcode) {
+	case OP_LSR:
+	case OP_ASR:
+	case OP_SHL:
+		src2 = insn->src2;
+		if (src2->type != PSEUDO_VAL)
+			break;
+		if ((unsigned long long)src2->value >= insn->size)
+			insn->tainted = 1;
+		break;
+	}
+}
+
 static pseudo_t add_binary_op(struct entrypoint *ep, struct symbol *ctype, int op, pseudo_t left, pseudo_t right)
 {
 	struct instruction *insn = alloc_typed_instruction(op, ctype);
@@ -1407,6 +1424,7 @@  static pseudo_t linearize_assignment(struct entrypoint *ep, struct expression *e
 		oldvalue = cast_pseudo(ep, oldvalue, target->ctype, ctype);
 		opcode = map_opcode(op_trans[expr->op - SPECIAL_BASE], ctype);
 		dst = add_binary_op(ep, ctype, opcode, oldvalue, value);
+		taint_undefined_behaviour(dst->def);
 		value = cast_pseudo(ep, dst, ctype, expr->ctype);
 	}
 	value = linearize_store_gen(ep, value, &ad);
@@ -1512,6 +1530,7 @@  static pseudo_t linearize_binop(struct entrypoint *ep, struct expression *expr)
 	src2 = linearize_expression(ep, expr->right);
 	op = map_opcode(opcode[expr->op], expr->ctype);
 	dst = add_binary_op(ep, expr->ctype, op, src1, src2);
+	taint_undefined_behaviour(dst->def);
 	return dst;
 }
 
diff --git a/simplify.c b/simplify.c
index 741b1272c..d09ff40ec 100644
--- a/simplify.c
+++ b/simplify.c
@@ -538,8 +538,9 @@  static int simplify_asr(struct instruction *insn, pseudo_t pseudo, long long val
 {
 	unsigned int size = operand_size(insn, pseudo);
 
-	if (value >= size) {
+	if (value >= size && !insn->tainted) {
 		warning(insn->pos, "right shift by bigger than source value");
+		insn->tainted = 1;
 		return replace_with_pseudo(insn, value_pseudo(0));
 	}
 	if (!value)