Skip to content

Commit

Permalink
fix: guard against recursive extends during async analysis, closes #…
Browse files Browse the repository at this point in the history
  • Loading branch information
jg-rp committed Aug 13, 2023
1 parent a93a3c9 commit 8f3ba5a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
32 changes: 27 additions & 5 deletions liquid/static_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,34 +552,56 @@ def _analyze_template_inheritance_chain(
self._update_reference_counters(refs)

async def _analyze_template_inheritance_chain_async(
self, child: ChildNode, template: BoundTemplate
self, node: ChildNode, template: BoundTemplate
) -> None:
name, load_context = self._make_load_context(child, "extends")
name, load_context = self._make_load_context(node, "extends")
if name is None or load_context is None:
return

stack_context = self._empty_context.copy({})
stack_context.tag_namespace["extends"] = defaultdict(list)

# Guard against recursive `extends`.
seen: Set[str] = set()

# Add blocks from the leaf template to the stack context.
self._stack_blocks(stack_context, template, count_tags=False)
extends_name, _ = self._stack_blocks(stack_context, template, count_tags=False)
assert extends_name
seen.add(extends_name)

try:
parent = await self._get_template_async(
name, load_context, self._template_name, child
name, load_context, self._template_name, node
)
except TemplateNotFound:
return

parent_template_name, _ = self._stack_blocks(stack_context, parent)

if parent_template_name:
if parent_template_name in seen:
raise TemplateInheritanceError(
f"circular extends {parent_template_name!r}",
linenum=node.linenum,
filename=template.name,
)
seen.add(parent_template_name)

while parent_template_name:
try:
parent = await self._get_template_async(
parent_template_name, load_context, self._template_name, child
parent_template_name, load_context, self._template_name, node
)
except TemplateNotFound:
return

parent_template_name, _ = self._stack_blocks(stack_context, parent)
if parent_template_name:
if parent_template_name in seen:
raise TemplateInheritanceError(
f"circular extends {parent_template_name!r}"
)
seen.add(parent_template_name)

refs = await _InheritanceChainCounter(
parent,
Expand Down
7 changes: 7 additions & 0 deletions tests/test_analyze_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,13 @@ def test_analyze_recursive_extends(self):
with self.assertRaises(TemplateInheritanceError):
template.analyze()

async def coro(template: BoundTemplate) -> str:
return await template.analyze_async()

with self.subTest(asynchronous=True):
with self.assertRaises(TemplateInheritanceError):
asyncio.run(coro(template))

def test_analyze_super_block(self):
"""Test that we can count references when rendering super blocks."""
loader = DictLoader(
Expand Down

0 comments on commit 8f3ba5a

Please sign in to comment.