-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
Go version
go version go1.22.1 darwin/arm64
Output of go env in your module/workspace:
GO111MODULE='auto'
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/tomcoupland/Library/Caches/go-build'
GOENV='/Users/tomcoupland/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/tomcoupland/pkg/mod'
GONOPROXY='github.com/monzo'
GONOSUMDB='github.com/monzo'
GOOS='darwin'
GOPATH='/Users/tomcoupland'
GOPRIVATE='github.com/monzo'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/tomcoupland/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.1.darwin-arm64'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/tomcoupland/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.1.darwin-arm64/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.23.1'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/tomcoupland/Library/Application Support/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/Users/tomcoupland/src/github.com/monzo/wearedev/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/ll/3h483n6j4jbd64x_tjbgwzd40000gn/T/go-build4023913863=/tmp/go-build -gno-record-gcc-switches -fno-common'What did you do?
fmt.Printf("GOARCH: %s\n", runtime.GOARCH)
limiter := rate.NewLimiter(1e-10, 1)
if limiter.Allow() {
fmt.Println("allow")
} else {
fmt.Println("not allow")
}
if limiter.Allow() {
fmt.Println("allow")
} else {
fmt.Println("not allow")
}
There is a conversion from float64 to int64 in durationFromTokens, when the final time.Duration is created:
func (limit Limit) durationFromTokens(tokens float64) time.Duration {
if limit <= 0 {
return InfDuration
}
seconds := tokens / float64(limit)
return time.Duration(float64(time.Second) * seconds)
}
When limiters are configured with small values (1e-10) this overflows and allows request through that should be blocked. amd64 does not saturate int64's when converting, where as arm64 does. Therefore this code is safe on arm64, but not amd64.
Results of running:
GOARCH = "amd64", see "allow", "allow"
GOARCH = 'arm64', see "allow", "not allow"
This leads to the second "allow" on amd64. I'm preparing a PR with some overflow protection.
What did you see happen?
When GOARCH = "amd64", see "allow", "allow"
Whe GOARCH = 'arm64', see "allow", "not allow"
What did you expect to see?
Regardless of GOARCH: "allow", "not allow"
The first attempt should succeed, due to the burst of 1, but the second should be denied.