Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checking only read permissions when asserting function preconditions #532

Merged
merged 9 commits into from
Dec 19, 2024
2 changes: 1 addition & 1 deletion silver
Submodule silver updated 27 files
+6 −4 src/main/scala/viper/silver/ast/Expression.scala
+4 −2 src/main/scala/viper/silver/ast/Program.scala
+32 −10 src/main/scala/viper/silver/ast/utility/Consistency.scala
+1 −1 src/main/scala/viper/silver/ast/utility/Expressions.scala
+3 −3 src/main/scala/viper/silver/ast/utility/InverseFunctions.scala
+1 −1 src/main/scala/viper/silver/ast/utility/Nodes.scala
+15 −6 src/main/scala/viper/silver/ast/utility/Permissions.scala
+1 −1 src/main/scala/viper/silver/cfg/CfgTest.scala
+7 −0 src/main/scala/viper/silver/frontend/SilFrontEndConfig.scala
+6 −2 src/main/scala/viper/silver/frontend/SilFrontend.scala
+2 −1 src/main/scala/viper/silver/parser/ParseAst.scala
+22 −3 src/main/scala/viper/silver/parser/Resolver.scala
+3 −4 src/main/scala/viper/silver/parser/Translator.scala
+1 −1 src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePlugin.scala
+4 −4 src/main/scala/viper/silver/testing/BackendTypeTest.scala
+444 −0 src/test/resources/all/functions/function_precondition_perms.vpr
+8 −8 src/test/resources/all/issues/carbon/0196.vpr
+1 −1 src/test/resources/all/issues/carbon/0223.vpr
+2 −9 src/test/resources/all/issues/silicon/0030.vpr
+5 −5 src/test/resources/all/issues/silicon/0240.vpr
+1 −0 src/test/resources/all/issues/silicon/0376.vpr
+1 −1 src/test/scala/ChopperTests.scala
+4 −4 src/test/scala/ConsistencyTests.scala
+4 −4 src/test/scala/FeatureCombinationsTests.scala
+5 −5 src/test/scala/MethodDependencyTests.scala
+1 −1 src/test/scala/SimplifierTests.scala
+1 −1 src/test/scala/UtilityTests.scala
6 changes: 6 additions & 0 deletions src/main/scala/viper/carbon/CarbonVerifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ case class CarbonVerifier(override val reporter: Reporter,
}
else false

def respectFunctionPrecPermAmounts: Boolean = if (config != null) config.respectFunctionPrePermAmounts.toOption match {
case Some(b) => b
case None => false
}
else false

override def usePolyMapsInEncoding =
if (config != null) {
config.desugarPolymorphicMaps.toOption match {
Expand Down
5 changes: 4 additions & 1 deletion src/main/scala/viper/carbon/modules/PermModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package viper.carbon.modules

import viper.carbon.boogie._
import viper.carbon.modules.components.CarbonStateComponent
import viper.carbon.utility.PolyMapRep
import viper.silver.{ast => sil}

case class PMaskDesugaredRep(selectId: Identifier, storeId: Identifier)
Expand Down Expand Up @@ -159,4 +158,8 @@ trait PermModule extends Module with CarbonStateComponent {
// removes permission to w#ft (footprint of the magic wand) (See Heap module for w#ft description)
def exhaleWandFt(w: sil.MagicWand): Stmt

def setCheckReadPermissionOnly(readOnly: Boolean): Boolean

def assumePermUpperBounds(doAssume: Boolean): Stmt

}
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
override def translateFunction(f: sil.Function, names: Option[mutable.Map[String, String]]): Seq[Decl] = {
viper-admin marked this conversation as resolved.
Show resolved Hide resolved
env = Environment(verifier, f)
ErrorMemberMapping.currentMember = f

val oldCheckReadPermOnly = permModule.setCheckReadPermissionOnly(!verifier.respectFunctionPrecPermAmounts)
val res = MaybeCommentedDecl(s"Translation of function ${f.name}",
MaybeCommentedDecl("Uninterpreted function definitions", functionDefinitions(f), size = 1) ++
(if (f.isAbstract) Nil else
Expand All @@ -207,6 +209,7 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
names.get ++= usedNames
}

permModule.setCheckReadPermissionOnly(oldCheckReadPermOnly)
env = null
ErrorMemberMapping.currentMember = null
res
Expand Down Expand Up @@ -642,7 +645,8 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
val args = f.formalArgs map translateLocalVarDecl
val res = sil.Result(f.typ)()
val init : Stmt = MaybeCommentBlock("Initializing the state",
stateModule.initBoogieState ++ (f.formalArgs map (a => allAssumptionsAboutValue(a.typ,mainModule.translateLocalVarDecl(a),true))) ++ assumeFunctionsAt(heights(f.name)))
stateModule.initBoogieState ++ (if (verifier.respectFunctionPrecPermAmounts) Nil else permModule.assumePermUpperBounds(false)) ++
(f.formalArgs map (a => allAssumptionsAboutValue(a.typ,mainModule.translateLocalVarDecl(a),true))) ++ assumeFunctionsAt(heights(f.name)))
val checkPre : Stmt = checkFunctionPreconditionDefinedness(f)
val checkExp : Stmt = if (f.isAbstract) MaybeCommentBlock("(no definition for abstract function)",Nil) else
MaybeCommentBlock("Check definedness of function body",
Expand All @@ -665,7 +669,9 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {

val args = p.formalArgs map translateLocalVarDecl
val init : Stmt = MaybeCommentBlock("Initializing the state",
stateModule.initBoogieState ++ assumeAllFunctionDefinitions ++ (p.formalArgs map (a => allAssumptionsAboutValue(a.typ,mainModule.translateLocalVarDecl(a),true)))
stateModule.initBoogieState ++ assumeAllFunctionDefinitions ++
(if (verifier.respectFunctionPrecPermAmounts) Nil else permModule.assumePermUpperBounds(true)) ++
(p.formalArgs map (a => allAssumptionsAboutValue(a.typ,mainModule.translateLocalVarDecl(a),true)))
)

val predicateBody = p.body.get
Expand Down Expand Up @@ -871,12 +877,17 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
* contain permission introspection.
*/
val curState = stateModule.state
val oldCheckReadPermOnly = permModule.setCheckReadPermissionOnly(!verifier.respectFunctionPrecPermAmounts)
defState.setDefState()
val res = executeExhale()
permModule.setCheckReadPermissionOnly(oldCheckReadPermOnly)
stateModule.replaceState(curState)
res
case None =>
executeExhale()
val oldCheckReadPermOnly = permModule.setCheckReadPermissionOnly(!verifier.respectFunctionPrecPermAmounts)
val res = executeExhale()
permModule.setCheckReadPermissionOnly(oldCheckReadPermOnly)
res
}
}
) ++
Expand Down Expand Up @@ -961,7 +972,10 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
wandModule.translatingStmtsInWandInit()
}
(checkDefinedness(acc, errors.FoldFailed(fold), insidePackageStmt = insidePackageStmt) ++
checkDefinedness(perm, errors.FoldFailed(fold), insidePackageStmt = insidePackageStmt) ++
// If no permission amount is supplied explicitly, we always use the default FullPerm; this is
// okay even if we are inside a function and only want to check for some positive amount, because permission
// amounts do not matter in this context.
checkDefinedness(perm.getOrElse(sil.FullPerm()()), errors.FoldFailed(fold), insidePackageStmt = insidePackageStmt) ++
viper-admin marked this conversation as resolved.
Show resolved Hide resolved
foldFirst, foldLast)
}
}
Expand Down Expand Up @@ -998,7 +1012,10 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
unfold match {
case sil.Unfold([email protected]([email protected](_, _), perm)) =>
checkDefinedness(acc, errors.UnfoldFailed(unfold), insidePackageStmt = insidePackageStmt) ++
checkDefinedness(perm, errors.UnfoldFailed(unfold)) ++
// If no permission amount is supplied explicitly, we always use the default FullPerm; this is
// okay even if we are inside a function and only want to check for some positive amount, because permission
// amounts do not matter in this context.
checkDefinedness(perm.getOrElse(sil.FullPerm()()), errors.UnfoldFailed(unfold)) ++
viper-admin marked this conversation as resolved.
Show resolved Hide resolved
unfoldPredicate(acc, errors.UnfoldFailed(unfold), false, statesStackForPackageStmt, insidePackageStmt)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ class DefaultMainModule(val verifier: Verifier) extends MainModule with Stateles
val initOldStateComment = "Initializing of old state"
val ins: Seq[LocalVarDecl] = formalArgs map translateLocalVarDecl
val outs: Seq[LocalVarDecl] = formalReturns map translateLocalVarDecl
val init = MaybeCommentBlock("Initializing the state", stateModule.initBoogieState ++ assumeAllFunctionDefinitions ++ stmtModule.initStmt(method.bodyOrAssumeFalse))
val init = MaybeCommentBlock("Initializing the state", stateModule.initBoogieState ++ assumeAllFunctionDefinitions ++
(if (verifier.respectFunctionPrecPermAmounts) Nil else permModule.assumePermUpperBounds(true)) ++ stmtModule.initStmt(method.bodyOrAssumeFalse))
val initOld = MaybeCommentBlock("Initializing the old state", stateModule.initOldState)
val paramAssumptions = mWithLoopInfo.formalArgs map (a => allAssumptionsAboutValue(a.typ, translateLocalVarDecl(a), true))
val inhalePre = translateMethodDeclPre(pres)
Expand Down Expand Up @@ -269,9 +270,9 @@ class DefaultMainModule(val verifier: Verifier) extends MainModule with Stateles
val resourceCurPerm =
q.exp match {
case r : sil.FieldAccess =>
sil.FieldAccessPredicate(r, curPermVar)()
sil.FieldAccessPredicate(r, Some(curPermVar))()
case r: sil.PredicateAccess =>
sil.PredicateAccessPredicate(r, curPermVar)()
sil.PredicateAccessPredicate(r, Some(curPermVar))()
case _ => sys.error("Not supported resource in quasihavoc")
}

Expand Down
Loading
Loading