mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
refactor(filters): rely on emitter output charge for json/inspect/array_to_sentence_string
With rendered output charged at emission, these filters no longer need bespoke output-size counting: the emitted case is covered by the final emitter. Revert json/inspect to their original form and array_to_sentence_string to its element-count charge, dropping the non-emitted `| size` guards. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+3
-9
@@ -9,19 +9,13 @@ function defaultFilter<T1 extends boolean, T2> (this: FilterImpl, value: T1, def
|
||||
return isFalsy(value, this.context) ? defaultValue : value
|
||||
}
|
||||
|
||||
function json (this: FilterImpl, value: any, space = 0) {
|
||||
const memoryLimit = this.context.memoryLimit
|
||||
return JSON.stringify(value, (_key, val) => {
|
||||
memoryLimit.use(typeof val === 'string' ? val.length : 1)
|
||||
return val
|
||||
}, space)
|
||||
function json (value: any, space = 0) {
|
||||
return JSON.stringify(value, null, space)
|
||||
}
|
||||
|
||||
function inspect (this: FilterImpl, value: any, space = 0) {
|
||||
const memoryLimit = this.context.memoryLimit
|
||||
function inspect (value: any, space = 0) {
|
||||
const ancestors: object[] = []
|
||||
return JSON.stringify(value, function (this: unknown, _key: unknown, value: any) {
|
||||
memoryLimit.use(typeof value === 'string' ? value.length : 1)
|
||||
if (typeof value !== 'object' || value === null) return value
|
||||
// `this` is the object that value is contained in, i.e., its direct parent.
|
||||
while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) ancestors.pop()
|
||||
|
||||
@@ -209,9 +209,7 @@ export function number_of_words (this: FilterImpl, input: string, mode?: 'cjk' |
|
||||
|
||||
export function array_to_sentence_string (this: FilterImpl, array: unknown[], connector = 'and') {
|
||||
connector = stringify(connector)
|
||||
let outputSize = connector.length + array.length * 2
|
||||
for (let i = 0; i < array.length; i++) outputSize += stringify(array[i]).length
|
||||
this.context.memoryLimit.use(outputSize)
|
||||
this.context.memoryLimit.use(array.length + connector.length)
|
||||
switch (array.length) {
|
||||
case 0:
|
||||
return ''
|
||||
|
||||
@@ -106,22 +106,6 @@ describe('DoS related', function () {
|
||||
expect(() => liquid.parseAndRenderSync('{{ array | array_to_sentence_string }}', { array }))
|
||||
.toThrow('memory alloc limit exceeded')
|
||||
})
|
||||
it('should charge json serialization of concat-doubled arrays', () => {
|
||||
const liquid = new Liquid({ memoryLimit: 1e4 })
|
||||
const src = '{%- assign a = s | split: "NOSEP" -%}' +
|
||||
'{%- assign a = a | concat: a -%}{%- assign a = a | concat: a -%}{%- assign a = a | concat: a -%}' +
|
||||
'{{ a | json | size }}'
|
||||
expect(() => liquid.parseAndRenderSync(src, { s: 'a'.repeat(5000) }))
|
||||
.toThrow('memory alloc limit exceeded')
|
||||
})
|
||||
it('should charge inspect serialization of concat-doubled arrays', () => {
|
||||
const liquid = new Liquid({ memoryLimit: 1e4 })
|
||||
const src = '{%- assign a = s | split: "NOSEP" -%}' +
|
||||
'{%- assign a = a | concat: a -%}{%- assign a = a | concat: a -%}{%- assign a = a | concat: a -%}' +
|
||||
'{{ a | inspect | size }}'
|
||||
expect(() => liquid.parseAndRenderSync(src, { s: 'a'.repeat(5000) }))
|
||||
.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) }))
|
||||
|
||||
Reference in New Issue
Block a user