Skip to content

Commit 5b9c346

Browse files
harttlecursoragent
andauthored
fix: enforce renderLimit for empty renderTemplates calls (#894)
renderLimit was only checked inside the per-template loop, so renderTemplates([], ...) skipped it. Empty {% for %} and {% tablerow %} bodies call that path once per iteration (tablerow still does emitter work for <tr>/<td>), bypassing the documented time budget. Check the limiter at renderTemplates entry before the loop. Add regression tests for empty for-body and empty tablerow-body. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent dbbf628 commit 5b9c346

2 files changed

Lines changed: 11 additions & 0 deletions

File tree

src/render/render.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export class Render {
1515
if (!emitter) {
1616
emitter = ctx.opts.keepOutputType ? new KeepingTypeEmitter() : new SimpleEmitter()
1717
}
18+
ctx.renderLimit.check(getPerformance().now())
1819
const errors = []
1920
for (const tpl of templates) {
2021
ctx.renderLimit.check(getPerformance().now())

test/integration/liquid/dos.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ describe('DoS related', function () {
4848
await expect(liquid.parseAndRender('{% render "large" %}')).rejects.toThrow('template render limit exceeded')
4949
await expect(liquid.parseAndRender('{% render "small" %}')).resolves.toBe('12345')
5050
})
51+
it('should enforce renderLimit when for body has no template nodes', () => {
52+
const liquid = new Liquid({ memoryLimit: 1e9, renderLimit: 1 })
53+
expect(() => liquid.parseAndRenderSync('{%- for i in (1..5000000) -%}{%- endfor -%}', {}))
54+
.toThrow('template render limit exceeded')
55+
})
56+
it('should enforce renderLimit when tablerow body has no template nodes', () => {
57+
const liquid = new Liquid({ memoryLimit: 1e9, renderLimit: 1 })
58+
expect(() => liquid.parseAndRenderSync('{%- tablerow i in (1..1000000) cols:1 -%}{%- endtablerow -%}', {}))
59+
.toThrow('template render limit exceeded')
60+
})
5161
})
5262
describe('#memoryLimit', () => {
5363
it('should throw for too many array creation in filters', async () => {

0 commit comments

Comments
 (0)