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

crucible-llvm: Simplify 'MemoryErrorReason' #915

Merged
merged 1 commit into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crucible-llvm/src/Lang/Crucible/LLVM/Errors.hs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ undefinedBehavior :: UB.UndefinedBehavior (RegValue' sym)
undefinedBehavior ub pred =
LLVMSafetyAssertion (BBUndefinedBehavior ub) pred Nothing

memoryError :: (1 <= w) => ME.MemoryOp sym w -> ME.MemoryErrorReason sym w -> Pred sym -> LLVMSafetyAssertion sym
memoryError :: (1 <= w) => ME.MemoryOp sym w -> ME.MemoryErrorReason -> Pred sym -> LLVMSafetyAssertion sym
memoryError mop rsn pred =
LLVMSafetyAssertion (BBMemoryError (ME.MemoryError mop rsn)) pred Nothing

Expand Down
63 changes: 33 additions & 30 deletions crucible-llvm/src/Lang/Crucible/LLVM/Errors/MemoryError.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,19 @@ module Lang.Crucible.LLVM.Errors.MemoryError
, ppMemoryOp
, MemoryErrorReason(..)
, ppMemoryErrorReason
, FuncLookupError(..)
, ppFuncLookupError

, concMemoryError
, concMemoryOp
, concMemoryErrorReason
) where

import Prelude hiding (pred)

import Data.Text (Text)
import Data.Void
import qualified Text.LLVM.PP as L
import qualified Text.LLVM.AST as L
import Type.Reflection (SomeTypeRep(SomeTypeRep))
import Prettyprinter

import What4.Interface
Expand All @@ -47,7 +48,6 @@ import Lang.Crucible.LLVM.MemModel.Common
import Lang.Crucible.LLVM.MemModel.Type
import Lang.Crucible.LLVM.MemModel.MemLog


data MemoryOp sym w
= MemLoadOp StorageType (Maybe String) (LLVMPtr sym w) (Mem sym)
| MemStoreOp StorageType (Maybe String) (LLVMPtr sym w) (Mem sym)
Expand All @@ -64,22 +64,43 @@ data MemoryOp sym w
data MemoryError sym where
MemoryError :: (1 <= w) =>
MemoryOp sym w ->
MemoryErrorReason sym w ->
MemoryErrorReason ->
MemoryError sym

-- | The kinds of type errors that arise while reading memory/constructing LLVM
-- values
data MemoryErrorReason sym w =
data MemoryErrorReason =
TypeMismatch StorageType StorageType
| UnexpectedArgumentType Text [StorageType]
| ApplyViewFail ValueView
| Invalid StorageType
| Invalidated Text
| NoSatisfyingWrite StorageType (LLVMPtr sym w)
| NoSatisfyingWrite StorageType
| UnwritableRegion
| UnreadableRegion
| BadFunctionPointer (Doc Void)
| BadFunctionPointer FuncLookupError
| OverlappingRegions
langston-barrett marked this conversation as resolved.
Show resolved Hide resolved
deriving (Eq, Ord)

-- | Reasons that looking up a function handle associated with an LLVM pointer
-- may fail
data FuncLookupError
= SymbolicPointer
| RawBitvector
| NoOverride
| Uncallable SomeTypeRep
deriving (Eq, Ord)

ppFuncLookupError :: FuncLookupError -> Doc ann
ppFuncLookupError =
\case
SymbolicPointer -> "Cannot resolve a symbolic pointer to a function handle"
RawBitvector -> "Cannot treat raw bitvector as function pointer"
NoOverride -> "No implementation or override found for pointer"
Uncallable (SomeTypeRep typeRep) ->
vsep [ "Data associated with the pointer found, but was not a callable function:"
, hang 2 (viaShow typeRep)
]

type MemErrContext sym w = MemoryOp sym w

Expand Down Expand Up @@ -148,7 +169,7 @@ details (MemoryError mop _rsn) = ppMemoryOp mop
ppMemoryError :: IsExpr (SymExpr sym) => MemoryError sym -> Doc ann
ppMemoryError (MemoryError mop rsn) = vcat [ppMemoryErrorReason rsn, ppMemoryOp mop]

ppMemoryErrorReason :: IsExpr (SymExpr sym) => MemoryErrorReason sym w -> Doc ann
ppMemoryErrorReason :: MemoryErrorReason -> Doc ann
ppMemoryErrorReason =
\case
TypeMismatch ty1 ty2 ->
Expand All @@ -170,20 +191,19 @@ ppMemoryErrorReason =
"Load from invalid memory at type" <+> ppType ty
Invalidated msg ->
"Load from explicitly invalidated memory:" <+> pretty msg
NoSatisfyingWrite tp ptr ->
NoSatisfyingWrite tp ->
vcat
[ "No previous write to this location was found"
, indent 2 ("Attempting load at type:" <+> ppType tp)
, indent 2 ("Via pointer:" <+> ppPtr ptr)
]
UnwritableRegion ->
"The region wasn't allocated, wasn't large enough, or was marked as readonly"
UnreadableRegion ->
"The region wasn't allocated or wasn't large enough"
BadFunctionPointer msg ->
BadFunctionPointer err ->
vcat
[ "The given pointer could not be resolved to a callable function"
, unAnnotate msg
, ppFuncLookupError err
]
OverlappingRegions ->
"Memory regions required to be disjoint"
Expand All @@ -194,7 +214,7 @@ concMemoryError ::
(forall tp. SymExpr sym tp -> IO (GroundValue tp)) ->
MemoryError sym -> IO (MemoryError sym)
concMemoryError sym conc (MemoryError mop rsn) =
MemoryError <$> concMemoryOp sym conc mop <*> concMemoryErrorReason sym conc rsn
MemoryError <$> concMemoryOp sym conc mop <*> pure rsn

concMemoryOp ::
(1 <= w, IsExprBuilder sym) =>
Expand Down Expand Up @@ -223,20 +243,3 @@ concMemoryOp sym conc (MemInvalidateOp msg gsym ptr len mem) =
concPtr sym conc ptr <*>
concBV sym conc len <*>
concMem sym conc mem

concMemoryErrorReason ::
(1 <= w, IsExprBuilder sym) =>
sym ->
(forall tp. SymExpr sym tp -> IO (GroundValue tp)) ->
MemoryErrorReason sym w -> IO (MemoryErrorReason sym w)
concMemoryErrorReason sym conc rsn = case rsn of
TypeMismatch t1 t2 -> pure (TypeMismatch t1 t2)
UnexpectedArgumentType msg ts -> pure (UnexpectedArgumentType msg ts)
ApplyViewFail v -> pure (ApplyViewFail v)
Invalid tp -> pure (Invalid tp)
Invalidated msg -> pure (Invalidated msg)
NoSatisfyingWrite tp ptr -> NoSatisfyingWrite tp <$> concPtr sym conc ptr
UnwritableRegion -> pure UnwritableRegion
UnreadableRegion -> pure UnreadableRegion
BadFunctionPointer msg -> pure (BadFunctionPointer msg)
OverlappingRegions -> pure OverlappingRegions
36 changes: 14 additions & 22 deletions crucible-llvm/src/Lang/Crucible/LLVM/MemModel.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ module Lang.Crucible.LLVM.MemModel
, G.AllocType(..)
, G.Mutability(..)
, doMallocHandle
, ME.FuncLookupError(..)
, ME.ppFuncLookupError
, doLookupHandle
, doInstallHandle
, doMemcpy
Expand Down Expand Up @@ -202,7 +204,6 @@ import Data.Text (Text)
import Data.Word
import GHC.TypeNats
import Numeric.Natural
import Prettyprinter
import System.IO (Handle, hPutStrLn)

import qualified Data.BitVector.Sized as BV
Expand Down Expand Up @@ -233,6 +234,7 @@ import Lang.Crucible.LLVM.Extension
import Lang.Crucible.LLVM.Bytes
import Lang.Crucible.LLVM.Errors.MemoryError
(MemErrContext, MemoryErrorReason(..), MemoryOp(..), ppMemoryErrorReason)
import qualified Lang.Crucible.LLVM.Errors.MemoryError as ME
import qualified Lang.Crucible.LLVM.Errors.UndefinedBehavior as UB
import Lang.Crucible.LLVM.MemType
import qualified Lang.Crucible.LLVM.MemModel.MemLog as ML
Expand Down Expand Up @@ -315,7 +317,7 @@ assertStoreError ::
(IsSymInterface sym, Partial.HasLLVMAnn sym, 1 <= wptr) =>
sym ->
MemErrContext sym wptr ->
MemoryErrorReason sym wptr ->
MemoryErrorReason ->
Pred sym ->
IO ()
assertStoreError sym errCtx rsn p =
Expand Down Expand Up @@ -428,14 +430,14 @@ evalStmt sym = eval
eval (LLVM_LoadHandle mvar ltp (regValue -> ptr) args ret) =
do mem <- getMem mvar
let gsym = unsymbol <$> isGlobalPointer (memImplSymbolMap mem) ptr
mhandle <- liftIO $ doLookupHandle sym mem ptr gsym
mhandle <- liftIO $ doLookupHandle sym mem ptr
let mop = MemLoadHandleOp ltp gsym ptr (memImplHeap mem)
let expectedTp = FunctionHandleRepr args ret
case mhandle of
Left doc -> lift $
do p <- Partial.annotateME sym mop (BadFunctionPointer doc) (falsePred sym)
Left lookupErr -> lift $
do p <- Partial.annotateME sym mop (BadFunctionPointer lookupErr) (falsePred sym)
loc <- getCurrentProgramLoc sym
let err = SimError loc (AssertFailureSimError "Failed to load function handle" (show doc))
let err = SimError loc (AssertFailureSimError "Failed to load function handle" (show (ME.ppFuncLookupError lookupErr)))
addProofObligation sym (LabeledPred p err)
abortExecBecause (AssertionFailure err)

Expand Down Expand Up @@ -748,29 +750,19 @@ doLookupHandle
=> sym
-> MemImpl sym
-> LLVMPtr sym wptr
-> Maybe String
-> IO (Either (Doc ann) a)
doLookupHandle _sym mem ptr gsym = do
-> IO (Either ME.FuncLookupError a)
doLookupHandle _sym mem ptr = do
let LLVMPointer blk _ = ptr
let ptrDoc = hang 2 $
case gsym of
Just s -> viaShow s
Nothing -> ppPtr ptr
case asNat blk of
Nothing -> return (Left ("Cannot resolve a symbolic pointer to a function handle:" <+> ptrDoc))
Nothing -> return (Left ME.SymbolicPointer)
Just i
| i == 0 -> return (Left ("Cannot treat raw bitvector as function pointer:" <+> ptrDoc))
| i == 0 -> return (Left ME.RawBitvector)
| otherwise ->
case Map.lookup i (memImplHandleMap mem) of
Nothing -> return (Left ("No implementation or override found for pointer:" <+> ptrDoc))
Nothing -> return (Left ME.NoOverride)
Just x ->
case fromDynamic x of
Nothing ->
return $ Left $ vcat
[ "Data associated with the pointer found, but was not a callable function:"
, hang 2 (viaShow (dynTypeRep x))
, ptrDoc
]
Nothing -> return (Left (ME.Uncallable (dynTypeRep x)))
Just a -> return (Right a)

-- | Free the memory region pointed to by the given pointer.
Expand Down
4 changes: 2 additions & 2 deletions crucible-llvm/src/Lang/Crucible/LLVM/MemModel/Generic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ readMem' sym w end gsym l0 origMem tp0 alignment (MemWrites ws) =
StorageType ->
LLVMPtr sym w ->
ReadMem sym (PartLLVMVal sym)
fallback0 tp l =
fallback0 tp _l =
liftIO $
if laxLoadsAndStores ?memOpts
then Partial.totalLLVMVal sym <$> freshLLVMVal sym tp
Expand All @@ -779,7 +779,7 @@ readMem' sym w end gsym l0 origMem tp0 alignment (MemWrites ws) =
-- and we can be relatively sure the annotation will survive.
b <- freshConstant sym emptySymbol BaseBoolRepr
Partial.Err <$>
Partial.annotateME sym mop (NoSatisfyingWrite tp l) b
Partial.annotateME sym mop (NoSatisfyingWrite tp) b

go :: (StorageType -> LLVMPtr sym w -> ReadMem sym (PartLLVMVal sym)) ->
LLVMPtr sym w ->
Expand Down
6 changes: 3 additions & 3 deletions crucible-llvm/src/Lang/Crucible/LLVM/MemModel/Partial.hs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ annotateUB sym ub p =
annotateME :: (IsSymInterface sym, HasLLVMAnn sym, 1 <= w) =>
sym ->
MemoryOp sym w ->
MemoryErrorReason sym w ->
MemoryErrorReason ->
Pred sym ->
IO (Pred sym)
annotateME sym mop rsn p =
Expand All @@ -271,7 +271,7 @@ data PartLLVMVal sym where
NoErr :: Pred sym -> LLVMVal sym -> PartLLVMVal sym

partErr :: (IsSymInterface sym, HasLLVMAnn sym, 1 <= w) =>
sym -> MemoryOp sym w -> MemoryErrorReason sym w -> IO (PartLLVMVal sym)
sym -> MemoryOp sym w -> MemoryErrorReason -> IO (PartLLVMVal sym)
partErr sym errCtx rsn =
do p <- annotateME sym errCtx rsn (falsePred sym)
pure (Err p)
Expand All @@ -295,7 +295,7 @@ attachMemoryError ::
sym ->
Pred sym ->
MemoryOp sym w ->
MemoryErrorReason sym w ->
MemoryErrorReason ->
PartLLVMVal sym ->
IO (PartLLVMVal sym)
attachMemoryError sym pnew mop rsn pv =
Expand Down
4 changes: 2 additions & 2 deletions crux-llvm/test-data/golden/golden/invoke-test.good
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
[Crux] internal: error: in _ZN3std2rt10lang_start17h4f32aa1279b9079fE
[Crux] Failed to load function handle
[Crux] Details:
[Crux] No implementation or override found for pointer: "_ZN3std2rt19lang_start_internal17h3dc68cf5532522d7E"
[Crux] No implementation or override found for pointer
[Crux] The given pointer could not be resolved to a callable function
[Crux] No implementation or override found for pointer: "_ZN3std2rt19lang_start_internal17h3dc68cf5532522d7E"
[Crux] No implementation or override found for pointer
[Crux] Attempting to load callable function with type: i64({ }*, [3 x i64]*, i64, i8**)
[Crux] Via pointer: Global symbol "_ZN3std2rt19lang_start_internal17h3dc68cf5532522d7E" (1, 0x0:[64])
Comment on lines -5 to 9
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the function name that is removed from this message appears here at line 9. It was just duplicated between the MemoryOp and the MemoryErrorReason.

[Crux] In memory state:
Expand Down
4 changes: 2 additions & 2 deletions uc-crux-llvm/src/UCCrux/LLVM/Classify.hs
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,8 @@ doClassifyBadBehavior appCtx modCtx funCtx sym memImpl skipped simError (Crucibl
requirePossiblePointer ReadNonPointer ptr
LLVMErrors.BBMemoryError
( MemError.MemoryError
(summarizeOp -> (_expl, _ptr, mem))
(MemError.NoSatisfyingWrite _storageType ptr)
(summarizeOp -> (_expl, ptr, mem))
(MemError.NoSatisfyingWrite _storageType)
) ->
do
ann <- liftIO $ getPtrBlockOrOffsetAnn ptr
Expand Down