diff mbox

[4/9] div0: warn on division by zero - general case

Message ID 20170531032207.95830-5-luc.vanoostenryck@gmail.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Luc Van Oostenryck May 31, 2017, 3:22 a.m. UTC
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@gmail.com>
---
 linearize.c              | 19 +++++++++++++++++++
 validation/div-by-zero.c | 12 ++++++++++++
 2 files changed, 31 insertions(+)
diff mbox

Patch

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
  */