Skip to content

Fix panic in slice filter with negative length - #149

Open
ChrisJr404 wants to merge 1 commit into
osteele:mainfrom
ChrisJr404:fix-slice-filter-negative-length-panic
Open

Fix panic in slice filter with negative length#149
ChrisJr404 wants to merge 1 commit into
osteele:mainfrom
ChrisJr404:fix-slice-filter-negative-length-panic

Conversation

@ChrisJr404

Copy link
Copy Markdown

Summary

The slice filter panics with runtime error: slice bounds out of range when given a negative length. This is reachable from the main entry points (Engine.ParseAndRender, Template.Render) purely through template source, so a template author can crash the renderer.

Cause

slice computes end := start + length and only clamps end against the upper bound (len). It never clamps against start. A negative length makes end < start, and the subsequent runes[start:end] / slice[start:end] slice expression panics.

Minimal reproductions (both panic before this change):

eng := liquid.NewEngine()
eng.ParseAndRenderString(`{{ "Liquid" | slice: 2, -1 }}`, nil)          // string case
eng.ParseAndRenderString(`{{ "a,b,c" | split: "," | slice: 1, -1 }}`, nil) // array case

Fix

Clamp end up to start in both the string and array branches, so a negative length yields an empty result instead of panicking. This matches Ruby's String#slice(start, length), which returns nil for a negative length. Existing valid slices (positive length, negative start, out-of-range values) are unaffected.

Tests

Added regression cases to filterTests covering negative length for both a string (ASCII and multi-byte runes) and an array. make test passes.

Checklist

  • I have read the contribution guidelines.
  • make test passes.
  • make lint passes. (golangci-lint not run locally; go vet ./... is clean and the change is a two-line bounds clamp.)
  • New and changed code is covered by tests.
  • Performance improvements include benchmarks. (N/A)
  • Changes match the documented behavior of Shopify (negative length yields an empty result).

The slice filter computed end = start + length without a lower bound. A
negative length produced end < start, so the runes[start:end] and
slice[start:end] expressions panicked with a slice-bounds-out-of-range
runtime error. Clamp end up to start so a negative length yields an empty
result, matching Ruby's String#slice behavior, and add regression tests
covering the string and array cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant