@@ -18,12 +18,17 @@ package etcd3
1818
1919import (
2020 "bytes"
21+ "encoding/base64"
22+ "encoding/json"
2123 "fmt"
2224 "reflect"
2325 "strconv"
2426 "sync"
2527 "testing"
2628
29+ "github.com/coreos/etcd/clientv3"
30+ "github.com/coreos/etcd/integration"
31+ "golang.org/x/net/context"
2732 apitesting "k8s.io/apimachinery/pkg/api/testing"
2833 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2934 "k8s.io/apimachinery/pkg/fields"
@@ -37,10 +42,6 @@ import (
3742 "k8s.io/apiserver/pkg/storage"
3843 storagetests "k8s.io/apiserver/pkg/storage/tests"
3944 "k8s.io/apiserver/pkg/storage/value"
40-
41- "github.com/coreos/etcd/clientv3"
42- "github.com/coreos/etcd/integration"
43- "golang.org/x/net/context"
4445)
4546
4647var scheme = runtime .NewScheme ()
@@ -923,3 +924,51 @@ func TestPrefix(t *testing.T) {
923924 }
924925 }
925926}
927+
928+ func encodeContinueOrDie (apiVersion string , resourceVersion int64 , nextKey string ) string {
929+ out , err := json .Marshal (& continueToken {APIVersion : apiVersion , ResourceVersion : resourceVersion , StartKey : nextKey })
930+ if err != nil {
931+ panic (err )
932+ }
933+ return base64 .RawURLEncoding .EncodeToString (out )
934+ }
935+
936+ func Test_decodeContinue (t * testing.T ) {
937+ type args struct {
938+ continueValue string
939+ keyPrefix string
940+ }
941+ tests := []struct {
942+ name string
943+ args args
944+ wantFromKey string
945+ wantRv int64
946+ wantErr bool
947+ }{
948+ {name : "valid" , args : args {continueValue : encodeContinueOrDie ("v1alpha1" , 1 , "key" ), keyPrefix : "/test/" }, wantRv : 1 , wantFromKey : "/test/key" },
949+
950+ {name : "empty version" , args : args {continueValue : encodeContinueOrDie ("" , 1 , "key" ), keyPrefix : "/test/" }, wantErr : true },
951+ {name : "invalid version" , args : args {continueValue : encodeContinueOrDie ("v1" , 1 , "key" ), keyPrefix : "/test/" }, wantErr : true },
952+
953+ {name : "path traversal - parent" , args : args {continueValue : encodeContinueOrDie ("v1alpha" , 1 , "../key" ), keyPrefix : "/test/" }, wantErr : true },
954+ {name : "path traversal - local" , args : args {continueValue : encodeContinueOrDie ("v1alpha" , 1 , "./key" ), keyPrefix : "/test/" }, wantErr : true },
955+ {name : "path traversal - double parent" , args : args {continueValue : encodeContinueOrDie ("v1alpha" , 1 , "./../key" ), keyPrefix : "/test/" }, wantErr : true },
956+ {name : "path traversal - after parent" , args : args {continueValue : encodeContinueOrDie ("v1alpha" , 1 , "key/../.." ), keyPrefix : "/test/" }, wantErr : true },
957+ {name : "path traversal - separator" , args : args {continueValue : encodeContinueOrDie ("v1alpha" , 1 , "/" ), keyPrefix : "/test/" }, wantErr : true },
958+ }
959+ for _ , tt := range tests {
960+ t .Run (tt .name , func (t * testing.T ) {
961+ gotFromKey , gotRv , err := decodeContinue (tt .args .continueValue , tt .args .keyPrefix )
962+ if (err != nil ) != tt .wantErr {
963+ t .Errorf ("decodeContinue() error = %v, wantErr %v" , err , tt .wantErr )
964+ return
965+ }
966+ if gotFromKey != tt .wantFromKey {
967+ t .Errorf ("decodeContinue() gotFromKey = %v, want %v" , gotFromKey , tt .wantFromKey )
968+ }
969+ if gotRv != tt .wantRv {
970+ t .Errorf ("decodeContinue() gotRv = %v, want %v" , gotRv , tt .wantRv )
971+ }
972+ })
973+ }
974+ }
0 commit comments