Skip to content

Commit

Permalink
Add jvm_modifies_array primitive.
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Huffman committed May 17, 2021
1 parent 4d9e593 commit f20ac29
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 22 deletions.
6 changes: 1 addition & 5 deletions examples/java/get.saw
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ jvm_verify c "get" [] false
j <- jvm_fresh_var "j" java_int;
jvm_precond {{ j <= 3 }};
jvm_execute_func [this, a, jvm_term j];
// TODO: Add declaration to say that the entire array is modified.
jvm_modifies_elem a 0;
jvm_modifies_elem a 1;
jvm_modifies_elem a 2;
jvm_modifies_elem a 3;
jvm_modifies_array a;
jvm_return (jvm_term {{ j }});
}
abc;
44 changes: 31 additions & 13 deletions src/SAWScript/Crucible/JVM/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module SAWScript.Crucible.JVM.Builtins
, jvm_modifies_field
, jvm_modifies_static_field
, jvm_modifies_elem
, jvm_modifies_array
, jvm_field_is
, jvm_static_field_is
, jvm_elem_is
Expand Down Expand Up @@ -476,7 +477,7 @@ setupPrePointsTos mspec cc env pts mem0 = foldM doPointsTo mem0 pts
do let lhs' = lookupAllocIndex env lhs
rhs' <- maybe (pure CJ.unassignedJVMValue) injectSetupVal rhs
CJ.doArrayStore sym mem lhs' idx rhs'
JVMPointsToArray _loc lhs rhs ->
JVMPointsToArray _loc lhs (Just rhs) ->
do sc <- saw_ctx <$> sawCoreState sym
let lhs' = lookupAllocIndex env lhs
(_ety, tts) <-
Expand All @@ -486,6 +487,8 @@ setupPrePointsTos mspec cc env pts mem0 = foldM doPointsTo mem0 pts
Just x -> pure x
rhs' <- traverse (injectSetupVal . MS.SetupTerm) tts
doEntireArrayStore sym mem lhs' rhs'
JVMPointsToArray _loc _lhs Nothing ->
pure mem -- This should probably never occur in the prestate section.

-- | Collects boolean terms that should be assumed to be true.
setupPrestateConditions ::
Expand Down Expand Up @@ -1146,11 +1149,22 @@ generic_elem_is ptr idx mval =
X.throwM $ JVMElemMultiple ptr' idx
Setup.addPointsTo pt

jvm_modifies_array ::
SetupValue {- ^ array reference -} ->
JVMSetupM ()
jvm_modifies_array ptr = generic_array_is ptr Nothing

jvm_array_is ::
SetupValue {- ^ array reference -} ->
TypedTerm {- ^ array value -} ->
JVMSetupM ()
jvm_array_is ptr val =
jvm_array_is ptr val = generic_array_is ptr (Just val)

generic_array_is ::
SetupValue {- ^ array reference -} ->
Maybe TypedTerm {- ^ array value -} ->
JVMSetupM ()
generic_array_is ptr mval =
JVMSetupM $
do loc <- SS.toW4Loc "jvm_array_is" <$> lift getPosition
ptr' <-
Expand All @@ -1163,17 +1177,21 @@ jvm_array_is ptr val =
case snd (lookupAllocIndex env ptr') of
AllocObject cname -> X.throwM $ JVMElemNonArray (J.ClassType cname)
AllocArray len elTy -> pure (len, elTy)
let schema = ttSchema val
let checkVal =
do ty <- Cryptol.isMono schema
(n, a) <- Cryptol.tIsSeq ty
guard (Cryptol.tIsNum n == Just (toInteger len))
jty <- toJVMType (Cryptol.evalValType mempty a)
guard (registerCompatible elTy jty)
case checkVal of
Nothing -> X.throwM (JVMArrayTypeMismatch len elTy schema)
Just () -> pure ()
let pt = JVMPointsToArray loc ptr' val
case mval of
Nothing -> pure ()
Just val ->
case checkVal of
Nothing -> X.throwM (JVMArrayTypeMismatch len elTy schema)
Just () -> pure ()
where
schema = ttSchema val
checkVal =
do ty <- Cryptol.isMono schema
(n, a) <- Cryptol.tIsSeq ty
guard (Cryptol.tIsNum n == Just (toInteger len))
jty <- toJVMType (Cryptol.evalValType mempty a)
guard (registerCompatible elTy jty)
let pt = JVMPointsToArray loc ptr' mval
let pts = st ^. Setup.csMethodSpec . MS.csPreState . MS.csPointsTos
when (st ^. Setup.csPrePost == PreState && any (overlapPointsTo pt) pts) $
X.throwM $ JVMArrayMultiple ptr'
Expand Down
4 changes: 2 additions & 2 deletions src/SAWScript/Crucible/JVM/MethodSpecIR.hs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ data JVMPointsTo
= JVMPointsToField ProgramLoc MS.AllocIndex J.FieldId (Maybe (MS.SetupValue CJ.JVM))
| JVMPointsToStatic ProgramLoc J.FieldId (Maybe (MS.SetupValue CJ.JVM))
| JVMPointsToElem ProgramLoc MS.AllocIndex Int (Maybe (MS.SetupValue CJ.JVM))
| JVMPointsToArray ProgramLoc MS.AllocIndex TypedTerm
| JVMPointsToArray ProgramLoc MS.AllocIndex (Maybe TypedTerm)

overlapPointsTo :: JVMPointsTo -> JVMPointsTo -> Bool
overlapPointsTo =
Expand Down Expand Up @@ -165,7 +165,7 @@ ppPointsTo =
JVMPointsToArray _loc ptr val ->
MS.ppAllocIndex ptr
PPL.<+> PPL.pretty "points to"
PPL.<+> MS.ppTypedTerm val
PPL.<+> opt MS.ppTypedTerm val
where
opt = maybe (PPL.pretty "<unspecified>")

Expand Down
13 changes: 11 additions & 2 deletions src/SAWScript/Crucible/JVM/Override.hs
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ learnPointsTo opts sc cc spec prepost pt = do
v <- liftIO $ projectJVMVal sym ty ("array load " ++ show idx ++ ", " ++ show loc) dyn
matchArg opts sc cc spec prepost v ty val

JVMPointsToArray loc ptr tt ->
JVMPointsToArray loc ptr (Just tt) ->
do (len, ety) <-
case Cryptol.isMono (ttSchema tt) of
Nothing -> fail "jvm_array_is: invalid polymorphic value"
Expand Down Expand Up @@ -846,7 +846,7 @@ executePointsTo opts sc cc spec pt = do
globals' <- liftIO $ CJ.doArrayStore sym globals rval idx dyn
OM (overrideGlobals .= globals')

JVMPointsToArray _loc ptr tt ->
JVMPointsToArray _loc ptr (Just tt) ->
do (_ety, tts) <-
liftIO (destVecTypedTerm sc tt) >>=
\case
Expand All @@ -857,6 +857,15 @@ executePointsTo opts sc cc spec pt = do
globals' <- liftIO $ doEntireArrayStore sym globals rval vs
OM (overrideGlobals .= globals')

JVMPointsToArray _loc ptr Nothing ->
case Map.lookup ptr (MS.csAllocations spec) of
Just (_, AllocArray len _) ->
do let vs = replicate len CJ.unassignedJVMValue
rval <- resolveAllocIndexJVM ptr
globals' <- liftIO $ doEntireArrayStore sym globals rval vs
OM (overrideGlobals .= globals')
_ -> panic "JVMSetup" ["executePointsTo", "expected array allocation"]

injectSetupValueJVM ::
Sym ->
Options ->
Expand Down
12 changes: 12 additions & 0 deletions src/SAWScript/Interpreter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2731,6 +2731,18 @@ primitives = Map.fromList
, "nothing about the new value."
]

, prim "jvm_modifies_array" "JVMValue -> JVMSetup ()"
(pureVal jvm_modifies_array)
Experimental
[ "Declare that the indicated array's elements contain unspecified"
, "values."
, ""
, "This lets users write partial specifications of JVM methods."
, "In the post-state section (after `jvm_execute_func`), it"
, "states that the method may modify the array elements, but says"
, "nothing about the new values."
]

, prim "jvm_field_is" "JVMValue -> String -> JVMValue -> JVMSetup ()"
(pureVal jvm_field_is)
Experimental
Expand Down

0 comments on commit f20ac29

Please sign in to comment.