diff --git a/go.mod b/go.mod index 3da86911..cafd3426 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/goccy/go-yaml v1.19.2 github.com/gogo/protobuf v1.3.2 github.com/google/go-cmp v0.7.0 - github.com/google/go-containerregistry v0.21.6 + github.com/google/go-containerregistry v0.21.7 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 @@ -101,7 +101,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v29.4.3+incompatible // indirect + github.com/docker/cli v29.5.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.9.3 // indirect github.com/docker/go-connections v0.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -198,12 +198,12 @@ require ( go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect - golang.org/x/mod v0.36.0 // indirect - golang.org/x/net v0.55.0 // indirect + golang.org/x/mod v0.37.0 // indirect + golang.org/x/net v0.56.0 // indirect golang.org/x/sync v0.21.0 // indirect golang.org/x/term v0.44.0 // indirect golang.org/x/time v0.15.0 // indirect - golang.org/x/tools v0.45.0 // indirect + golang.org/x/tools v0.46.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 20dae804..e00c1c18 100644 --- a/go.sum +++ b/go.sum @@ -158,6 +158,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU= github.com/docker/cli v29.4.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v29.5.3+incompatible h1:nbEFfz774vBwQ5KRYv7c/AghjReqnGISvrRhzjV0evs= +github.com/docker/cli v29.5.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= @@ -227,6 +229,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.6 h1:T+yqQIlJXKrM98Om4DlW3GoWQAmhZuLMwoDOvVrtiUM= github.com/google/go-containerregistry v0.21.6/go.mod h1:U7MMSBIJynke2MVQrQk19NP9k/uQsGz/h0amIFSHMbo= +github.com/google/go-containerregistry v0.21.7 h1:/vPFuVXDjtFREsVArW+0h1CIl5urnOhzei4X2DMW9IU= +github.com/google/go-containerregistry v0.21.7/go.mod h1:kjSbt7/zMsKLWfnHrIvKvhXHUw91jbe9DNjPPJ32gXE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= @@ -538,12 +542,16 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -587,6 +595,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= +golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk= +golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/docker/cli/cli/config/configfile/file.go b/vendor/github.com/docker/cli/cli/config/configfile/file.go index 1a0e5b46..26e148f0 100644 --- a/vendor/github.com/docker/cli/cli/config/configfile/file.go +++ b/vendor/github.com/docker/cli/cli/config/configfile/file.go @@ -20,6 +20,34 @@ import ( "github.com/sirupsen/logrus" ) +// authConfigKey is the key used to store credentials for Docker Hub. It is +// a copy of [registry.IndexServer]. +// +// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/docker@v28.5.1+incompatible/registry#IndexServer +const authConfigKey = "https://index.docker.io/v1/" + +// getAuthConfigKey returns the canonical key used to look up stored +// registry credentials for the given registry domain. +// +// For the official Docker Hub registry ("docker.io"), credentials are stored +// under the historical full index address ("https://index.docker.io/v1/"). +// +// For all other registries, the input is domainName to already be a normalized +// hostname (optionally including ":port") and is returned unchanged. +// +// This function performs key normalization only; it does not validate or parse +// the input. +// +// It is similar to [registry.GetAuthConfigKey] in the daemon. +// +// [registry.GetAuthConfigKey]: https://pkg.go.dev/github.com/docker/docker@v28.5.1+incompatible/registry#GetAuthConfigKey +func getAuthConfigKey(domainName string) string { + if domainName == "docker.io" || domainName == "index.docker.io" { + return authConfigKey + } + return domainName +} + // ConfigFile ~/.docker/config.json file info type ConfigFile struct { AuthConfigs map[string]types.AuthConfig `json:"auths"` @@ -96,12 +124,12 @@ func New(fn string) *ConfigFile { // LoadFromReader reads the configuration data given and sets up the auth config // information with given directory and populates the receiver object -func (configFile *ConfigFile) LoadFromReader(configData io.Reader) error { - if err := json.NewDecoder(configData).Decode(configFile); err != nil && !errors.Is(err, io.EOF) { +func (c *ConfigFile) LoadFromReader(configData io.Reader) error { + if err := json.NewDecoder(configData).Decode(c); err != nil && !errors.Is(err, io.EOF) { return err } var err error - for addr, ac := range configFile.AuthConfigs { + for addr, ac := range c.AuthConfigs { if ac.Auth != "" { ac.Username, ac.Password, err = decodeAuth(ac.Auth) if err != nil { @@ -110,33 +138,33 @@ func (configFile *ConfigFile) LoadFromReader(configData io.Reader) error { } ac.Auth = "" ac.ServerAddress = addr - configFile.AuthConfigs[addr] = ac + c.AuthConfigs[addr] = ac } return nil } // ContainsAuth returns whether there is authentication configured // in this file or not. -func (configFile *ConfigFile) ContainsAuth() bool { - return configFile.CredentialsStore != "" || - len(configFile.CredentialHelpers) > 0 || - len(configFile.AuthConfigs) > 0 +func (c *ConfigFile) ContainsAuth() bool { + return c.CredentialsStore != "" || + len(c.CredentialHelpers) > 0 || + len(c.AuthConfigs) > 0 } // GetAuthConfigs returns the mapping of repo to auth configuration -func (configFile *ConfigFile) GetAuthConfigs() map[string]types.AuthConfig { - if configFile.AuthConfigs == nil { - configFile.AuthConfigs = make(map[string]types.AuthConfig) +func (c *ConfigFile) GetAuthConfigs() map[string]types.AuthConfig { + if c.AuthConfigs == nil { + c.AuthConfigs = make(map[string]types.AuthConfig) } - return configFile.AuthConfigs + return c.AuthConfigs } // SaveToWriter encodes and writes out all the authorization information to // the given writer -func (configFile *ConfigFile) SaveToWriter(writer io.Writer) error { +func (c *ConfigFile) SaveToWriter(writer io.Writer) error { // Encode sensitive data into a new/temp struct - tmpAuthConfigs := make(map[string]types.AuthConfig, len(configFile.AuthConfigs)) - for k, authConfig := range configFile.AuthConfigs { + tmpAuthConfigs := make(map[string]types.AuthConfig, len(c.AuthConfigs)) + for k, authConfig := range c.AuthConfigs { authCopy := authConfig // encode and save the authstring, while blanking out the original fields authCopy.Auth = encodeAuth(&authCopy) @@ -146,18 +174,18 @@ func (configFile *ConfigFile) SaveToWriter(writer io.Writer) error { tmpAuthConfigs[k] = authCopy } - saveAuthConfigs := configFile.AuthConfigs - configFile.AuthConfigs = tmpAuthConfigs - defer func() { configFile.AuthConfigs = saveAuthConfigs }() + saveAuthConfigs := c.AuthConfigs + c.AuthConfigs = tmpAuthConfigs + defer func() { c.AuthConfigs = saveAuthConfigs }() // User-Agent header is automatically set, and should not be stored in the configuration - for v := range configFile.HTTPHeaders { + for v := range c.HTTPHeaders { if strings.EqualFold(v, "User-Agent") { - delete(configFile.HTTPHeaders, v) + delete(c.HTTPHeaders, v) } } - data, err := json.MarshalIndent(configFile, "", "\t") + data, err := json.MarshalIndent(c, "", "\t") if err != nil { return err } @@ -166,16 +194,16 @@ func (configFile *ConfigFile) SaveToWriter(writer io.Writer) error { } // Save encodes and writes out all the authorization information -func (configFile *ConfigFile) Save() (retErr error) { - if configFile.Filename == "" { +func (c *ConfigFile) Save() (retErr error) { + if c.Filename == "" { return errors.New("can't save config with empty filename") } - dir := filepath.Dir(configFile.Filename) + dir := filepath.Dir(c.Filename) if err := os.MkdirAll(dir, 0o700); err != nil { return err } - temp, err := os.CreateTemp(dir, filepath.Base(configFile.Filename)) + temp, err := os.CreateTemp(dir, filepath.Base(c.Filename)) if err != nil { return err } @@ -189,7 +217,7 @@ func (configFile *ConfigFile) Save() (retErr error) { } }() - err = configFile.SaveToWriter(temp) + err = c.SaveToWriter(temp) if err != nil { return err } @@ -199,7 +227,7 @@ func (configFile *ConfigFile) Save() (retErr error) { } // Handle situation where the configfile is a symlink, and allow for dangling symlinks - cfgFile := configFile.Filename + cfgFile := c.Filename if f, err := filepath.EvalSymlinks(cfgFile); err == nil { cfgFile = f } else if os.IsNotExist(err) { @@ -217,16 +245,16 @@ func (configFile *ConfigFile) Save() (retErr error) { // ParseProxyConfig computes proxy configuration by retrieving the config for the provided host and // then checking this against any environment variables provided to the container -func (configFile *ConfigFile) ParseProxyConfig(host string, runOpts map[string]*string) map[string]*string { +func (c *ConfigFile) ParseProxyConfig(host string, runOpts map[string]*string) map[string]*string { var cfgKey string - if _, ok := configFile.Proxies[host]; !ok { + if _, ok := c.Proxies[host]; !ok { cfgKey = "default" } else { cfgKey = host } - config := configFile.Proxies[cfgKey] + config := c.Proxies[cfgKey] permitted := map[string]*string{ "HTTP_PROXY": &config.HTTPProxy, "HTTPS_PROXY": &config.HTTPSProxy, @@ -290,11 +318,11 @@ func decodeAuth(authStr string) (string, string, error) { // GetCredentialsStore returns a new credentials store from the settings in the // configuration file -func (configFile *ConfigFile) GetCredentialsStore(registryHostname string) credentials.Store { - store := credentials.NewFileStore(configFile) +func (c *ConfigFile) GetCredentialsStore(registryHostname string) credentials.Store { + store := credentials.NewFileStore(c) - if helper := getConfiguredCredentialStore(configFile, registryHostname); helper != "" { - store = newNativeStore(configFile, helper) + if helper := getConfiguredCredentialStore(c, getAuthConfigKey(registryHostname)); helper != "" { + store = newNativeStore(c, helper) } envConfig := os.Getenv(DockerEnvConfigKey) @@ -357,8 +385,9 @@ var newNativeStore = func(configFile *ConfigFile, helperSuffix string) credentia } // GetAuthConfig for a repository from the credential store -func (configFile *ConfigFile) GetAuthConfig(registryHostname string) (types.AuthConfig, error) { - return configFile.GetCredentialsStore(registryHostname).Get(registryHostname) +func (c *ConfigFile) GetAuthConfig(registryHostname string) (types.AuthConfig, error) { + acKey := getAuthConfigKey(registryHostname) + return c.GetCredentialsStore(acKey).Get(acKey) } // getConfiguredCredentialStore returns the credential helper configured for the @@ -375,13 +404,13 @@ func getConfiguredCredentialStore(c *ConfigFile, registryHostname string) string // GetAllCredentials returns all of the credentials stored in all of the // configured credential stores. -func (configFile *ConfigFile) GetAllCredentials() (map[string]types.AuthConfig, error) { +func (c *ConfigFile) GetAllCredentials() (map[string]types.AuthConfig, error) { auths := make(map[string]types.AuthConfig) addAll := func(from map[string]types.AuthConfig) { maps.Copy(auths, from) } - defaultStore := configFile.GetCredentialsStore("") + defaultStore := c.GetCredentialsStore("") newAuths, err := defaultStore.GetAll() if err != nil { return nil, err @@ -389,8 +418,8 @@ func (configFile *ConfigFile) GetAllCredentials() (map[string]types.AuthConfig, addAll(newAuths) // Auth configs from a registry-specific helper should override those from the default store. - for registryHostname := range configFile.CredentialHelpers { - newAuth, err := configFile.GetAuthConfig(registryHostname) + for registryHostname := range c.CredentialHelpers { + newAuth, err := c.GetAuthConfig(registryHostname) if err != nil { // TODO(thaJeztah): use context-logger, so that this output can be suppressed (in tests). logrus.WithError(err).Warnf("Failed to get credentials for registry: %s", registryHostname) @@ -402,16 +431,16 @@ func (configFile *ConfigFile) GetAllCredentials() (map[string]types.AuthConfig, } // GetFilename returns the file name that this config file is based on. -func (configFile *ConfigFile) GetFilename() string { - return configFile.Filename +func (c *ConfigFile) GetFilename() string { + return c.Filename } // PluginConfig retrieves the requested option for the given plugin. -func (configFile *ConfigFile) PluginConfig(pluginname, option string) (string, bool) { - if configFile.Plugins == nil { +func (c *ConfigFile) PluginConfig(pluginname, option string) (string, bool) { + if c.Plugins == nil { return "", false } - pluginConfig, ok := configFile.Plugins[pluginname] + pluginConfig, ok := c.Plugins[pluginname] if !ok { return "", false } @@ -423,14 +452,14 @@ func (configFile *ConfigFile) PluginConfig(pluginname, option string) (string, b // plugin. Passing a value of "" will remove the option. If removing // the final config item for a given plugin then also cleans up the // overall plugin entry. -func (configFile *ConfigFile) SetPluginConfig(pluginname, option, value string) { - if configFile.Plugins == nil { - configFile.Plugins = make(map[string]map[string]string) +func (c *ConfigFile) SetPluginConfig(pluginname, option, value string) { + if c.Plugins == nil { + c.Plugins = make(map[string]map[string]string) } - pluginConfig, ok := configFile.Plugins[pluginname] + pluginConfig, ok := c.Plugins[pluginname] if !ok { pluginConfig = make(map[string]string) - configFile.Plugins[pluginname] = pluginConfig + c.Plugins[pluginname] = pluginConfig } if value != "" { pluginConfig[option] = value @@ -438,6 +467,6 @@ func (configFile *ConfigFile) SetPluginConfig(pluginname, option, value string) delete(pluginConfig, option) } if len(pluginConfig) == 0 { - delete(configFile.Plugins, pluginname) + delete(c.Plugins, pluginname) } } diff --git a/vendor/github.com/docker/cli/cli/config/credentials/default_store.go b/vendor/github.com/docker/cli/cli/config/credentials/default_store.go index a36afc41..35b9ae4f 100644 --- a/vendor/github.com/docker/cli/cli/config/credentials/default_store.go +++ b/vendor/github.com/docker/cli/cli/config/credentials/default_store.go @@ -2,12 +2,19 @@ package credentials import "os/exec" -// DetectDefaultStore return the default credentials store for the platform if -// no user-defined store is passed, and the store executable is available. -func DetectDefaultStore(store string) string { - if store != "" { +// DetectDefaultStore returns the credentials store to use if no user-defined +// custom helper is passed. +// +// Some platforms define a preferred helper, in which case it attempts to look +// up the helper binary before falling back to the platform's default. +// +// If no user-defined helper is passed, and no helper is found, it returns an +// empty string, which means credentials are stored unencrypted in the CLI's +// config-file without the use of a credentials store. +func DetectDefaultStore(customStore string) string { + if customStore != "" { // use user-defined - return store + return customStore } platformDefault := defaultCredentialsStore() diff --git a/vendor/github.com/google/go-containerregistry/internal/gzip/zip.go b/vendor/github.com/google/go-containerregistry/internal/gzip/zip.go index 018c0f8c..98100c02 100644 --- a/vendor/github.com/google/go-containerregistry/internal/gzip/zip.go +++ b/vendor/github.com/google/go-containerregistry/internal/gzip/zip.go @@ -51,33 +51,31 @@ func ReadCloserLevel(r io.ReadCloser, level int) io.ReadCloser { // Returns err so we can pw.CloseWithError(err) go func() error { - // TODO(go1.14): Just defer {pw,gw,r}.Close like you'd expect. - // Context: https://golang.org/issue/24283 + // Always close the source reader when the goroutine exits, + // regardless of which error path is taken. This prevents + // resource leaks (e.g. pullLimiter token slots held by + // limitedReadCloser wrappers around r). + defer r.Close() + gw, err := gzip.NewWriterLevel(bw, level) if err != nil { return pw.CloseWithError(err) } + defer gw.Close() + defer pw.Close() if _, err := io.Copy(gw, r); err != nil { - defer r.Close() - defer gw.Close() return pw.CloseWithError(err) } - // Close gzip writer to Flush it and write gzip trailers. if err := gw.Close(); err != nil { return pw.CloseWithError(err) } - // Flush bufio writer to ensure we write out everything. if err := bw.Flush(); err != nil { return pw.CloseWithError(err) } - // We don't really care if these fail. - defer pw.Close() - defer r.Close() - return nil }() diff --git a/vendor/github.com/google/go-containerregistry/internal/limit/limit.go b/vendor/github.com/google/go-containerregistry/internal/limit/limit.go new file mode 100644 index 00000000..29d2b08a --- /dev/null +++ b/vendor/github.com/google/go-containerregistry/internal/limit/limit.go @@ -0,0 +1,36 @@ +// Copyright 2026 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package limit provides bounded reads from io.Readers. +package limit + +import ( + "fmt" + "io" +) + +// ReadAll reads from r until EOF and returns the data. If r produces more +// than max bytes, it returns an error instead of a silently truncated +// slice. Use this in preference to io.ReadAll(io.LimitReader(r, max)) +// when callers must distinguish a complete read from a truncated one. +func ReadAll(r io.Reader, max int64) ([]byte, error) { + b, err := io.ReadAll(io.LimitReader(r, max+1)) + if err != nil { + return nil, err + } + if int64(len(b)) > max { + return nil, fmt.Errorf("body exceeds %d byte limit", max) + } + return b, nil +} diff --git a/vendor/github.com/google/go-containerregistry/pkg/name/registry.go b/vendor/github.com/google/go-containerregistry/pkg/name/registry.go index 7531d242..47802148 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/name/registry.go +++ b/vendor/github.com/google/go-containerregistry/pkg/name/registry.go @@ -28,10 +28,10 @@ import ( var reLocal = regexp.MustCompile(`.*\.localhost(?::\d{1,5})?$`) // Detect the loopback IP (127.0.0.1) -var reLoopback = regexp.MustCompile(regexp.QuoteMeta("127.0.0.1")) +var reLoopback = regexp.MustCompile(`^127\.0\.0\.1(?::\d{1,5})?$`) // Detect the loopback IPV6 (::1) -var reipv6Loopback = regexp.MustCompile(regexp.QuoteMeta("::1")) +var reipv6Loopback = regexp.MustCompile(`^(::1|\[::1\](?::\d{1,5})?)$`) // Registry stores a docker registry name in a structured form. type Registry struct { diff --git a/vendor/github.com/google/go-containerregistry/pkg/name/repository.go b/vendor/github.com/google/go-containerregistry/pkg/name/repository.go index 29079757..efde6e86 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/name/repository.go +++ b/vendor/github.com/google/go-containerregistry/pkg/name/repository.go @@ -85,11 +85,12 @@ func NewRepository(name string, opts ...Option) (Repository, error) { var registry string repo := name parts := strings.SplitN(name, regRepoDelimiter, 2) - if len(parts) == 2 && (strings.ContainsRune(parts[0], '.') || strings.ContainsRune(parts[0], ':')) { + maybeRegistry := parts[0] + if len(parts) == 2 && (maybeRegistry == "localhost" || strings.ContainsAny(maybeRegistry, ".:")) { // The first part of the repository is treated as the registry domain - // iff it contains a '.' or ':' character, otherwise it is all repository - // and the domain defaults to Docker Hub. - registry = parts[0] + // if it is localhost or contains a '.' or ':' character, otherwise it + // is all repository and the domain defaults to Docker Hub. + registry = maybeRegistry repo = parts[1] } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go index a6186b37..09458e96 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go @@ -365,6 +365,15 @@ func extractLayer(tarWriter *tar.Writer, fileMap map[string]bool, layer v1.Layer } } } + + // Drain any bytes the tar.Reader did not consume (trailing data after the + // end-of-archive marker) so the underlying verifying reader reaches io.EOF + // and the layer's digest is verified. Without this, a layer whose contents + // do not match the manifest's layer digest is extracted without error. + // pkg/v1/validate/layer.go performs the same drain. + if _, err := io.Copy(io.Discard, layerReader); err != nil { + return fmt.Errorf("verifying layer: %w", err) + } return nil } @@ -501,6 +510,12 @@ func layerTime(layer v1.Layer, t time.Time) (v1.Layer, error) { } } + // Drain trailing bytes so the underlying verifying reader reaches io.EOF + // and the layer digest is verified (see extractLayer). + if _, err := io.Copy(io.Discard, layerReader); err != nil { + return nil, fmt.Errorf("verifying layer: %w", err) + } + if err := tarWriter.Close(); err != nil { return nil, err } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/catalog.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/catalog.go index a0281b9f..7b9cc0e2 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/catalog.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/catalog.go @@ -122,7 +122,7 @@ func (f *fetcher) catalogPage(ctx context.Context, reg name.Registry, next strin return nil, err } - uri, err := getNextPageURL(resp) + uri, err := getNextPageURLForRegistry(resp, reg) if err != nil { return nil, err } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/fetcher.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/fetcher.go index 3bda1d09..4b238d12 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/fetcher.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/fetcher.go @@ -24,6 +24,7 @@ import ( "net/url" "strings" + "github.com/google/go-containerregistry/internal/limit" "github.com/google/go-containerregistry/internal/redact" "github.com/google/go-containerregistry/internal/verify" "github.com/google/go-containerregistry/pkg/authn" @@ -168,7 +169,7 @@ func (f *fetcher) fetchManifest(ctx context.Context, ref name.Reference, accepta return nil, nil, err } - manifest, err := io.ReadAll(io.LimitReader(resp.Body, manifestLimit)) + manifest, err := limit.ReadAll(resp.Body, manifestLimit) if err != nil { return nil, nil, err } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/list.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/list.go index 910d2a94..9beff7dc 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/list.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/list.go @@ -17,6 +17,7 @@ package remote import ( "context" "encoding/json" + "errors" "fmt" "net/http" "net/url" @@ -85,7 +86,7 @@ func (f *fetcher) listPage(ctx context.Context, repo name.Repository, next strin return nil, err } - uri, err := getNextPageURL(resp) + uri, err := getNextPageURL(resp, repo) if err != nil { return nil, err } @@ -99,8 +100,9 @@ func (f *fetcher) listPage(ctx context.Context, repo name.Repository, next strin // getNextPageURL checks if there is a Link header in a http.Response which // contains a link to the next page. If yes it returns the url.URL of the next -// page otherwise it returns nil. -func getNextPageURL(resp *http.Response) (*url.URL, error) { +// page otherwise it returns nil. It validates that the resolved URL points +// to the same registry to prevent SSRF attacks. +func getNextPageURL(resp *http.Response, repo name.Repository) (*url.URL, error) { link := resp.Header.Get("Link") if link == "" { return nil, nil @@ -115,6 +117,9 @@ func getNextPageURL(resp *http.Response) (*url.URL, error) { return nil, fmt.Errorf("failed to parse link header: missing '>' in: %s", link) } link = link[1:end] + if link == "" { + return nil, nil + } linkURL, err := url.Parse(link) if err != nil { @@ -124,9 +129,31 @@ func getNextPageURL(resp *http.Response) (*url.URL, error) { return nil, nil } linkURL = resp.Request.URL.ResolveReference(linkURL) + + // Validate that the pagination URL points to the same registry to prevent SSRF. + if err := validatePaginationURL(linkURL, repo); err != nil { + return nil, err + } + return linkURL, nil } +// validatePaginationURL checks that a pagination URL is safe to follow. +func validatePaginationURL(u *url.URL, repo name.Repository) error { + return validatePaginationURLHost(u, repo.Scheme(), repo.RegistryStr()) +} + +// validatePaginationURLHost checks that a pagination URL is safe to follow. +func validatePaginationURLHost(u *url.URL, scheme, host string) error { + if u.Scheme != scheme { + return fmt.Errorf("pagination URL scheme %q does not match registry scheme %q", u.Scheme, scheme) + } + if u.Host != host { + return errors.New("pagination URL host does not match registry host: potential SSRF attack") + } + return nil +} + type Lister struct { f *fetcher repo name.Repository @@ -150,3 +177,40 @@ func (l *Lister) Next(ctx context.Context) (*Tags, error) { func (l *Lister) HasNext() bool { return l.page != nil && (!l.needMore || l.page.Next != "") } + +// getNextPageURLForRegistry is like getNextPageURL but for name.Registry. +func getNextPageURLForRegistry(resp *http.Response, reg name.Registry) (*url.URL, error) { + link := resp.Header.Get("Link") + if link == "" { + return nil, nil + } + + if link[0] != '<' { + return nil, fmt.Errorf("failed to parse link header: missing '<' in: %s", link) + } + + end := strings.Index(link, ">") + if end == -1 { + return nil, fmt.Errorf("failed to parse link header: missing '>' in: %s", link) + } + link = link[1:end] + if link == "" { + return nil, nil + } + + linkURL, err := url.Parse(link) + if err != nil { + return nil, err + } + if resp.Request == nil || resp.Request.URL == nil { + return nil, nil + } + linkURL = resp.Request.URL.ResolveReference(linkURL) + + // Validate that the pagination URL points to the same registry to prevent SSRF. + if err := validatePaginationURLHost(linkURL, reg.Scheme(), reg.RegistryStr()); err != nil { + return nil, err + } + + return linkURL, nil +} diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/referrers.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/referrers.go index 17e9c26e..c23e1d83 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/referrers.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/referrers.go @@ -18,10 +18,10 @@ import ( "bytes" "context" "errors" - "io" "net/http" "strings" + "github.com/google/go-containerregistry/internal/limit" "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/empty" @@ -67,7 +67,7 @@ func (f *fetcher) fetchReferrers(ctx context.Context, filter map[string]string, var b []byte if resp.StatusCode == http.StatusOK && resp.Header.Get("Content-Type") == string(types.OCIImageIndex) { - b, err = io.ReadAll(io.LimitReader(resp.Body, manifestLimit)) + b, err = limit.ReadAll(resp.Body, manifestLimit) if err != nil { return nil, err } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go index f845dd1f..cbc2b1d4 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go @@ -19,13 +19,13 @@ import ( "encoding/json" "errors" "fmt" - "io" "net" "net/http" "net/url" "strings" "sync" + "github.com/google/go-containerregistry/internal/limit" "github.com/google/go-containerregistry/internal/redact" "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/logs" @@ -247,7 +247,23 @@ func (bt *bearerTransport) RoundTrip(in *http.Request) (*http.Response, error) { if err = bt.refresh(in.Context()); err != nil { return nil, err } - return sendRequest() + // Re-attach the freshly fetched token, but only when the request is + // still talking to the registry we authenticated against. matchesHost + // guards against forwarding the Authorization header across an + // http.Client-level redirect to a different host: a malicious or + // compromised registry can 302 the request to an attacker-controlled + // host, answer the follow-up with a Bearer challenge, and harvest the + // token if we re-attach it unconditionally. For a cross-host request + // fall back to sendRequest(), which omits the credential, rather than + // leaking it to a host we never logged in to. + if !matchesHost(bt.registry.RegistryStr(), in, bt.scheme) { + return sendRequest() + } + bt.mx.RLock() + tok := bt.bearer.RegistryToken + bt.mx.RUnlock() + in.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tok)) + return bt.inner.RoundTrip(in) } return res, err @@ -420,7 +436,7 @@ func (bt *bearerTransport) refreshOauth(ctx context.Context) ([]byte, error) { return nil, err } - return io.ReadAll(io.LimitReader(resp.Body, maxTokenBodySize)) + return limit.ReadAll(resp.Body, maxTokenBodySize) } // https://docs.docker.com/registry/spec/auth/token/ @@ -465,5 +481,5 @@ func (bt *bearerTransport) refreshBasic(ctx context.Context) ([]byte, error) { return nil, err } - return io.ReadAll(io.LimitReader(resp.Body, maxTokenBodySize)) + return limit.ReadAll(resp.Body, maxTokenBodySize) } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/error.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/error.go index 934484db..7b14b8c4 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/error.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/error.go @@ -22,6 +22,7 @@ import ( "net/http" "strings" + "github.com/google/go-containerregistry/internal/limit" "github.com/google/go-containerregistry/internal/redact" ) @@ -167,7 +168,7 @@ func CheckError(resp *http.Response, codes ...int) error { } } - b, err := io.ReadAll(io.LimitReader(resp.Body, maxErrorBodySize)) + b, err := limit.ReadAll(resp.Body, maxErrorBodySize) if err != nil { return err } @@ -191,7 +192,7 @@ func makeError(resp *http.Response, body []byte) *Error { } func retryError(resp *http.Response) error { - b, err := io.ReadAll(io.LimitReader(resp.Body, maxErrorBodySize)) + b, err := limit.ReadAll(resp.Body, maxErrorBodySize) if err != nil { return err } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/tarball/image.go b/vendor/github.com/google/go-containerregistry/pkg/v1/tarball/image.go index 96c0cce4..9b0350b1 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/tarball/image.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/tarball/image.go @@ -248,7 +248,7 @@ func followLinks(opener Opener, filePath string, visited map[string]bool) (io.Re if err != nil { return nil, err } - if hdr.Name == filePath { + if path.Clean(hdr.Name) == path.Clean(filePath) { if hdr.Typeflag == tar.TypeSymlink || hdr.Typeflag == tar.TypeLink { currentDir := filepath.Dir(filePath) return followLinks(opener, path.Join(currentDir, path.Clean(hdr.Linkname)), visited) @@ -374,6 +374,9 @@ func (c *compressedImage) Manifest() (*v1.Manifest, error) { if err != nil { return nil, err } + if i >= len(cfg.RootFS.DiffIDs) { + return nil, fmt.Errorf("tarball manifest references %d layer(s) but config has %d rootfs.diff_ids; the config may not describe a runnable image (for example, a buildkit cacheconfig)", len(c.imgDescriptor.Layers), len(cfg.RootFS.DiffIDs)) + } diffid := cfg.RootFS.DiffIDs[i] if d, ok := c.imgDescriptor.LayerSources[diffid]; ok { // If it's a foreign layer, just append the descriptor so we can avoid diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/tarball/write.go b/vendor/github.com/google/go-containerregistry/pkg/v1/tarball/write.go index e607df16..062268a5 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/tarball/write.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/tarball/write.go @@ -191,16 +191,7 @@ func writeImagesToTar(imageToTags map[v1.Image][]string, m []byte, size int64, w } seenLayerDigests[hex] = struct{}{} - r, err := l.Compressed() - if err != nil { - return sendProgressWriterReturn(pw, err) - } - blobSize, err := l.Size() - if err != nil { - return sendProgressWriterReturn(pw, err) - } - - if err := writeTarEntry(tf, layerFiles[i], r, blobSize); err != nil { + if err := writeLayer(tf, layerFiles[i], l); err != nil { return sendProgressWriterReturn(pw, err) } } @@ -380,6 +371,23 @@ func writeTarEntry(tf *tar.Writer, path string, r io.Reader, size int64) error { return err } +// writeLayer streams a layer's compressed blob into the tar writer and closes +// the reader before returning. The close releases any pull-limiter slot held +// by a remote-backed layer (remote.WithJobs); leaving it open would deadlock +// the write loop after defaultJobs layers. +func writeLayer(tf *tar.Writer, name string, l v1.Layer) error { + r, err := l.Compressed() + if err != nil { + return err + } + defer r.Close() + blobSize, err := l.Size() + if err != nil { + return err + } + return writeTarEntry(tf, name, r, blobSize) +} + // ComputeManifest get the manifest.json that will be written to the tarball // for multiple references func ComputeManifest(refToImage map[name.Reference]v1.Image) (Manifest, error) { diff --git a/vendor/golang.org/x/net/http2/server_wrap.go b/vendor/golang.org/x/net/http2/server_wrap.go index a7a09551..737f1f05 100644 --- a/vendor/golang.org/x/net/http2/server_wrap.go +++ b/vendor/golang.org/x/net/http2/server_wrap.go @@ -10,9 +10,11 @@ package http2 import ( "context" + "crypto/tls" "errors" "net" "net/http" + "slices" "sync" "time" ) @@ -44,6 +46,20 @@ func configureServer(s *http.Server, conf *Server) error { h2.IdleTimeout = h1.ReadTimeout } } + + // Register h2 and http/1.1 ALPN protocols on s.TLSConfig, matching + // the pre-wrapping implementation in server.go, so that TLS listeners + // built from s.TLSConfig still negotiate HTTP/2. + if s.TLSConfig == nil { + s.TLSConfig = new(tls.Config) + } + if !slices.Contains(s.TLSConfig.NextProtos, NextProtoTLS) { + s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS) + } + if !slices.Contains(s.TLSConfig.NextProtos, "http/1.1") { + s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, "http/1.1") + } + conf.state = &serverInternalState{ s1: s, } diff --git a/vendor/golang.org/x/net/http2/transport_wrap.go b/vendor/golang.org/x/net/http2/transport_wrap.go index d25d99bd..eab2e6b0 100644 --- a/vendor/golang.org/x/net/http2/transport_wrap.go +++ b/vendor/golang.org/x/net/http2/transport_wrap.go @@ -22,8 +22,8 @@ import ( ) func configureTransport(t1 *http.Transport) error { - // ConfigureTransport is a no-op: The http.Transport already supports HTTP/2. - return nil + _, err := configureTransports(t1) + return err } func configureTransports(t1 *http.Transport) (*Transport, error) { @@ -31,6 +31,17 @@ func configureTransports(t1 *http.Transport) (*Transport, error) { // linked to the http.Transport's. tr2 := &Transport{} tr2.configure(t1) + // Enable HTTP/2 on the transport, as the pre-wrapping implementation did: + // net/http does not auto-enable it for a transport with a custom + // TLSClientConfig or dialer. + if t1.TLSClientConfig == nil { + t1.TLSClientConfig = &tls.Config{} + } + if t1.Protocols == nil { + t1.Protocols = new(http.Protocols) + t1.Protocols.SetHTTP1(true) + } + t1.Protocols.SetHTTP2(true) return tr2, nil } diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go index de683684..1e5549ab 100644 --- a/vendor/golang.org/x/tools/go/packages/packages.go +++ b/vendor/golang.org/x/tools/go/packages/packages.go @@ -815,6 +815,12 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { needsrc: needsrc, goVersion: response.GoVersion, } + // Don't trust the driver to respond with duplicate-free + // package names (go.dev/issue/63822). + if _, ok := ld.pkgs[lpkg.ID]; ok { + return nil, fmt.Errorf("%s response contained duplicate packages for ID %q", + cond(ld.externalDriver, "go/packages driver", "go list"), lpkg.ID) + } ld.pkgs[lpkg.ID] = lpkg if rootIndex >= 0 { initial[rootIndex] = lpkg @@ -1589,3 +1595,11 @@ func usesExportData(cfg *Config) bool { } type unit struct{} + +func cond[T any](cond bool, t, f T) T { + if cond { + return t + } else { + return f + } +} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go index 4c9450f4..686f171d 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go @@ -823,6 +823,9 @@ func (p *iexporter) doDecl(obj types.Object) { w.pos(m.Pos()) w.string(m.Name()) sig, _ := m.Type().(*types.Signature) + if w.p.version >= iexportVersionGenericMethods && w.bool(sig.TypeParams().Len() > 0) { + w.tparamList(obj.Name()+"."+m.Name(), sig.TypeParams(), obj.Pkg()) + } // Receiver type parameters are type arguments of the receiver type, so // their name must be qualified before exporting recv. diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go index 1ee4e935..7b1723e0 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go @@ -48,13 +48,14 @@ func (r *intReader) uint64() uint64 { // Keep this in sync with constants in iexport.go. const ( - iexportVersionGo1_11 = 0 - iexportVersionPosCol = 1 - iexportVersionGo1_18 = 2 - iexportVersionGenerics = 2 - iexportVersion = iexportVersionGenerics - - iexportVersionCurrent = 2 + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGo1_18 = 2 + iexportVersionGenerics = 2 + iexportVersionGenericMethods = 3 + iexportVersion = iexportVersionGenericMethods + + iexportVersionCurrent = 3 ) type ident struct { @@ -179,9 +180,9 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte version = int64(r.uint64()) switch version { - case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: + case iexportVersionGenericMethods, iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: default: - if version > iexportVersionGo1_18 { + if version > iexportVersionGenericMethods { errorf("unstable iexport format version %d, just rebuild compiler and std library", version) } else { errorf("unknown iexport format version %d", version) @@ -614,6 +615,10 @@ func (r *importReader) obj(pkg *types.Package, name string) { for n := r.uint64(); n > 0; n-- { mpos := r.pos() mname := r.ident() + var tpars []*types.TypeParam + if r.p.version >= iexportVersionGenericMethods && r.bool() { + tpars = r.tparamList() + } recv := r.param(pkg) // If the receiver has any targs, set those as the @@ -628,8 +633,7 @@ func (r *importReader) obj(pkg *types.Package, name string) { rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam) } } - msig := r.signature(pkg, recv, rparams, nil) - + msig := r.signature(pkg, recv, rparams, tpars) named.AddMethod(types.NewFunc(mpos, pkg, mname, msig)) } } diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go index d29ecfb0..b99ea6c9 100644 --- a/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/vendor/golang.org/x/tools/internal/imports/fix.go @@ -273,7 +273,6 @@ func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) erro } unknown = append(unknown, imp.ImportPath) } - names, err := p.source.LoadPackageNames(ctx, p.srcDir, unknown) if err != nil { return err diff --git a/vendor/golang.org/x/tools/internal/imports/imports.go b/vendor/golang.org/x/tools/internal/imports/imports.go index b5f5218b..07229383 100644 --- a/vendor/golang.org/x/tools/internal/imports/imports.go +++ b/vendor/golang.org/x/tools/internal/imports/imports.go @@ -74,6 +74,10 @@ func Process(filename string, src []byte, opt *Options) (formatted []byte, err e // Note that filename's directory influences which imports can be chosen, // so it is important that filename be accurate. func FixImports(ctx context.Context, filename string, src []byte, goroot string, logf func(string, ...any), source Source) (fixes []*ImportFix, err error) { + if source == nil { + // In case someone adds a defective call from a new place + panic("source is nil") + } ctx, done := event.Start(ctx, "imports.FixImports") defer done() diff --git a/vendor/golang.org/x/tools/internal/typesinternal/element.go b/vendor/golang.org/x/tools/internal/typesinternal/element.go index 5fe4d8ab..89eeea16 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/element.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/element.go @@ -37,6 +37,10 @@ func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T type tmset := msets.MethodSet(T) for method := range tmset.Methods() { sig := method.Type().(*types.Signature) + if sig.TypeParams() != nil { + continue // skip type-parameterized methods + } + // It is tempting to call visit(sig, false) // but, as noted in golang.org/cl/65450043, // the Signature.Recv field is ignored by @@ -123,10 +127,10 @@ func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T type case *types.TypeParam, *types.Union: // forEachReachable must not be called on parameterized types. - panic(T) + panic(fmt.Sprintf("ForEachElement called on type containing %T", T)) default: - panic(T) + panic(fmt.Sprintf("ForEachElement called on unexpected type %T", T)) } } visit(T, false) diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go index 6582cc81..d2c0b4c5 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/types.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go @@ -22,6 +22,7 @@ import ( "go/ast" "go/token" "go/types" + "iter" "reflect" "golang.org/x/tools/go/ast/inspector" @@ -242,3 +243,30 @@ func ObjectKind(obj types.Object) string { } return "unknown symbol" } + +// ImplicitFieldSelections returns the sequence of implicit embedded fields +// traversed by the given selection. It skips the final leaf field or method. +// The boolean component indicates whether the traversal traversed a pointer. +func ImplicitFieldSelections(seln types.Selection) iter.Seq2[*types.Var, bool] { + return func(yield func(*types.Var, bool) bool) { + var ( + t = seln.Recv() + indices = seln.Index() + ) + for _, idx := range indices[:len(indices)-1] { + ptr, isPtr := t.Underlying().(*types.Pointer) + if isPtr { + t = ptr.Elem() + } + structType, ok := t.Underlying().(*types.Struct) + if !ok { + break + } + field := structType.Field(idx) + if !yield(field, isPtr) { + break + } + t = field.Type() + } + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 98ce2a99..91d43e6c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -272,7 +272,7 @@ github.com/davecgh/go-spew/spew # github.com/distribution/reference v0.6.0 ## explicit; go 1.20 github.com/distribution/reference -# github.com/docker/cli v29.4.3+incompatible +# github.com/docker/cli v29.5.3+incompatible ## explicit github.com/docker/cli/cli/config github.com/docker/cli/cli/config/configfile @@ -435,11 +435,12 @@ github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/google/go-containerregistry v0.21.6 +# github.com/google/go-containerregistry v0.21.7 ## explicit; go 1.25.0 github.com/google/go-containerregistry/internal/and github.com/google/go-containerregistry/internal/compression github.com/google/go-containerregistry/internal/gzip +github.com/google/go-containerregistry/internal/limit github.com/google/go-containerregistry/internal/redact github.com/google/go-containerregistry/internal/retry github.com/google/go-containerregistry/internal/retry/wait @@ -1037,12 +1038,12 @@ golang.org/x/crypto/ssh/internal/bcrypt_pbkdf ## explicit; go 1.25.0 golang.org/x/exp/constraints golang.org/x/exp/slices -# golang.org/x/mod v0.36.0 +# golang.org/x/mod v0.37.0 ## explicit; go 1.25.0 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/module golang.org/x/mod/semver -# golang.org/x/net v0.55.0 +# golang.org/x/net v0.56.0 ## explicit; go 1.25.0 golang.org/x/net/http/httpguts golang.org/x/net/http2 @@ -1103,7 +1104,7 @@ golang.org/x/text/width # golang.org/x/time v0.15.0 ## explicit; go 1.25.0 golang.org/x/time/rate -# golang.org/x/tools v0.45.0 +# golang.org/x/tools v0.46.0 ## explicit; go 1.25.0 golang.org/x/tools/cover golang.org/x/tools/go/ast/astutil