From 3607cd7110a8e62c69ea02900139c1c54534aaa9 Mon Sep 17 00:00:00 2001 From: Antonio Gamez Diaz Date: Wed, 9 Aug 2023 23:53:56 +0200 Subject: [PATCH] Avoid nil dereference if passing a nil resolver Signed-off-by: Antonio Gamez Diaz --- pkg/registry/client.go | 58 +++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/pkg/registry/client.go b/pkg/registry/client.go index 95dc6d631..0dfa6926f 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -88,37 +88,43 @@ func NewClient(options ...ClientOption) (*Client, error) { client.authorizer = authClient } - if client.resolver == nil { - client.resolver = func(ref registry.Reference) (remotes.Resolver, error) { - headers := http.Header{} - headers.Set("User-Agent", version.GetUserAgent()) - dockerClient, ok := client.authorizer.(*dockerauth.Client) - if ok { - username, password, err := dockerClient.Credential(ref.Registry) - if err != nil { - return nil, errors.New("unable to retrieve credentials") - } - // A blank returned username and password value is a bearer token - if username == "" && password != "" { - headers.Set("Authorization", fmt.Sprintf("Bearer %s", password)) - } else { - headers.Set("Authorization", fmt.Sprintf("Basic %s", basicAuth(username, password))) - } + resolverFn := client.resolver // copy for avoiding recursive call + client.resolver = func(ref registry.Reference) (remotes.Resolver, error) { + if resolverFn != nil { + // validate if the resolverFn returns a valid resolver + if resolver, err := resolverFn(ref); resolver != nil && err == nil { + return resolver, nil } + } - opts := []auth.ResolverOption{auth.WithResolverHeaders(headers)} - if client.httpClient != nil { - opts = append(opts, auth.WithResolverClient(client.httpClient)) - } - if client.plainHTTP { - opts = append(opts, auth.WithResolverPlainHTTP()) - } - resolver, err := client.authorizer.ResolverWithOpts(opts...) + headers := http.Header{} + headers.Set("User-Agent", version.GetUserAgent()) + dockerClient, ok := client.authorizer.(*dockerauth.Client) + if ok { + username, password, err := dockerClient.Credential(ref.Registry) if err != nil { - return nil, err + return nil, errors.New("unable to retrieve credentials") } - return resolver, nil + // A blank returned username and password value is a bearer token + if username == "" && password != "" { + headers.Set("Authorization", fmt.Sprintf("Bearer %s", password)) + } else { + headers.Set("Authorization", fmt.Sprintf("Basic %s", basicAuth(username, password))) + } + } + + opts := []auth.ResolverOption{auth.WithResolverHeaders(headers)} + if client.httpClient != nil { + opts = append(opts, auth.WithResolverClient(client.httpClient)) + } + if client.plainHTTP { + opts = append(opts, auth.WithResolverPlainHTTP()) + } + resolver, err := client.authorizer.ResolverWithOpts(opts...) + if err != nil { + return nil, err } + return resolver, nil } // allocate a cache if option is set