Skip to content

Commit f9b6194

Browse files
authored
Merge pull request #1773 from GaloisInc/T1768
Fix two bugs in SAWCore's handing of infinite streams
2 parents bde217a + 938d7f7 commit f9b6194

File tree

12 files changed

+91
-8
lines changed

12 files changed

+91
-8
lines changed

intTests/test1703/Makefile

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CC = clang
2+
CFLAGS = -g -emit-llvm -frecord-command-line -O0
3+
4+
all: test.bc
5+
6+
test.bc: test.c
7+
$(CC) $(CFLAGS) -c $< -o $@
8+
9+
.PHONY: clean
10+
clean:
11+
rm -f test.bc

intTests/test1703/test.bc

2.92 KB
Binary file not shown.

intTests/test1703/test.c

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include <stdint.h>
2+
3+
uint32_t weird(uint32_t cv[8], uint8_t i) {
4+
return cv[i % 8];
5+
}

intTests/test1703/test.cry

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
weird : [8][32] -> [8] -> [32]
2+
weird cv i = k
3+
where
4+
k = cvs @ i
5+
cvs = cv # cvs

intTests/test1703/test.saw

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import "test.cry";
2+
3+
let weird_spec = do {
4+
cv <- llvm_fresh_var "cv" (llvm_array 8 (llvm_int 32));
5+
cv_p <- llvm_alloc (llvm_array 8 (llvm_int 32));
6+
llvm_points_to cv_p (llvm_term {{ cv }});
7+
i <- llvm_fresh_var "i" (llvm_int 8);
8+
9+
llvm_execute_func [cv_p, llvm_term i];
10+
11+
llvm_return (llvm_term {{ weird cv i }});
12+
};
13+
14+
m <- llvm_load_module "test.bc";
15+
llvm_verify m "weird" [] false weird_spec (w4_unint_z3 []);

intTests/test1703/test.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
set -e
2+
3+
$SAW test.saw

intTests/test1768/test.cry

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
f : [2] -> [10]
2+
f x = take y
3+
where
4+
y = x # y

intTests/test1768/test.saw

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import "test.cry";
2+
print {{ f 0b11 }};
3+
print {{ f 0b10 }};
4+
print {{ f 0b00 }};
5+
sat z3 {{ \x -> f x == zero }};

intTests/test1768/test.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
set -e
2+
3+
$SAW test.saw

saw-core-sbv/src/Verifier/SAW/Simulator/SBV.hs

+11-3
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ lazyMux muxFn c tm fm =
314314
f <- fm
315315
muxFn c t f
316316

317-
-- selectV merger maxValue valueFn index returns valueFn v when index has value v
318-
-- if index is greater than maxValue, it returns valueFn maxValue. Use the ite op from merger.
317+
-- @selectV merger maxValue valueFn vx@ treats @vx@ as an index, represented
318+
-- as a big-endian list of bits. It does a binary lookup, using @merger@ as an
319+
-- if-then-else operator. If the index is greater than @maxValue@, then it
320+
-- returns @valueFn maxValue@.
319321
selectV :: (SBool -> b -> b -> b) -> Natural -> (Natural -> b) -> SWord -> b
320322
selectV merger maxValue valueFn vx =
321323
case svAsInteger vx of
@@ -326,7 +328,13 @@ selectV merger maxValue valueFn vx =
326328
where
327329
impl _ x | x > maxValue || x < 0 = valueFn maxValue
328330
impl 0 y = valueFn y
329-
impl i y = merger (svTestBit vx j) (impl j (y `setBit` j)) (impl j y) where j = i - 1
331+
impl i y =
332+
-- NB: `i` counts down in each iteration, so we use svTestBit (a
333+
-- little-endian indexing function) to ensure that the bits are processed
334+
-- in big-endian order. Alternatively, we could have `i` count up and use
335+
-- svAt (a big-endian indexing function), but we use svTestBit as it is
336+
-- slightly cheaper to compute.
337+
merger (svTestBit vx j) (impl j (y `setBit` j)) (impl j y) where j = i - 1
330338

331339
-- Big-endian version of svTestBit
332340
svAt :: SWord -> Int -> SBool

saw-core-what4/src/Verifier/SAW/Simulator/What4.hs

+10-3
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,10 @@ lazyMux muxFn c tm fm =
580580
f <- fm
581581
muxFn c t f
582582

583-
-- selectV merger maxValue valueFn index returns valueFn v when index has value v
584-
-- if index is greater than maxValue, it returns valueFn maxValue. Use the ite op from merger.
583+
-- @selectV sym merger maxValue valueFn vx@ treats @vx@ as an index, represented
584+
-- as a big-endian list of bits. It does a binary lookup, using @merger@ as an
585+
-- if-then-else operator. If the index is greater than @maxValue@, then it
586+
-- returns @valueFn maxValue@.
585587
selectV :: forall sym b.
586588
Sym sym =>
587589
sym ->
@@ -595,7 +597,12 @@ selectV sym merger maxValue valueFn vx =
595597
impl _ x | x > maxValue || x < 0 = valueFn maxValue
596598
impl 0 y = valueFn y
597599
impl i y = do
598-
p <- SW.bvAtBE sym vx (toInteger j)
600+
-- NB: `i` counts down in each iteration, so we use bvAtLE (a
601+
-- little-endian indexing function) to ensure that the bits are processed
602+
-- in big-endian order. Alternatively, we could have `i` count up and use
603+
-- bvAtBE (a big-endian indexing function), but we use bvAtLE as it is
604+
-- slightly cheaper to compute.
605+
p <- SW.bvAtLE sym vx (toInteger j)
599606
merger p (impl j (y `setBit` j)) (impl j y) where j = i - 1
600607

601608
instance Show (SArray sym) where

saw-core/src/Verifier/SAW/Simulator/Prims.hs

+19-2
Original file line numberDiff line numberDiff line change
@@ -769,21 +769,38 @@ atWithDefaultOp bp =
769769
VNat i ->
770770
case x of
771771
VVector xv -> lift (force (vecIdx d xv (fromIntegral i))) -- FIXME dangerous fromIntegral
772-
VWord xw -> lift (VBool <$> bpBvAt bp xw (fromIntegral i)) -- FIXME dangerous fromIntegral
772+
VWord xw -> lift (bpBvAtWithDefault bp (fromIntegral n) (force d) xw (fromIntegral i)) -- FIXME dangerous fromIntegral
773773
_ -> throwE "atOp: expected vector"
774774
VBVToNat _sz i | bpIsSymbolicEvaluator bp -> do
775775
iv <- lift (toBits (bpUnpack bp) i)
776776
case x of
777777
VVector xv ->
778778
lift $ selectV (lazyMuxValue bp tp) (fromIntegral n - 1) (force . vecIdx d xv) iv -- FIXME dangerous fromIntegral
779779
VWord xw ->
780-
lift $ selectV (lazyMuxValue bp tp) (fromIntegral n - 1) (liftM VBool . bpBvAt bp xw) iv -- FIXME dangerous fromIntegral
780+
lift $ selectV (lazyMuxValue bp tp) (fromIntegral n - 1) (bpBvAtWithDefault bp (fromIntegral n) (force d) xw) iv -- FIXME dangerous fromIntegral
781781
_ -> throwE "atOp: expected vector"
782782

783783
VIntToNat _i | bpIsSymbolicEvaluator bp -> panic "atWithDefault: symbolic integer TODO"
784784

785785
_ -> throwE $ "atOp: expected Nat, got " <> Text.pack (show idx)
786786

787+
-- | @bpBvAtWithDefault bp w d vw i@ returns @bpBvAt bp vw i@ if @i@ is between
788+
-- @0@ (inclusive) and @w@ (exclusive), the bit width of @vw@. Otherwise, it
789+
-- returns @d@.
790+
bpBvAtWithDefault ::
791+
VMonad l =>
792+
BasePrims l ->
793+
Int ->
794+
MValue l ->
795+
VWord l ->
796+
Int ->
797+
MValue l
798+
bpBvAtWithDefault bp w d vw i
799+
| 0 <= i && i < w
800+
= VBool <$> bpBvAt bp vw i
801+
| otherwise
802+
= d
803+
787804
-- upd :: (n :: Nat) -> (a :: sort 0) -> Vec n a -> Nat -> a -> Vec n a;
788805
updOp :: (VMonadLazy l, Show (Extra l)) => BasePrims l -> Prim l
789806
updOp bp =

0 commit comments

Comments
 (0)