aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-05-31 02:58:30 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-07-21 16:22:55 +0200
commit5aa92924b10bd6eefbbb7d6f8ac6ac6ccfd2ccce (patch)
tree900e6d01d45bcc81adb3dcf3c6c1c0b723faaf16
parent47f8b684d56973d558741770c99e2059d635b9e4 (diff)
downloadsparse-dev-5aa92924b10bd6eefbbb7d6f8ac6ac6ccfd2ccce.tar.gz
big-shift: mark out-of-range OP_{ASR,LSR,SHL} as tainted
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>
-rw-r--r--linearize.c19
-rw-r--r--simplify.c3
2 files changed, 21 insertions, 1 deletions
diff --git a/linearize.c b/linearize.c
index 194afe66..938dbc07 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 741b1272..d09ff40e 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)