Skip to content

Commit 706f25b

Browse files
Merge pull request #1543 from GaloisInc/heapster/add-false-permission
Heapster: Add support for the trivially false permission
2 parents a07c01c + 399e0bb commit 706f25b

File tree

11 files changed

+137
-1
lines changed

11 files changed

+137
-1
lines changed

heapster-saw/examples/rust_data.bc

9.84 KB
Binary file not shown.

heapster-saw/examples/rust_data.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use std::collections::{HashMap, HashSet};
22
use std::fmt;
33

4+
/* A function that immediately panics */
5+
pub fn get_out () -> ! {
6+
panic!("Uh oh!")
7+
}
48

59
/* The logical and operation as a function on bool */
610
pub fn bool_and (x:bool, y:bool) -> bool {

heapster-saw/examples/rust_data.saw

+9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ heapster_define_rust_type env "pub enum Sum<X,Y> { Left (X), Right (Y) }";
3333
// The Option type
3434
heapster_define_rust_type env "pub enum Option<X> { None, Some (X) }";
3535

36+
// Location type from std::panic
37+
heapster_define_llvmshape env "panic::Location" 64 ""
38+
"exsh len:bv 64.ptrsh(arraysh(<len,*1,fieldsh(8,int8<>))); fieldsh(eq(llvmword(len))); u32<>; u32<>";
39+
3640
// The str type
3741
// For now we have to define the shape explicitly without the int8 name because
3842
// we don't yet have implications on array cells
@@ -395,10 +399,15 @@ Formatter__write_fmt_sym <- heapster_find_symbol env "9Formatter9write_fmt";
395399
heapster_assume_fun_rename_prim env Formatter__write_fmt_sym "Formatter__write_fmt"
396400
"<'a> fn (&'a mut fmt::Formatter, fmt::Arguments) -> fmt::Result";
397401

402+
// std::panicking::begin_panic
403+
begin_panic_sym <- heapster_find_symbol env "3std9panicking11begin_panic17";
404+
heapster_assume_fun_rename_prim env begin_panic_sym "begin_panic" "<'a, 'b> fn(&'a str, &'b panic::Location) -> !";
398405

399406
/***
400407
*** Type-Checked Functions
401408
***/
409+
get_out_sym <- heapster_find_symbol env "7get_out";
410+
heapster_typecheck_fun_rename env get_out_sym "get_out" "<> fn() -> !";
402411

403412
// bool_and
404413
bool_and_sym <- heapster_find_symbol env "8bool_and";

heapster-saw/src/Verifier/SAW/Heapster/IRTTranslation.hs

+3
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ instance ContainsIRTRecName (ValuePerm a) where
132132
containsIRTRecName n args
133133
containsIRTRecName _ (ValPerm_Var _ _) = False
134134
containsIRTRecName n (ValPerm_Conj ps) = containsIRTRecName n ps
135+
containsIRTRecName _ ValPerm_False = False
135136

136137
instance ContainsIRTRecName (RAssign ValuePerm tps) where
137138
containsIRTRecName _ MNil = False
@@ -318,6 +319,7 @@ instance IRTTyVars (ValuePerm a) where
318319
[nuMP| ValPerm_Var x _ |] ->
319320
irtTTranslateVar mb_p x
320321
[nuMP| ValPerm_Conj ps |] -> irtTyVars ps
322+
[nuMP| ValPerm_False |] -> return ([], IRTVarsNil)
321323

322324
-- | Get all IRT type variables in a binding, including any type variables
323325
-- from the bound variable
@@ -468,6 +470,7 @@ instance IRTTyVars (PermExpr (LLVMShapeType w)) where
468470
(tps2, ixs2) <- irtTyVars sh2
469471
return (tps1 ++ tps2, IRTVarsAppend ixs1 ixs2)
470472
[nuMP| PExpr_ExShape sh |] -> irtTyVars sh -- see the instance for Binding!
473+
[nuMP| PExpr_FalseShape |] -> return ([], IRTVarsNil)
471474

472475
-- | Get all IRT type variables in a field shape
473476
instance IRTTyVars (LLVMFieldShape w) where

heapster-saw/src/Verifier/SAW/Heapster/Implication.hs

+47
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,13 @@ data SimplImpl ps_in ps_out where
11311131
(1 <= w, KnownNat w) => ExprVar (LLVMPointerType w) -> LLVMBlockPerm w ->
11321132
SimplImpl (RNil :> LLVMPointerType w) (RNil :> LLVMPointerType w)
11331133

1134+
-- | Eliminate a block of shape @falsesh@ to @false@
1135+
--
1136+
-- > x:memblock(..., falsesh) -o x:false
1137+
SImpl_ElimLLVMBlockFalse ::
1138+
(1 <= w, KnownNat w) => ExprVar (LLVMPointerType w) -> LLVMBlockPerm w ->
1139+
SimplImpl (RNil :> LLVMPointerType w) (RNil :> LLVMPointerType w)
1140+
11341141
-- | Fold a named permission (other than an opaque permission):
11351142
--
11361143
-- > x:(unfold P args) -o x:P<args>
@@ -1278,6 +1285,12 @@ data PermImpl1 ps_in ps_outs where
12781285
Binding tp (ValuePerm a) ->
12791286
PermImpl1 (ps :> a) (RNil :> '(RNil :> tp, ps :> a))
12801287

1288+
-- | Eliminate a @false@ permission on the top of the stack, which is a
1289+
-- contradiction and so has no output disjuncts
1290+
--
1291+
-- > ps * x:false -o .
1292+
Impl1_ElimFalse :: ExprVar a -> PermImpl1 (ps :> a) RNil
1293+
12811294
-- | Apply a 'SimplImpl'
12821295
Impl1_Simpl :: SimplImpl ps_in ps_out -> Proxy ps ->
12831296
PermImpl1 (ps :++: ps_in) (RNil :> '(RNil, ps :++: ps_out))
@@ -1622,6 +1635,7 @@ permImplSucceeds (PermImpl_Step (Impl1_ElimOr _ _ _)
16221635
permImplSucceeds (PermImpl_Step (Impl1_ElimExists _ _)
16231636
(MbPermImpls_Cons _ _ mb_impl)) =
16241637
mbLift $ fmap permImplSucceeds mb_impl
1638+
permImplSucceeds (PermImpl_Step (Impl1_ElimFalse _) _) = 2
16251639
permImplSucceeds (PermImpl_Step (Impl1_Simpl _ _)
16261640
(MbPermImpls_Cons _ _ mb_impl)) =
16271641
mbLift $ fmap permImplSucceeds mb_impl
@@ -1949,6 +1963,8 @@ simplImplIn (SImpl_IntroLLVMBlockEx x bp) =
19491963
error "simplImplIn: SImpl_IntroLLVMBlockEx: non-existential shape"
19501964
simplImplIn (SImpl_ElimLLVMBlockEx x bp) =
19511965
distPerms1 x (ValPerm_LLVMBlock bp)
1966+
simplImplIn (SImpl_ElimLLVMBlockFalse x bp) =
1967+
distPerms1 x (ValPerm_LLVMBlock bp)
19521968
simplImplIn (SImpl_FoldNamed x np args off) =
19531969
distPerms1 x (unfoldPerm np args off)
19541970
simplImplIn (SImpl_UnfoldNamed x np args off) =
@@ -2295,6 +2311,11 @@ simplImplOut (SImpl_ElimLLVMBlockEx x bp) =
22952311
ValPerm_LLVMBlock (bp { llvmBlockShape = sh }))
22962312
_ ->
22972313
error "simplImplOut: SImpl_ElimLLVMBlockEx: non-existential shape"
2314+
simplImplOut (SImpl_ElimLLVMBlockFalse x bp) =
2315+
case llvmBlockShape bp of
2316+
PExpr_FalseShape ->
2317+
distPerms1 x ValPerm_False
2318+
_ -> error "simplImplOut: SImpl_ElimLLVMBlockFalse: non-false shape"
22982319
simplImplOut (SImpl_FoldNamed x np args off) =
22992320
distPerms1 x (ValPerm_Named (namedPermName np) args off)
23002321
simplImplOut (SImpl_UnfoldNamed x np args off) =
@@ -2396,6 +2417,11 @@ applyImpl1 _ (Impl1_ElimExists x p_body) ps =
23962417
mbPermSets1 (fmap (\p -> set (topDistPerm x) p ps) p_body)
23972418
else
23982419
error "applyImpl1: Impl1_ElimExists: unexpected permission"
2420+
applyImpl1 _ (Impl1_ElimFalse x) ps =
2421+
if ps ^. topDistPerm x == ValPerm_False then
2422+
MbPermSets_Nil
2423+
else
2424+
error "applyImpl1: Impl1_ElimFalse: unexpected permission"
23992425
applyImpl1 pp_info (Impl1_Simpl simpl prx) ps =
24002426
mbPermSets1 $ emptyMb $ applySimplImpl pp_info prx simpl ps
24012427
applyImpl1 _ (Impl1_LetBind tp e) ps =
@@ -2776,6 +2802,8 @@ instance SubstVar PermVarSubst m =>
27762802
SImpl_IntroLLVMBlockEx <$> genSubst s x <*> genSubst s bp
27772803
[nuMP| SImpl_ElimLLVMBlockEx x bp |] ->
27782804
SImpl_ElimLLVMBlockEx <$> genSubst s x <*> genSubst s bp
2805+
[nuMP| SImpl_ElimLLVMBlockFalse x bp |] ->
2806+
SImpl_ElimLLVMBlockFalse <$> genSubst s x <*> genSubst s bp
27792807
[nuMP| SImpl_FoldNamed x np args off |] ->
27802808
SImpl_FoldNamed <$> genSubst s x <*> genSubst s np <*> genSubst s args
27812809
<*> genSubst s off
@@ -2822,6 +2850,8 @@ instance SubstVar PermVarSubst m =>
28222850
Impl1_ElimOr <$> genSubst s x <*> genSubst s p1 <*> genSubst s p2
28232851
[nuMP| Impl1_ElimExists x p_body |] ->
28242852
Impl1_ElimExists <$> genSubst s x <*> genSubst s p_body
2853+
[nuMP| Impl1_ElimFalse x |] ->
2854+
Impl1_ElimFalse <$> genSubst s x
28252855
[nuMP| Impl1_Simpl simpl prx |] ->
28262856
Impl1_Simpl <$> genSubst s simpl <*> return (mbLift prx)
28272857
[nuMP| Impl1_LetBind tp e |] ->
@@ -3405,6 +3435,12 @@ implElimExistsM x p =
34053435
implApplyImpl1 (Impl1_ElimExists x p)
34063436
(MNil :>: Impl1Cont (const $ pure ()))
34073437

3438+
-- | Eliminate a false permission in the current permission set
3439+
implElimFalseM :: NuMatchingAny1 r => ExprVar a ->
3440+
ImplM vars s r ps_any (ps :> a) ()
3441+
implElimFalseM x =
3442+
implApplyImpl1 (Impl1_ElimFalse x) MNil
3443+
34083444
-- | Apply a simple implication rule to the top permissions on the stack
34093445
implSimplM :: HasCallStack => NuMatchingAny1 r => Proxy ps ->
34103446
SimplImpl ps_in ps_out ->
@@ -4704,6 +4740,10 @@ implElimLLVMBlock x bp@(LLVMBlockPerm { llvmBlockShape =
47044740
PExpr_ExShape _mb_sh }) =
47054741
implSimplM Proxy (SImpl_ElimLLVMBlockEx x bp)
47064742

4743+
implElimLLVMBlock x bp@(LLVMBlockPerm { llvmBlockShape =
4744+
PExpr_FalseShape }) =
4745+
implSimplM Proxy (SImpl_ElimLLVMBlockFalse x bp)
4746+
47074747
-- If none of the above cases matched, we cannot eliminate, so fail
47084748
implElimLLVMBlock _ bp =
47094749
implTraceM (\i -> pretty "Could not eliminate permission" <+>
@@ -4967,6 +5007,7 @@ recombinePermExpl x x_p p =
49675007
recombinePerm' :: NuMatchingAny1 r => ExprVar a -> ValuePerm a -> ValuePerm a ->
49685008
ImplM vars s r as (as :> a) ()
49695009
recombinePerm' x _ p@ValPerm_True = implDropM x p
5010+
recombinePerm' x _ ValPerm_False = implElimFalseM x
49705011
recombinePerm' x _ p@(ValPerm_Eq (PExpr_Var y)) | y == x = implDropM x p
49715012
recombinePerm' x ValPerm_True (ValPerm_Eq e) =
49725013
simplEqPerm x e >>>= \e' -> implPopM x (ValPerm_Eq e')
@@ -5090,6 +5131,12 @@ recombinePermConj x x_ps (Perm_LLVMBlock bp)
50905131
getTopDistPerm x >>>= \p ->
50915132
recombinePerm x p
50925133

5134+
-- If p is a memblock permission on the false shape, eliminate the block to
5135+
-- a false permission (and eliminate the false permission itself)
5136+
recombinePermConj x _ (Perm_LLVMBlock bp)
5137+
| PExpr_FalseShape <- llvmBlockShape bp
5138+
= implElimLLVMBlock x bp >>> implElimFalseM x
5139+
50935140
-- Default case: insert p at the end of the x_ps
50945141
recombinePermConj x x_ps p =
50955142
implPushM x (ValPerm_Conj x_ps) >>>

heapster-saw/src/Verifier/SAW/Heapster/LLVMGlobalConst.hs

+13-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Control.Monad.Reader
1616
import GHC.TypeLits
1717
import qualified Text.PrettyPrint.HughesPJ as PPHPJ
1818

19+
import qualified Data.BitVector.Sized as BV
1920
import qualified Text.LLVM.AST as L
2021
import qualified Text.LLVM.PP as L
2122

@@ -118,14 +119,25 @@ translateLLVMValue w _ (L.ValPackedStruct elems) =
118119
mapM (translateLLVMTypedValue w) elems >>= \(unzip -> (shs,ts)) ->
119120
return (foldr PExpr_SeqShape PExpr_EmptyShape shs, tupleOpenTerm ts)
120121
translateLLVMValue _ _ (L.ValString []) = mzero
122+
translateLLVMValue _ _ (L.ValString bytes) =
123+
let sh =
124+
foldr1 PExpr_SeqShape $
125+
map (PExpr_FieldShape . LLVMFieldShape . ValPerm_Eq .
126+
PExpr_LLVMWord . bvBV . BV.word8) bytes in
127+
return (sh, unitOpenTerm)
128+
-- NOTE: we don't translate strings to one big bitvector value because that
129+
-- seems to mess up the endianness
130+
{-
121131
translateLLVMValue _ _ (L.ValString bytes) =
122132
do endianness <- llvmTransInfoEndianness <$> ask
123133
case bvFromBytes endianness bytes of
124134
Some (BVExpr e) ->
125135
return (PExpr_FieldShape (LLVMFieldShape $
126136
ValPerm_Eq $ PExpr_LLVMWord e),
127137
unitOpenTerm)
128-
138+
-}
139+
-- NOTE: we don't convert string values to arrays because we sometimes need to
140+
-- statically know the values of the bytes in a string value as eq perms
129141
{-
130142
translateLLVMValue w tp (L.ValString bytes) =
131143
translateLLVMValue w tp (L.ValArray

0 commit comments

Comments
 (0)