-
Notifications
You must be signed in to change notification settings - Fork 393
/
Copy pathCorpus.hs
129 lines (110 loc) · 3.53 KB
/
Corpus.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
module Echidna.Mutator.Corpus where
import Control.Monad.Random.Strict (MonadRandom, getRandomR, weighted)
import Data.Set qualified as Set
import Echidna.Mutator.Array
import Echidna.Transaction (mutateTx, shrinkTx)
import Echidna.Types (MutationConsts)
import Echidna.Types.Tx (Tx)
import Echidna.Types.Corpus
defaultMutationConsts :: Num a => MutationConsts a
defaultMutationConsts = (1, 1, 1, 1, 1)
fromConsts :: Num a => MutationConsts Integer -> MutationConsts a
fromConsts (a, b, c, d, e) = let fi = fromInteger in (fi a, fi b, fi c, fi d, fi e)
data TxsMutation = Identity
| Shrinking
| Mutation
| Expansion
| Swapping
| Deletion
deriving (Eq, Ord, Show)
data CorpusMutation = RandomAppend TxsMutation
| RandomPrepend TxsMutation
| RandomSplice
| RandomInterleave
| RemoveReverts
deriving (Eq, Ord, Show)
mutator :: MonadRandom m => TxsMutation -> [Tx] -> m [Tx]
mutator Identity = return
mutator Shrinking = mapM shrinkTx
mutator Mutation = mapM mutateTx
mutator Expansion = expandRandList
mutator Swapping = swapRandList
mutator Deletion = deleteRandList
selectAndMutate
:: MonadRandom m
=> ([Tx] -> m [Tx])
-> Corpus
-> m [Tx]
selectAndMutate f corpus = do
rtxs <- selectFromCorpus corpus
k <- getRandomR (0, length rtxs - 1)
f $ take k rtxs
selectAndCombine
:: MonadRandom m
=> ([Tx] -> [Tx] -> m [Tx])
-> Int
-> Corpus
-> [Tx]
-> m [Tx]
selectAndCombine f ql corpus gtxs = do
rtxs1 <- selectFromCorpus corpus
rtxs2 <- selectFromCorpus corpus
txs <- f rtxs1 rtxs2
pure . take ql $ txs <> gtxs
selectFromCorpus
:: MonadRandom m
=> Corpus
-> m [Tx]
selectFromCorpus =
weighted . map (\(i, txs) -> (txs, fromIntegral i)) . Set.toDescList . fst
getCorpusMutation
:: MonadRandom m
=> CorpusMutation
-> (Int -> Corpus -> [Tx] -> m [Tx])
getCorpusMutation (RandomAppend m) = mut (mutator m)
where
mut f ql ctxs gtxs = do
rtxs' <- selectAndMutate f ctxs
pure . take ql $ rtxs' ++ gtxs
getCorpusMutation (RandomPrepend m) = mut (mutator m)
where
mut f ql ctxs gtxs = do
rtxs' <- selectAndMutate f ctxs
k <- getRandomR (0, ql - 1)
pure . take ql $ take k gtxs ++ rtxs'
getCorpusMutation RandomSplice = selectAndCombine spliceAtRandom
getCorpusMutation RandomInterleave = selectAndCombine interleaveAtRandom
getCorpusMutation RemoveReverts = \_ (_, revertingTxs) txs -> pure $ filter (not . flip Set.member revertingTxs) txs
seqMutatorsStateful
:: MonadRandom m
=> MutationConsts Rational
-> m CorpusMutation
seqMutatorsStateful (c1, c2, c3, c4, c5) = weighted
[(RandomAppend Identity, 800),
(RandomPrepend Identity, 200),
(RandomAppend Shrinking, c1),
(RandomAppend Mutation, c2),
(RandomAppend Expansion, c3),
(RandomAppend Swapping, c3),
(RandomAppend Deletion, c3),
(RandomPrepend Shrinking, c1),
(RandomPrepend Mutation, c2),
(RandomPrepend Expansion, c3),
(RandomPrepend Swapping, c3),
(RandomPrepend Deletion, c3),
(RandomSplice, c4),
(RandomInterleave, c4),
(RemoveReverts, c5)
]
seqMutatorsStateless
:: MonadRandom m
=> MutationConsts Rational
-> m CorpusMutation
seqMutatorsStateless (c1, c2, _, _, _) = weighted
[(RandomAppend Identity, 800),
(RandomPrepend Identity, 200),
(RandomAppend Shrinking, c1),
(RandomAppend Mutation, c2),
(RandomPrepend Shrinking, c1),
(RandomPrepend Mutation, c2)
]