[bug] Unstable decoding of different keys that are case-folded to the same value
yurykabanov opened this issue · 1 comments
Describe the bug
Having query with two distinct parameters, that are different in case (e.g. "x" and "X"), decoding returns unstable result - either one or another value will be present in result.
For example: for URL http://domain.tld/?x=aaa&X=bbb
, decoder will return bbb
in ~87% of cases and aaa
in ~13% of cases. The percentage heavily depends on amount of query parameters and their complexity.
Versions
Go version: go version
go version go1.17.6 windows/amd64
package version: run git rev-parse HEAD
inside the repo
github.com/gorilla/schema v1.2.0
Steps to Reproduce
The bug is triggered by trying to decode URL parameters with two distinct keys, that are case-folded to the same value.
Expected behavior
RFC 7230 claims that all components that are not scheme and host should be compared in a case-sensitive manner.
I understand that case insensitive comparison might be intended behavior for this library, but it should be stable (i.e. always return the same results for the exact same query). I assume this behavior is a result of randomized iteration order of maps.
Code Snippets
package main
import (
"fmt"
"net/url"
"github.com/gorilla/schema"
)
func main() {
decoder := schema.NewDecoder()
s := `http://domain.tld/?x=a&X=b`
u, _ := url.Parse(s)
q := u.Query()
fmt.Printf("%+v\n", q)
stats := make(map[string]uint)
for i := 0; i < 1000; i++ {
var v struct {
X string `schema:"x"`
}
_ = decoder.Decode(&v, q)
stats[v.X] += 1
}
for k, v := range stats {
fmt.Printf("%4d %s\n", v, k)
}
}
Result:
map[X:[b] x:[a]] <-- `url.ParseQuery()` treats parameters as distinct ones
866 b
134 a
Expected result (case insensitive):
1000 b
OR
1000 a
Alternatively, following RFC 7230, having case-sensitive results could have been an option, but it will be a breaking change and it will definitely affect library users.
This issue has been automatically marked as stale because it hasn't seen a recent update. It'll be automatically closed in a few days.