Skip to content

Commit a142ab2

Browse files
committed
Fix recursion check in direct style interpreter
1 parent d7f63ee commit a142ab2

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

pact-repl/Pact/Core/IR/Eval/Direct/Evaluator.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,13 +649,15 @@ sysOnlyEnv e
649649

650650
evalWithStackFrame :: i -> StackFrame i -> Maybe Type -> EvalM e b i (EvalValue e b i) -> EvalM e b i (EvalValue e b i)
651651
evalWithStackFrame info sf mty act = do
652+
checkRecursion
652653
esStack %= (sf:)
653654
#ifdef WITH_FUNCALL_TRACING
654655
timeEnter <- liftIO $ getTime ProcessCPUTime
655656
esTraceOutput %= (TraceFunctionEnter timeEnter sf info:)
656657
#endif
657658
v <- act
658659
esStack %= safeTail
660+
esCheckRecursion %= getPrevRecCheck
659661
pv <- enforcePactValue info v
660662
rtcEnabled <- isExecutionFlagSet FlagDisableRuntimeRTC
661663
unless rtcEnabled $ maybeTCType info mty pv
@@ -664,6 +666,16 @@ evalWithStackFrame info sf mty act = do
664666
esTraceOutput %= (TraceFunctionExit timeExit sf info:)
665667
#endif
666668
return (VPactValue pv)
669+
where
670+
checkRecursion = do
671+
RecursionCheck currentCalled <- uses esCheckRecursion NE.head
672+
let qn = fqnToQualName (_sfName sf)
673+
when (S.member qn currentCalled) $ throwExecutionError info (RuntimeRecursionDetected qn)
674+
esCheckRecursion %= NE.cons (RecursionCheck (S.insert qn currentCalled))
675+
getPrevRecCheck (_ :| l) = case l of
676+
top : rest -> top :| rest
677+
[] -> (RecursionCheck mempty) :| []
678+
667679
{-# INLINE evalWithStackFrame #-}
668680

669681
applyLamUnsafe

pact-tests/pact-tests/modref-recursion.repl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
)
2828

2929
(env-gasmodel "table")
30-
(env-gaslimit 10) ; ensures test does not run forever in case recursion breaks
30+
(env-gaslimit 1000) ; ensures test does not run forever in case recursion breaks
3131

3232

33-
(expect-failure "Recursion should fail @ runtime" (knot2.callF knot1))
33+
(expect-failure "Recursion should fail @ runtime" "Recursion detected by the runtime. Recursing in function: knot2.callF" (knot2.callF knot1))

0 commit comments

Comments
 (0)