Skip to content

Commit 84c9005

Browse files
insert transactions in a random part of the ones in the corpus
1 parent 9df353f commit 84c9005

File tree

4 files changed

+40
-14
lines changed

4 files changed

+40
-14
lines changed

lib/Echidna/Agent/Fuzzer.hs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import System.Random (mkStdGen)
1818
import Data.IORef (IORef, writeIORef, readIORef, atomicModifyIORef')
1919
import Data.Map (Map)
2020
import qualified Data.Map as Map
21+
import qualified Data.Set as Set
2122
import System.Directory (getCurrentDirectory)
2223

2324
import Echidna.Output.Source (saveLcovHook)
@@ -198,10 +199,10 @@ fuzzerLoop callback vm testLimit bus = do
198199
void $ saveLcovHook env dir env.sourceCache contracts
199200
putStrLn $ "Fuzzer " ++ show workerId ++ ": dumped LCOV coverage."
200201
pure ()
201-
Just (WrappedMessage _ (ToFuzzer tid (FuzzSequence txs))) -> do
202+
Just (WrappedMessage _ (ToFuzzer tid (FuzzSequence txs prob))) -> do
202203
workerId <- gets (.workerId)
203204
when (tid == workerId) $ do
204-
modify' $ \s -> s { prioritizedSequences = txs : s.prioritizedSequences }
205+
modify' $ \s -> s { prioritizedSequences = (prob, txs) : s.prioritizedSequences }
205206
pure ()
206207
Just (WrappedMessage _ (ToFuzzer tid ClearPrioritization)) -> do
207208
workerId <- gets (.workerId)
@@ -233,11 +234,16 @@ randseq deployedContracts = do
233234
seqLen = env.cfg.campaignConf.seqLen
234235

235236
prioritized <- gets (.prioritizedSequences)
236-
usePrioritized <- (<= (0.90 :: Double)) <$> getRandom
237237

238-
if not (null prioritized) && usePrioritized
239-
then do
240-
seqPrototype <- rElem (NE.fromList prioritized)
238+
mbSeq <- if null prioritized
239+
then pure Nothing
240+
else do
241+
(prob, seqPrototype) <- rElem (NE.fromList prioritized)
242+
useIt <- (<= prob) <$> getRandom
243+
pure $ if useIt then Just seqPrototype else Nothing
244+
245+
case mbSeq of
246+
Just seqPrototype -> do
241247
let expandPrototype [] = return []
242248
expandPrototype [p] = do
243249
tx <- genTxFromPrototype world deployedContracts p
@@ -250,14 +256,29 @@ randseq deployedContracts = do
250256
return ((tx : rndTxs) ++ rest)
251257

252258
expandedTxs <- expandPrototype seqPrototype
253-
let len = length expandedTxs
259+
corpusSet <- liftIO $ readIORef env.corpusRef
260+
prefix <- if Set.null corpusSet
261+
then pure []
262+
else do
263+
idx <- getRandomR (0, Set.size corpusSet - 1)
264+
let (_, cTxs) = Set.elemAt idx corpusSet
265+
let middleLen = length expandedTxs
266+
let maxPrefix = seqLen - middleLen
267+
if maxPrefix <= 0
268+
then pure []
269+
else do
270+
k <- getRandomR (0, min (length cTxs) maxPrefix)
271+
pure (take k cTxs)
272+
273+
let combined = prefix ++ expandedTxs
274+
let len = length combined
254275
if len < seqLen
255276
then do
256277
paddingTxs <- replicateM (seqLen - len) (genTx world deployedContracts)
257-
pure (expandedTxs ++ paddingTxs)
278+
pure (combined ++ paddingTxs)
258279
else
259-
pure (take seqLen expandedTxs)
260-
else do
280+
pure (take seqLen combined)
281+
Nothing -> do
261282
-- Generate new random transactions
262283
randTxs <- replicateM seqLen (genTx world deployedContracts)
263284
-- Generate a random mutator

lib/Echidna/MCP.hs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,12 @@ fuzzTransactionTool args env bus _ = do
261261
then return $ "Error:\n" ++ unlines errors
262262
else do
263263
let nWorkers = getNFuzzWorkers env.cfg.campaignConf
264-
mapM_ (\i -> atomically $ writeTChan bus (WrappedMessage AIId (ToFuzzer i (FuzzSequence seqPrototype)))) [0 .. nWorkers - 1]
264+
calcProb i
265+
| i == 0 = 0.0
266+
| nWorkers <= 2 = 0.2
267+
| otherwise = 0.2 + fromIntegral (i - 1) * (0.7 / fromIntegral (nWorkers - 2))
268+
269+
mapM_ (\i -> atomically $ writeTChan bus (WrappedMessage AIId (ToFuzzer i (FuzzSequence seqPrototype (calcProb i))))) [0 .. nWorkers - 1]
265270
return $ printf "Requested fuzzing of transaction sequence '%s' on %d fuzzers" (unpack txStr) nWorkers
266271

267272
-- | Implementation of clear_fuzz_priorities tool

lib/Echidna/Types/Campaign.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ data WorkerState = WorkerState
8787
, runningThreads :: [ThreadId]
8888
-- ^ Extra threads currently being run,
8989
-- aside from the main worker thread
90-
, prioritizedSequences :: ![[(Text, [Maybe AbiValue])]]
90+
, prioritizedSequences :: ![(Double, [(Text, [Maybe AbiValue])])]
9191
-- ^ Sequences of functions to prioritize during fuzzing
9292
}
9393

lib/Echidna/Types/InterWorker.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ data AgentId = FuzzerId Int | SymbolicId | AIId
1515
data FuzzerCmd
1616
= DumpLcov
1717
| SolutionFound [Tx]
18-
| FuzzSequence [(Text, [Maybe AbiValue])]
18+
| FuzzSequence [(Text, [Maybe AbiValue])] Double
1919
| ClearPrioritization
2020
| ExecuteSequence [Tx] (Maybe (TMVar Bool))
2121

2222
instance Show FuzzerCmd where
2323
show DumpLcov = "DumpLcov"
2424
show (SolutionFound txs) = "SolutionFound " ++ show txs
25-
show (FuzzSequence s) = "FuzzSequence " ++ show s
25+
show (FuzzSequence s p) = "FuzzSequence " ++ show s ++ " (" ++ show p ++ ")"
2626
show ClearPrioritization = "ClearPrioritization"
2727
show (ExecuteSequence txs _) = "ExecuteSequence " ++ show txs
2828

0 commit comments

Comments
 (0)