lib/api: Fix and optimize csrfManager (#8329)
An off-by-one error could cause tokens to be forgotten. Suppose
tokens := []string{"foo", "bar", "baz", "quux"}
i := 2
token := tokens[i] // token == "baz"
Then, after
copy(tokens[1:], tokens[:i+1])
tokens[0] = token
we have
tokens == []string{"baz", "foo", "bar", "baz"}
The short test actually relied on this bug.
This commit is contained in:
+24
-2
@@ -18,6 +18,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -73,10 +74,10 @@ func TestMain(m *testing.M) {
|
||||
func TestCSRFToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
max := 250
|
||||
max := 10 * maxCsrfTokens
|
||||
int := 5
|
||||
if testing.Short() {
|
||||
max = 20
|
||||
max = 1 + maxCsrfTokens
|
||||
int = 2
|
||||
}
|
||||
|
||||
@@ -90,6 +91,11 @@ func TestCSRFToken(t *testing.T) {
|
||||
t.Fatal("t3 should be valid")
|
||||
}
|
||||
|
||||
valid := make(map[string]struct{}, maxCsrfTokens)
|
||||
for _, token := range m.tokens {
|
||||
valid[token] = struct{}{}
|
||||
}
|
||||
|
||||
for i := 0; i < max; i++ {
|
||||
if i%int == 0 {
|
||||
// t1 and t2 should remain valid by virtue of us checking them now
|
||||
@@ -102,11 +108,27 @@ func TestCSRFToken(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(m.tokens) == maxCsrfTokens {
|
||||
// We're about to add a token, which will remove the last token
|
||||
// from m.tokens.
|
||||
delete(valid, m.tokens[len(m.tokens)-1])
|
||||
}
|
||||
|
||||
// The newly generated token is always valid
|
||||
t4 := m.newToken()
|
||||
if !m.validToken(t4) {
|
||||
t.Fatal("t4 should be valid at iteration", i)
|
||||
}
|
||||
valid[t4] = struct{}{}
|
||||
|
||||
v := make(map[string]struct{}, maxCsrfTokens)
|
||||
for _, token := range m.tokens {
|
||||
v[token] = struct{}{}
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(v, valid) {
|
||||
t.Fatalf("want valid tokens %v, got %v", valid, v)
|
||||
}
|
||||
}
|
||||
|
||||
if m.validToken(t3) {
|
||||
|
||||
Reference in New Issue
Block a user