Skip to content

Commit

Permalink
RakuAST: Add potential infinite loop in BEGIN time call with nested b…
Browse files Browse the repository at this point in the history
…locks

Creating QAST for a block did not mean that we would generate QAST for
nested blocks. The reason is that these blocks are not called directly,
but instead their meta object gets closure cloned. Creating the meta
object does not require immediate creation of the QAST. We just stub
code objects instead.

This means that if the outer block gets called at BEGIN time, the inner
block may not have been linked yet to its QAST::Block. This in turn
results in the clone not being registered in the original's clone list
as they are linked via the CUID which comes from the QAST::Block. Since
the clone is not known, calling the clone would have lead to dynamic
compilation when its stub was called, but this compilation only set the
$!do of the original code object, not the clone's. Thus when the stub
then tried to forward the call to the actual code object, we'd end up in
the stub again, hence in an infinite loop.
  • Loading branch information
niner committed Nov 5, 2022
1 parent 9d4a15c commit a2860e8
Showing 1 changed file with 3 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/Raku/ast/code.rakumod
Expand Up @@ -699,6 +699,9 @@ class RakuAST::Block is RakuAST::LexicalScope is RakuAST::Term is RakuAST::Code
else {
# Not immediate, so already produced as a declaration above; just
# closure clone it. Only invoke if it's a bare block.
# Ensure the block is linked when our outer block gets cloned before
# our IMPL-QAST-DECL-CODE is called.
self.IMPL-QAST-BLOCK($context, :blocktype('declaration_static'));
my $ast := self.IMPL-CLOSURE-QAST($context);
self.bare-block
?? QAST::Op.new( :op('call'), $ast )
Expand Down

0 comments on commit a2860e8

Please sign in to comment.