diff --git a/language/parse.go b/language/parse.go index 053336e2..1bac5b10 100644 --- a/language/parse.go +++ b/language/parse.go @@ -166,7 +166,12 @@ func ParseAcceptLanguage(s string) (tag []Tag, q []float32, err error) { } }() - if strings.Count(s, "-") > 1000 { + // Reject excessively large input to avoid quadratic behavior in the + // scanner (see Go issue 56152). Underscores are treated as separators + // equivalent to dashes (they are normalized to '-' during scanning), so + // they must be counted here as well; otherwise an underscore-separated + // value bypasses this limit. + if strings.Count(s, "-")+strings.Count(s, "_") > 1000 { return nil, nil, errTagListTooLarge } diff --git a/language/parse_test.go b/language/parse_test.go index 0eee033e..116a1edc 100644 --- a/language/parse_test.go +++ b/language/parse_test.go @@ -406,4 +406,11 @@ func TestParseAcceptLanguageTooBig(t *testing.T) { if err != errTagListTooLarge { t.Errorf("ParseAcceptLanguage() unexpected error: got %v, want %v", err, errTagListTooLarge) } + + // Underscores are normalized to dashes by the scanner, so they are + // separators too and must be subject to the same limit. + u := strings.Repeat("en_x_a_", 333) + "en_x_a" + if _, _, err = ParseAcceptLanguage(u); err != errTagListTooLarge { + t.Errorf("ParseAcceptLanguage(underscores) unexpected error: got %v, want %v", err, errTagListTooLarge) + } }