Skip to content

Commit 08fd249

Browse files
dunglasclaude
andcommitted
fix: propagate tokenizing error on trailing backslash
The escape-at-end branch checked err == nil instead of err != nil, which caused two failure modes: - Strict policy: the non-nil error was dropped and the tokenizer's index was never advanced, producing an infinite loop. - Lenient policy: the function returned (nil, nil) after a single invalid-char token instead of continuing to tokenize the rest. Add a regression test that times out if strict tokenization loops. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 716dfa1 commit 08fd249

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

tokenizer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func tokenize(input string, policy tokenizePolicy) ([]token, error) {
5151

5252
case '\\':
5353
if t.index == len-1 {
54-
if err := t.processTokenizingError(t.nextIndex, t.index); err == nil {
54+
if err := t.processTokenizingError(t.nextIndex, t.index); err != nil {
5555
return nil, err
5656
}
5757

tokenizer_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package urlpattern_test
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/dunglas/go-urlpattern"
8+
)
9+
10+
// Regression: a pattern pathname ending with a trailing backslash used to
11+
// hang the strict tokenizer because the escape-at-end branch swallowed the
12+
// returned error instead of propagating it, leaving the tokenizer index
13+
// unchanged and causing an infinite loop.
14+
func TestTrailingBackslashDoesNotHang(t *testing.T) {
15+
pathname := "/foo\\"
16+
init := &urlpattern.URLPatternInit{Pathname: &pathname}
17+
18+
done := make(chan struct{})
19+
var newErr error
20+
go func() {
21+
defer close(done)
22+
_, newErr = init.New(nil)
23+
}()
24+
25+
select {
26+
case <-done:
27+
case <-time.After(2 * time.Second):
28+
t.Fatal("URLPatternInit.New hung on pathname with trailing backslash")
29+
}
30+
31+
if newErr == nil {
32+
t.Fatal("expected an error for a pathname ending with a lone backslash, got nil")
33+
}
34+
}

0 commit comments

Comments
 (0)