sparse warn about division by zero but only in plain expression: no checks are done when the division is part of a compound assignement. Change this by adding the appropriate check and warning during linearization and take care to avoid warning twice. Note: if should be simpler to drop the checks done at expansion time but some expressions are discarded before reaching linearization and we want to check and warn for those too. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- linearize.c | 19 +++++++++++++++++++ validation/div-by-zero.c | 12 ++++++++++++ 2 files changed, 31 insertions(+) diff --git a/linearize.c b/linearize.c index 7313e72d8..7760ea996 100644 --- a/linearize.c +++ b/linearize.c @@ -959,6 +959,23 @@ static pseudo_t linearize_store_gen(struct entrypoint *ep, return value; } +static void warn_undef_insn(struct instruction *insn, int warn) +{ + switch (insn->opcode) { + case OP_DIVU: + case OP_DIVS: + case OP_MODU: + case OP_MODS: + if (is_pseudo_value(insn->src2, 0)) { + if (warn) + warning(insn->pos, "division by zero"); + } + break; + default: + 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); @@ -1208,6 +1225,7 @@ static pseudo_t linearize_assignment(struct entrypoint *ep, struct expression *e oldvalue = cast_pseudo(ep, oldvalue, target->ctype, ctype); opcode = opcode_sign(op_trans[expr->op - SPECIAL_BASE], ctype); dst = add_binary_op(ep, ctype, opcode, oldvalue, value); + warn_undef_insn(dst->def, 1); value = cast_pseudo(ep, dst, ctype, expr->ctype); } value = linearize_store_gen(ep, value, &ad); @@ -1323,6 +1341,7 @@ static pseudo_t linearize_binop(struct entrypoint *ep, struct expression *expr) src2 = linearize_expression(ep, expr->right); op = opcode_sign(opcode[expr->op], expr->ctype); dst = add_binary_op(ep, expr->ctype, op, src1, src2); + warn_undef_insn(dst->def, 0); return dst; } diff --git a/validation/div-by-zero.c b/validation/div-by-zero.c index 786e48298..a06944a58 100644 --- a/validation/div-by-zero.c +++ b/validation/div-by-zero.c @@ -18,6 +18,14 @@ int isvmod(int a) { return a % (int) 0; } int lsvmod(int a) { return a % (long) 0; } int usvmod(int a) { return a % (unsigned int) 0; } +int xsvdiv(int a) { if (a && 0) return a / 0; return 0; } +int asvdiv(int a) { return a /= 0; } +int osvdiv(int a) { return a / (a && 0); } + +int xsvmod(int a) { if (a && 0) return a % 0; return 0; } +int asvmod(int a) { return a %= 0; } +int osvmod(int a) { return a % (a && 0); } + /* * check-name: div-by-zero.c * check-command: sparse -Wno-decl $file @@ -39,5 +47,9 @@ div-by-zero.c:16:30: warning: division by zero div-by-zero.c:17:30: warning: division by zero div-by-zero.c:18:30: warning: division by zero div-by-zero.c:19:30: warning: division by zero +div-by-zero.c:21:42: warning: division by zero +div-by-zero.c:22:33: warning: division by zero +div-by-zero.c:25:42: warning: division by zero +div-by-zero.c:26:33: warning: division by zero * check-error-end */ -- 2.13.0 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html