Skip to content

Commit 58e49fe

Browse files
author
Brian Huffman
committed
Use throwM or panic instead of fail for error handling in JVMSetup.
This partially addresses #928. This patch only covers the uses of `fail` that were used to implement the JVMSetup commands. There are still a lot of uses of `fail` in other parts of the SAW/JVM code.
1 parent 6a62999 commit 58e49fe

File tree

2 files changed

+85
-26
lines changed

2 files changed

+85
-26
lines changed

src/SAWScript/Crucible/JVM/Builtins.hs

+57-16
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ module SAWScript.Crucible.JVM.Builtins
4141

4242
import Control.Lens
4343

44+
import qualified Control.Monad.Catch as X
4445
import Control.Monad.State
4546
import qualified Control.Monad.State.Strict as Strict
4647
import Control.Monad.Trans.Except (runExceptT)
@@ -792,6 +793,54 @@ setupDynamicClassTable sym jc = foldM addClass Map.empty (Map.assocs (CJ.classTa
792793
--------------------------------------------------------------------------------
793794
-- Setup builtins
794795

796+
data JVMSetupError
797+
= JVMFreshVarInvalidType JavaType
798+
| JVMFieldMultiple SetupValue String -- reference and field name
799+
| JVMFieldFailure String -- TODO: switch to a more structured type
800+
| JVMFieldTypeMismatch String J.Type J.Type -- field name, expected, found
801+
| JVMElemNonArray J.Type
802+
| JVMElemInvalidIndex SetupValue Int Int -- reference, length, index
803+
| JVMElemTypeMismatch Int J.Type J.Type -- index, expected, found
804+
| JVMElemMultiple SetupValue Int -- reference and array index
805+
| JVMArrayMultiple SetupValue
806+
807+
instance X.Exception JVMSetupError
808+
809+
instance Show JVMSetupError where
810+
show err =
811+
case err of
812+
JVMFreshVarInvalidType jty ->
813+
"jvm_fresh_var: Invalid type: " ++ show jty
814+
JVMFieldMultiple _ptr fname ->
815+
"jvm_field_is: Multiple specifications for the same instance field (" ++ fname ++ ")"
816+
JVMFieldFailure msg ->
817+
"jvm_field_is: JVM field resolution failed:\n" ++ msg
818+
JVMFieldTypeMismatch fname expected found ->
819+
-- FIXME: use a pretty printing function for J.Type instead of show
820+
unlines
821+
[ "jvm_field_is: Incompatible types for field " ++ show fname
822+
, "Expected type: " ++ show expected
823+
, "Given type: " ++ show found
824+
]
825+
JVMElemNonArray jty ->
826+
"jvm_elem_is: Not an array type: " ++ show jty
827+
JVMElemInvalidIndex _ptr len idx ->
828+
unlines
829+
[ "jvm_elem_is: Array index out of bounds"
830+
, "Array length: " ++ show len
831+
, "Given index: " ++ show idx
832+
]
833+
JVMElemTypeMismatch idx expected found ->
834+
unlines
835+
[ "jvm_elem_is: Incompatible types for array index " ++ show idx
836+
, "Expected type: " ++ show expected
837+
, "Given type: " ++ show found
838+
]
839+
JVMElemMultiple _ptr idx ->
840+
"jvm_elem_is: Multiple specifications for the same array index (" ++ show idx ++ ")"
841+
JVMArrayMultiple _ptr ->
842+
"jvm_array_is: Multiple specifications for the same array reference"
843+
795844
-- | Returns Cryptol type of actual type if it is an array or
796845
-- primitive type.
797846
cryptolTypeOfActual :: JavaType -> Maybe Cryptol.Type
@@ -837,7 +886,7 @@ jvm_fresh_var bic _opts name jty =
837886
JVMSetupM $
838887
do let sc = biSharedContext bic
839888
case cryptolTypeOfActual jty of
840-
Nothing -> fail $ "Unsupported type in jvm_fresh_var: " ++ show jty
889+
Nothing -> X.throwM $ JVMFreshVarInvalidType jty
841890
Just cty -> Setup.freshVariable sc name cty
842891

843892
jvm_alloc_object ::
@@ -884,19 +933,15 @@ jvm_field_is _typed _bic _opt ptr fname val =
884933
let cb = cc ^. jccCodebase
885934
let path = Left fname
886935
if st ^. Setup.csPrePost == PreState && MS.testResolved ptr [] rs
887-
then fail $ "Multiple points-to preconditions on same pointer (field " ++ fname ++ ")"
936+
then X.throwM $ JVMFieldMultiple ptr fname
888937
else Setup.csResolvedState %= MS.markResolved ptr [path]
889938
let env = MS.csAllocations (st ^. Setup.csMethodSpec)
890939
let nameEnv = MS.csTypeNames (st ^. Setup.csMethodSpec)
891940
ptrTy <- typeOfSetupValue cc env nameEnv ptr
892941
valTy <- typeOfSetupValue cc env nameEnv val
893-
fid <- either fail pure =<< (liftIO $ runExceptT $ findField cb pos ptrTy fname)
942+
fid <- either (X.throwM . JVMFieldFailure) pure =<< (liftIO $ runExceptT $ findField cb pos ptrTy fname)
894943
unless (registerCompatible (J.fieldIdType fid) valTy) $
895-
fail $ unlines
896-
[ "Incompatible types for field " ++ fname
897-
, "Expected: " ++ show (J.fieldIdType fid)
898-
, "but given value of type: " ++ show valTy
899-
]
944+
X.throwM $ JVMFieldTypeMismatch fname (J.fieldIdType fid) valTy
900945
Setup.addPointsTo (JVMPointsToField loc ptr fid val)
901946

902947
jvm_elem_is ::
@@ -915,7 +960,7 @@ jvm_elem_is _typed _bic _opt ptr idx val =
915960
let cc = st ^. Setup.csCrucibleContext
916961
let path = Right idx
917962
if st ^. Setup.csPrePost == PreState && MS.testResolved ptr [path] rs
918-
then fail "Multiple points-to preconditions on same pointer"
963+
then X.throwM $ JVMElemMultiple ptr idx
919964
else Setup.csResolvedState %= MS.markResolved ptr [path]
920965
let env = MS.csAllocations (st ^. Setup.csMethodSpec)
921966
let nameEnv = MS.csTypeNames (st ^. Setup.csMethodSpec)
@@ -924,13 +969,9 @@ jvm_elem_is _typed _bic _opt ptr idx val =
924969
elTy <-
925970
case ptrTy of
926971
J.ArrayType elTy -> pure elTy
927-
_ -> fail $ "Not an array type: " ++ show ptrTy
972+
_ -> X.throwM $ JVMElemNonArray ptrTy
928973
unless (registerCompatible elTy valTy) $
929-
fail $ unlines
930-
[ "Incompatible types for array element"
931-
, "Expected: " ++ show elTy
932-
, "but given value of type: " ++ show valTy
933-
]
974+
X.throwM $ JVMElemTypeMismatch idx elTy valTy
934975
Setup.addPointsTo (JVMPointsToElem loc ptr idx val)
935976

936977
jvm_array_is ::
@@ -946,7 +987,7 @@ jvm_array_is _typed _bic _opt ptr val =
946987
st <- get
947988
let rs = st ^. Setup.csResolvedState
948989
if st ^. Setup.csPrePost == PreState && MS.testResolved ptr [] rs
949-
then fail "Multiple points-to preconditions on same pointer"
990+
then X.throwM $ JVMArrayMultiple ptr
950991
else Setup.csResolvedState %= MS.markResolved ptr []
951992
Setup.addPointsTo (JVMPointsToArray loc ptr val)
952993

src/SAWScript/Crucible/JVM/ResolveSetupValue.hs

+28-10
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ module SAWScript.Crucible.JVM.ResolveSetupValue
2626
) where
2727

2828
import Control.Lens
29-
import qualified Control.Monad.Fail as Fail
29+
import qualified Control.Monad.Catch as X
3030
import Data.IORef
3131
import qualified Data.BitVector.Sized as BV
3232
import Data.Map (Map)
3333
import qualified Data.Map as Map
3434
import Data.Void (absurd)
3535

3636
import qualified Cryptol.Eval.Type as Cryptol (TValue(..), evalValType)
37-
import qualified Cryptol.TypeCheck.AST as Cryptol (Schema(..))
37+
import qualified Cryptol.TypeCheck.AST as Cryptol (Type, Schema(..))
3838
import qualified Cryptol.Utils.PP as Cryptol (pp)
3939

4040
import qualified What4.BaseTypes as W4
@@ -68,6 +68,7 @@ import SAWScript.Crucible.Common (Sym)
6868
import SAWScript.Crucible.Common.MethodSpec (AllocIndex(..))
6969

7070
--import SAWScript.JavaExpr (JavaType(..))
71+
import SAWScript.Panic
7172
import SAWScript.Prover.Rewrite
7273
import SAWScript.Crucible.JVM.MethodSpecIR
7374
import qualified SAWScript.Crucible.Common.MethodSpec as MS
@@ -88,8 +89,27 @@ type JVMRefVal = Crucible.RegValue Sym CJ.JVMRefType
8889

8990
type SetupValue = MS.SetupValue CJ.JVM
9091

92+
data JvmTypeOfError
93+
= JvmPolymorphicType Cryptol.Schema
94+
| JvmNonRepresentableType Cryptol.Type
95+
96+
instance Show JvmTypeOfError where
97+
show (JvmPolymorphicType s) =
98+
unlines
99+
[ "Expected monomorphic term"
100+
, "instead got:"
101+
, show (Cryptol.pp s)
102+
]
103+
show (JvmNonRepresentableType ty) =
104+
unlines
105+
[ "Type not representable in JVM:"
106+
, show (Cryptol.pp ty)
107+
]
108+
109+
instance X.Exception JvmTypeOfError
110+
91111
typeOfSetupValue ::
92-
Fail.MonadFail m =>
112+
X.MonadThrow m =>
93113
JVMCrucibleContext ->
94114
Map AllocIndex (W4.ProgramLoc, Allocation) ->
95115
Map AllocIndex JIdent ->
@@ -99,18 +119,16 @@ typeOfSetupValue _cc env _nameEnv val =
99119
case val of
100120
MS.SetupVar i ->
101121
case Map.lookup i env of
102-
Nothing -> fail ("typeOfSetupValue: Unresolved prestate variable:" ++ show i)
122+
Nothing -> panic "JVMSetup" ["typeOfSetupValue", "Unresolved prestate variable:" ++ show i]
103123
Just (_, alloc) -> return (allocationType alloc)
104124
MS.SetupTerm tt ->
105125
case ttSchema tt of
106126
Cryptol.Forall [] [] ty ->
107127
case toJVMType (Cryptol.evalValType mempty ty) of
108-
Nothing -> fail "typeOfSetupValue: non-representable type"
128+
Nothing -> X.throwM (JvmNonRepresentableType ty)
109129
Just jty -> return jty
110-
s -> fail $ unlines [ "typeOfSetupValue: expected monomorphic term"
111-
, "instead got:"
112-
, show (Cryptol.pp s)
113-
]
130+
s -> X.throwM (JvmPolymorphicType s)
131+
114132
MS.SetupNull () ->
115133
-- We arbitrarily set the type of NULL to java.lang.Object,
116134
-- because a) it is memory-compatible with any type that NULL
@@ -137,7 +155,7 @@ resolveSetupVal cc env _tyenv _nameEnv val =
137155
case val of
138156
MS.SetupVar i
139157
| Just v <- Map.lookup i env -> return (RVal v)
140-
| otherwise -> fail ("resolveSetupVal: Unresolved prestate variable:" ++ show i)
158+
| otherwise -> panic "JVMSetup" ["resolveSetupVal", "Unresolved prestate variable:" ++ show i]
141159
MS.SetupTerm tm -> resolveTypedTerm cc tm
142160
MS.SetupNull () ->
143161
return (RVal (W4.maybePartExpr sym Nothing))

0 commit comments

Comments
 (0)