diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/internal/godebugs/table.go | 1 | ||||
| -rw-r--r-- | src/net/url/url.go | 23 | ||||
| -rw-r--r-- | src/net/url/url_test.go | 48 | ||||
| -rw-r--r-- | src/runtime/metrics/doc.go | 5 |
4 files changed, 77 insertions, 0 deletions
diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index 8f6d8bbdda..87b499385a 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -69,6 +69,7 @@ var All = []Info{ {Name: "tlssha1", Package: "crypto/tls", Changed: 25, Old: "1"}, {Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"}, {Name: "updatemaxprocs", Package: "runtime", Changed: 25, Old: "0"}, + {Name: "urlmaxqueryparams", Package: "net/url", Changed: 24, Old: "0"}, {Name: "urlstrictcolons", Package: "net/url", Changed: 26, Old: "0"}, {Name: "winreadlinkvolume", Package: "os", Changed: 23, Old: "0"}, {Name: "winsymlink", Package: "os", Changed: 23, Old: "0"}, diff --git a/src/net/url/url.go b/src/net/url/url.go index 3acd202c24..202957a3a2 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -929,7 +929,30 @@ func ParseQuery(query string) (Values, error) { return m, err } +var urlmaxqueryparams = godebug.New("urlmaxqueryparams") + +const defaultMaxParams = 10000 + +func urlParamsWithinMax(params int) bool { + withinDefaultMax := params <= defaultMaxParams + if urlmaxqueryparams.Value() == "" { + return withinDefaultMax + } + customMax, err := strconv.Atoi(urlmaxqueryparams.Value()) + if err != nil { + return withinDefaultMax + } + withinCustomMax := customMax == 0 || params < customMax + if withinDefaultMax != withinCustomMax { + urlmaxqueryparams.IncNonDefault() + } + return withinCustomMax +} + func parseQuery(m Values, query string) (err error) { + if !urlParamsWithinMax(strings.Count(query, "&") + 1) { + return errors.New("number of URL query parameters exceeded limit") + } for query != "" { var key string key, query, _ = strings.Cut(query, "&") diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index bb48bb6bee..d099353eb2 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -1521,6 +1521,54 @@ func TestParseQuery(t *testing.T) { } } +func TestParseQueryLimits(t *testing.T) { + for _, test := range []struct { + params int + godebug string + wantErr bool + }{{ + params: 10, + wantErr: false, + }, { + params: defaultMaxParams, + wantErr: false, + }, { + params: defaultMaxParams + 1, + wantErr: true, + }, { + params: 10, + godebug: "urlmaxqueryparams=9", + wantErr: true, + }, { + params: defaultMaxParams + 1, + godebug: "urlmaxqueryparams=0", + wantErr: false, + }} { + t.Setenv("GODEBUG", test.godebug) + want := Values{} + var b strings.Builder + for i := range test.params { + if i > 0 { + b.WriteString("&") + } + p := fmt.Sprintf("p%v", i) + b.WriteString(p) + want[p] = []string{""} + } + query := b.String() + got, err := ParseQuery(query) + if gotErr, wantErr := err != nil, test.wantErr; gotErr != wantErr { + t.Errorf("GODEBUG=%v ParseQuery(%v params) = %v, want error: %v", test.godebug, test.params, err, wantErr) + } + if err != nil { + continue + } + if got, want := len(got), test.params; got != want { + t.Errorf("GODEBUG=%v ParseQuery(%v params): got %v params, want %v", test.godebug, test.params, got, want) + } + } +} + type RequestURITest struct { url *URL out string diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go index ca032f51b1..6b774c36f3 100644 --- a/src/runtime/metrics/doc.go +++ b/src/runtime/metrics/doc.go @@ -404,6 +404,11 @@ Below is the full list of supported metrics, ordered lexicographically. The number of non-default behaviors executed by the runtime package due to a non-default GODEBUG=updatemaxprocs=... setting. + /godebug/non-default-behavior/urlmaxqueryparams:events + The number of non-default behaviors executed by the net/url + package due to a non-default GODEBUG=urlmaxqueryparams=... + setting. + /godebug/non-default-behavior/urlstrictcolons:events The number of non-default behaviors executed by the net/url package due to a non-default GODEBUG=urlstrictcolons=... |
