From de24011eb3f431cf9810be883b6d6ab6a71ada72 Mon Sep 17 00:00:00 2001 From: Regis Blanc <regwblanc@gmail.com> Date: Wed, 3 Jun 2015 19:17:09 +0200 Subject: [PATCH] detect mod and rem by 0 --- .../scala/leon/purescala/PrettyPrinter.scala | 4 ++-- .../leon/verification/DefaultTactic.scala | 4 ++++ .../leon/verification/InjectAsserts.scala | 18 +++++++++++++++++- .../verification/VerificationCondition.scala | 2 ++ ...VDivision.scala => BVDivisionByZero.scala} | 2 +- .../purescala/invalid/BVRemainderByZero.scala | 11 +++++++++++ .../{Division.scala => DivisionByZero.scala} | 4 ++-- .../purescala/invalid/ModuloByZero.scala | 11 +++++++++++ .../purescala/invalid/RemainderByZero.scala | 11 +++++++++++ ...VDivision.scala => BVDivisionByZero.scala} | 6 +++++- ...ivision2.scala => BVDivisionByZero2.scala} | 2 +- .../purescala/valid/Division.scala | 11 ----------- .../purescala/valid/DivisionByZero.scala | 19 +++++++++++++++++++ 13 files changed, 86 insertions(+), 19 deletions(-) rename src/test/resources/regression/verification/purescala/invalid/{BVDivision.scala => BVDivisionByZero.scala} (82%) create mode 100644 src/test/resources/regression/verification/purescala/invalid/BVRemainderByZero.scala rename src/test/resources/regression/verification/purescala/invalid/{Division.scala => DivisionByZero.scala} (84%) create mode 100644 src/test/resources/regression/verification/purescala/invalid/ModuloByZero.scala create mode 100644 src/test/resources/regression/verification/purescala/invalid/RemainderByZero.scala rename src/test/resources/regression/verification/purescala/valid/{BVDivision.scala => BVDivisionByZero.scala} (57%) rename src/test/resources/regression/verification/purescala/valid/{BVDivision2.scala => BVDivisionByZero2.scala} (83%) delete mode 100644 src/test/resources/regression/verification/purescala/valid/Division.scala create mode 100644 src/test/resources/regression/verification/purescala/valid/DivisionByZero.scala diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index 7b6ccdcd6..bbee52fbf 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -625,11 +625,11 @@ class PrettyPrinter(opts: PrinterOptions, def precedence(ex: Expr): Int = ex match { case (pa: PrettyPrintable) => pa.printPrecedence case (_: ElementOfSet) => 0 - case (_: Or | BinaryMethodCall(_, "||", _)) => 1 + case (_: Modulo) => 1 + case (_: Or | BinaryMethodCall(_, "||", _)) => 2 case (_: And | BinaryMethodCall(_, "&&", _)) => 3 case (_: GreaterThan | _: GreaterEquals | _: LessEquals | _: LessThan) => 4 case (_: Equals | _: Not) => 5 - case (_: Modulo) => 6 case (_: Plus | _: BVPlus | _: Minus | _: BVMinus | _: SetUnion| _: SetDifference | BinaryMethodCall(_, "+" | "-", _)) => 7 case (_: Times | _: BVTimes | _: Division | _: BVDivision | _: Remainder | _: BVRemainder | BinaryMethodCall(_, "*" | "/", _)) => 8 case _ => 9 diff --git a/src/main/scala/leon/verification/DefaultTactic.scala b/src/main/scala/leon/verification/DefaultTactic.scala index 2333c3191..43ef19dfd 100644 --- a/src/main/scala/leon/verification/DefaultTactic.scala +++ b/src/main/scala/leon/verification/DefaultTactic.scala @@ -60,6 +60,10 @@ class DefaultTactic(vctx: VerificationContext) extends Tactic(vctx) { VCKinds.ArrayUsage } else if (err.startsWith("Division ")) { VCKinds.DivisionByZero + } else if (err.startsWith("Modulo ")) { + VCKinds.ModuloByZero + } else if (err.startsWith("Remainder ")) { + VCKinds.RemainderByZero } else { VCKinds.Assert } diff --git a/src/main/scala/leon/verification/InjectAsserts.scala b/src/main/scala/leon/verification/InjectAsserts.scala index bacfbe140..fae6329c8 100644 --- a/src/main/scala/leon/verification/InjectAsserts.scala +++ b/src/main/scala/leon/verification/InjectAsserts.scala @@ -13,7 +13,7 @@ import xlang.Expressions._ object InjectAsserts extends LeonPhase[Program, Program] { val name = "Asserts" - val description = "Inject asserts for various corrected conditions (map accesses, array accesses, ..)" + val description = "Inject asserts for various correctness conditions (map accesses, array accesses, divisions by zero,..)" def run(ctx: LeonContext)(pgm: Program): Program = { def indexUpTo(i: Expr, e: Expr) = { @@ -40,11 +40,27 @@ object InjectAsserts extends LeonPhase[Program, Program] { Some("Division by zero"), e ).setPos(e)) + case e @ Remainder(_, d) => + Some(Assert(Not(Equals(d, InfiniteIntegerLiteral(0))), + Some("Remainder by zero"), + e + ).setPos(e)) + case e @ Modulo(_, d) => + Some(Assert(Not(Equals(d, InfiniteIntegerLiteral(0))), + Some("Modulo by zero"), + e + ).setPos(e)) + case e @ BVDivision(_, d) => Some(Assert(Not(Equals(d, IntLiteral(0))), Some("Division by zero"), e ).setPos(e)) + case e @ BVRemainder(_, d) => + Some(Assert(Not(Equals(d, IntLiteral(0))), + Some("Remainder by zero"), + e + ).setPos(e)) case _ => None diff --git a/src/main/scala/leon/verification/VerificationCondition.scala b/src/main/scala/leon/verification/VerificationCondition.scala index 890a16d06..2063902c2 100644 --- a/src/main/scala/leon/verification/VerificationCondition.scala +++ b/src/main/scala/leon/verification/VerificationCondition.scala @@ -35,6 +35,8 @@ object VCKinds { case object MapUsage extends VCKind("map usage", "map use") case object ArrayUsage extends VCKind("array usage", "arr. use") case object DivisionByZero extends VCKind("division by zero", "div 0") + case object ModuloByZero extends VCKind("modulo by zero", "mod 0") + case object RemainderByZero extends VCKind("remainder by zero", "rem 0") } case class VCResult(status: VCStatus, solvedWith: Option[Solver], timeMs: Option[Long]) { diff --git a/src/test/resources/regression/verification/purescala/invalid/BVDivision.scala b/src/test/resources/regression/verification/purescala/invalid/BVDivisionByZero.scala similarity index 82% rename from src/test/resources/regression/verification/purescala/invalid/BVDivision.scala rename to src/test/resources/regression/verification/purescala/invalid/BVDivisionByZero.scala index a2572db84..54ac21fb6 100644 --- a/src/test/resources/regression/verification/purescala/invalid/BVDivision.scala +++ b/src/test/resources/regression/verification/purescala/invalid/BVDivisionByZero.scala @@ -2,7 +2,7 @@ import leon.lang._ import leon.collection._ import leon._ -object BVDivision { +object BVDivisionByZero { def divByZero(x: Int): Boolean = { (x / 0 == 10) diff --git a/src/test/resources/regression/verification/purescala/invalid/BVRemainderByZero.scala b/src/test/resources/regression/verification/purescala/invalid/BVRemainderByZero.scala new file mode 100644 index 000000000..ed3ebf22a --- /dev/null +++ b/src/test/resources/regression/verification/purescala/invalid/BVRemainderByZero.scala @@ -0,0 +1,11 @@ +import leon.lang._ +import leon.collection._ +import leon._ + +object BVRemainderByZero { + + def remByZero(x: Int): Boolean = { + (x % 0 == 10) + } + +} diff --git a/src/test/resources/regression/verification/purescala/invalid/Division.scala b/src/test/resources/regression/verification/purescala/invalid/DivisionByZero.scala similarity index 84% rename from src/test/resources/regression/verification/purescala/invalid/Division.scala rename to src/test/resources/regression/verification/purescala/invalid/DivisionByZero.scala index 6b505a773..7415f2e6a 100644 --- a/src/test/resources/regression/verification/purescala/invalid/Division.scala +++ b/src/test/resources/regression/verification/purescala/invalid/DivisionByZero.scala @@ -2,10 +2,10 @@ import leon.lang._ import leon.collection._ import leon._ -object Division { +object DivisionByZero { def divByZero(x: BigInt): Boolean = { (x / BigInt(0) == BigInt(10)) } - + } diff --git a/src/test/resources/regression/verification/purescala/invalid/ModuloByZero.scala b/src/test/resources/regression/verification/purescala/invalid/ModuloByZero.scala new file mode 100644 index 000000000..19eb0da32 --- /dev/null +++ b/src/test/resources/regression/verification/purescala/invalid/ModuloByZero.scala @@ -0,0 +1,11 @@ +import leon.lang._ +import leon.collection._ +import leon._ + +object ModuloByZero { + + def modByZero(x: BigInt): Boolean = { + (x mod BigInt(0)) == BigInt(10) + } + +} diff --git a/src/test/resources/regression/verification/purescala/invalid/RemainderByZero.scala b/src/test/resources/regression/verification/purescala/invalid/RemainderByZero.scala new file mode 100644 index 000000000..5fc587fe8 --- /dev/null +++ b/src/test/resources/regression/verification/purescala/invalid/RemainderByZero.scala @@ -0,0 +1,11 @@ +import leon.lang._ +import leon.collection._ +import leon._ + +object RemainderByZero { + + def remByZero(x: BigInt): Boolean = { + (x % BigInt(0) == BigInt(10)) + } + +} diff --git a/src/test/resources/regression/verification/purescala/valid/BVDivision.scala b/src/test/resources/regression/verification/purescala/valid/BVDivisionByZero.scala similarity index 57% rename from src/test/resources/regression/verification/purescala/valid/BVDivision.scala rename to src/test/resources/regression/verification/purescala/valid/BVDivisionByZero.scala index 2121f416e..3de75f003 100644 --- a/src/test/resources/regression/verification/purescala/valid/BVDivision.scala +++ b/src/test/resources/regression/verification/purescala/valid/BVDivisionByZero.scala @@ -2,10 +2,14 @@ import leon.lang._ import leon.collection._ import leon._ -object BVDivision { +object BVDivisionByZero { def noDivByZero(x: Int): Boolean = { (x / 10 == 10) } + + def noRemByZero(x: BigInt): Boolean = { + (x % 10 == 10) + } } diff --git a/src/test/resources/regression/verification/purescala/valid/BVDivision2.scala b/src/test/resources/regression/verification/purescala/valid/BVDivisionByZero2.scala similarity index 83% rename from src/test/resources/regression/verification/purescala/valid/BVDivision2.scala rename to src/test/resources/regression/verification/purescala/valid/BVDivisionByZero2.scala index 77d677753..382dbb191 100644 --- a/src/test/resources/regression/verification/purescala/valid/BVDivision2.scala +++ b/src/test/resources/regression/verification/purescala/valid/BVDivisionByZero2.scala @@ -2,7 +2,7 @@ import leon.lang._ import leon.collection._ import leon._ -object BVDivision2 { +object BVDivisionByZero2 { def division(x: Int, y: Int): Int = { require(y != 0) diff --git a/src/test/resources/regression/verification/purescala/valid/Division.scala b/src/test/resources/regression/verification/purescala/valid/Division.scala deleted file mode 100644 index 49337b86d..000000000 --- a/src/test/resources/regression/verification/purescala/valid/Division.scala +++ /dev/null @@ -1,11 +0,0 @@ -import leon.lang._ -import leon.collection._ -import leon._ - -object Division { - - def noDivByZero(x: BigInt): Boolean = { - (x / BigInt(10) == BigInt(10)) - } - -} diff --git a/src/test/resources/regression/verification/purescala/valid/DivisionByZero.scala b/src/test/resources/regression/verification/purescala/valid/DivisionByZero.scala new file mode 100644 index 000000000..559e13591 --- /dev/null +++ b/src/test/resources/regression/verification/purescala/valid/DivisionByZero.scala @@ -0,0 +1,19 @@ +import leon.lang._ +import leon.collection._ +import leon._ + +object DivisionByZero { + + def noDivByZero(x: BigInt): Boolean = { + (x / BigInt(10) == BigInt(10)) + } + + def noRemByZero(x: BigInt): Boolean = { + (x % BigInt(10) == BigInt(10)) + } + + def noModByZero(x: BigInt): Boolean = { + (x mod BigInt(10)) == BigInt(10) + } + +} -- GitLab