fix(security): charge pop filter allocation to memoryLimit (CWE-770)

The `pop` array filter cloned the input via `[...toArray(v)]` without
charging `this.context.memoryLimit.use(...)`, bypassing the memoryLimit
DoS guard that its sibling filters (shift, unshift, compact, etc.) apply.
Mirror `shift` to account for the O(N) allocation.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Yang Jun
2026-06-14 00:14:00 +08:00
co-authored by Cursor
parent ed15a52c26
commit 8734b5fc6e
2 changed files with 9 additions and 2 deletions
+5
View File
@@ -79,6 +79,11 @@ describe('DoS related', function () {
await expect(liquid.parseAndRender(src, { array, count: 3 })).resolves.toBe('a a a a a a a a')
await expect(liquid.parseAndRender(src, { array, count: 100 })).rejects.toThrow('memory alloc limit exceeded, line:1, col:26')
})
it('should charge pop allocation to memoryLimit', async () => {
const array = Array(1e3).fill(0)
const liquid = new Liquid({ memoryLimit: 100 })
await expect(liquid.parseAndRender('{{ array | pop | size }}', { array })).rejects.toThrow('memory alloc limit exceeded')
})
it('should charge strip_html input length to memoryLimit', () => {
const liquid = new Liquid({ memoryLimit: 100 })
expect(() => liquid.parseAndRenderSync('{{ s | strip_html }}', { s: 'a'.repeat(200) }))