diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-05-31 02:58:30 +0200 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-07-21 16:22:55 +0200 |
| commit | 5aa92924b10bd6eefbbb7d6f8ac6ac6ccfd2ccce (patch) | |
| tree | 900e6d01d45bcc81adb3dcf3c6c1c0b723faaf16 | |
| parent | 47f8b684d56973d558741770c99e2059d635b9e4 (diff) | |
| download | sparse-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.c | 19 | ||||
| -rw-r--r-- | simplify.c | 3 |
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; } @@ -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) |
