From 3ee4c06af6c69aa79e792079a8d9822ffc6dd2f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Fri, 4 Sep 2026 15:57:10 +0200 Subject: [PATCH 01/26] Revert "e2e/container: Skip umask test until engine support" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 45a3e0bc2aece19bb2970905231b97dc3a86568b. Signed-off-by: Paweł Gronowski --- e2e/container/run_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e/container/run_test.go b/e2e/container/run_test.go index d45fe0865d..9151131a47 100644 --- a/e2e/container/run_test.go +++ b/e2e/container/run_test.go @@ -112,7 +112,6 @@ func TestRunWithCgroupNamespace(t *testing.T) { func TestRunUmask(t *testing.T) { environment.SkipIfDaemonNotLinux(t) - t.Skip("FIXME: un-skip once e2e tests v29.8.0") testCases := []struct { name string From e8bb7f7c818691f013fa9c1ff38a1202e735a669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Fri, 4 Sep 2026 15:59:11 +0200 Subject: [PATCH 02/26] e2e/container: Gate umask test on API support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- e2e/container/run_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/container/run_test.go b/e2e/container/run_test.go index 9151131a47..fb6c8d19c7 100644 --- a/e2e/container/run_test.go +++ b/e2e/container/run_test.go @@ -112,6 +112,7 @@ func TestRunWithCgroupNamespace(t *testing.T) { func TestRunUmask(t *testing.T) { environment.SkipIfDaemonNotLinux(t) + skip.If(t, versions.LessThan(environment.DaemonAPIVersion(t), "1.56")) testCases := []struct { name string From d6bc11318d18fb85988e101aba7e913609aadb7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 1 Oct 2026 18:58:38 +0200 Subject: [PATCH 03/26] Bump version to 29.9.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 89eac39afb..4552f1e80f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -29.8.2 +29.9.0 From b1f2c1dc060370c54e73d04f859f1107d8112ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 1 Oct 2026 19:01:36 +0200 Subject: [PATCH 04/26] cli-plugins/metadata: Add Features for optional plugin contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plugins had no generic way to declare support for optional CLI contracts, so each one would need its own top-level metadata field. Add Features, keyed by feature name. Values are arbitrary JSON so a feature can carry more than a boolean. Signed-off-by: Paweł Gronowski --- cli-plugins/metadata/metadata.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cli-plugins/metadata/metadata.go b/cli-plugins/metadata/metadata.go index 7061486a70..c35a5ad028 100644 --- a/cli-plugins/metadata/metadata.go +++ b/cli-plugins/metadata/metadata.go @@ -1,3 +1,6 @@ +// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: +//go:build go1.26 + package metadata const ( @@ -35,4 +38,7 @@ type Metadata struct { URL string `json:",omitempty"` // Hidden hides the plugin in completion and help message output. Hidden bool `json:",omitempty"` + // Features declares optional contracts supported by the plugin, keyed by + // feature name. + Features map[string]any `json:",omitempty"` } From b53372e86a35d4ca3c1e2b7b99018654962209c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 1 Oct 2026 19:01:41 +0200 Subject: [PATCH 05/26] cli/command: Add WithContextResolver to override context selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Callers that choose the context from configuration had to do it before Initialize. That meant loading the config file and context store themselves and handling --config a second time. WithContextResolver runs a callback inside Initialize after the config file and context store are loaded, but before telemetry and endpoint initialization. A non-empty result replaces the selected context, an empty result keeps normal selection, and an error aborts initialization. The API client and endpoint are resolved lazily, so they use the overridden context. Signed-off-by: Paweł Gronowski --- cli/command/cli.go | 13 +++++++++ cli/command/cli_options.go | 13 +++++++++ cli/command/cli_test.go | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/cli/command/cli.go b/cli/command/cli.go index e405c2cc4f..0d2f4b506f 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -68,6 +68,7 @@ type DockerCli struct { serverInfo ServerInfo contextStore store.Store currentContext string + contextResolver func(*DockerCli) (string, error) init sync.Once initErr error dockerEndpoint docker.Endpoint @@ -208,6 +209,8 @@ func (cli *DockerCli) HooksEnabled() bool { // Initialize the dockerCli runs initialization that must happen after command // line flags are parsed. +// +//nolint:gocyclo func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption) error { for _, o := range ops { if err := o(cli); err != nil { @@ -257,6 +260,16 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption) }, } + if cli.contextResolver != nil { + contextName, err := cli.contextResolver(cli) + if err != nil { + return err + } + if contextName != "" { + cli.currentContext = contextName + } + } + // TODO(krissetto): pass ctx to the funcs instead of using this if cli.enableGlobalMeter { cli.createGlobalMeterProvider(cli.baseCtx) diff --git a/cli/command/cli_options.go b/cli/command/cli_options.go index 469932f9c3..733cfbdf64 100644 --- a/cli/command/cli_options.go +++ b/cli/command/cli_options.go @@ -84,6 +84,19 @@ func WithDefaultContextStoreConfig() CLIOption { } } +// WithContextResolver overrides context selection during [DockerCli.Initialize]. +// The resolver runs after configuration and the context store are loaded, but +// before telemetry and endpoint initialization. +// An empty result preserves normal context selection; an error aborts +// initialization. +// The resolver must not initialize the API client. +func WithContextResolver(resolve func(*DockerCli) (string, error)) CLIOption { + return func(cli *DockerCli) error { + cli.contextResolver = resolve + return nil + } +} + // WithAPIClient configures the cli to use the given API client. func WithAPIClient(c client.APIClient) CLIOption { return func(cli *DockerCli) error { diff --git a/cli/command/cli_test.go b/cli/command/cli_test.go index 27be8d348c..09c093d5dd 100644 --- a/cli/command/cli_test.go +++ b/cli/command/cli_test.go @@ -325,6 +325,64 @@ func TestInitializeShouldAlwaysCreateTheContextStore(t *testing.T) { assert.Check(t, cli.ContextStore() != nil) } +func TestInitializeContextResolver(t *testing.T) { + resolverErr := errors.New("resolver failed") + + for _, tc := range []struct { + name string + context string + err error + }{ + {name: "resolved context", context: "resolved"}, + {name: "normal selection"}, + {name: "resolver failure", err: resolverErr}, + } { + t.Run(tc.name, func(t *testing.T) { + originalConfigDir := config.Dir() + t.Cleanup(func() { config.SetDir(originalConfigDir) }) + config.SetDir(t.TempDir()) + + configDir := t.TempDir() + cfg := configfile.New(filepath.Join(configDir, config.ConfigFileName)) + cfg.Features = map[string]string{"cloud": "foobar"} + assert.NilError(t, cfg.Save()) + + cli, err := NewDockerCli() + assert.NilError(t, err) + + var loadedConfig *configfile.ConfigFile + calls := 0 + + err = cli.Initialize(&flags.ClientOptions{ConfigDir: configDir, Context: "original"}, + WithContextResolver(func(cli *DockerCli) (string, error) { + calls++ + assert.Equal(t, config.Dir(), configDir) + loadedConfig = cli.ConfigFile() + assert.Equal(t, loadedConfig.Features["cloud"], "foobar") + assert.Assert(t, cli.ContextStore() != nil) + assert.Assert(t, cli.client == nil) + return tc.context, tc.err + }), + ) + assert.Equal(t, calls, 1) + assert.Assert(t, cli.ConfigFile() == loadedConfig) + assert.Assert(t, cli.client == nil) + + if tc.err != nil { + assert.ErrorIs(t, err, tc.err) + return + } + assert.NilError(t, err) + + wantContext := tc.context + if wantContext == "" { + wantContext = "original" + } + assert.Equal(t, cli.CurrentContext(), wantContext) + }) + } +} + func TestHooksEnabled(t *testing.T) { t.Run("disabled by default", func(t *testing.T) { // Make sure we don't depend on any existing ~/.docker/config.json From 6868874c983e4f55ba4e7a970e2ad7ba6e6db11c Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 1 Oct 2026 19:29:12 +0200 Subject: [PATCH 06/26] vendor: github.com/Microsoft/go-winio f19d9717deb0 full diff: https://github.com/Microsoft/go-winio/compare/v0.6.2...f19d9717deb0a33bb37c3580481dd1909782fc03 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 4 +- .../Microsoft/go-winio/.golangci.yml | 280 ++++++++++-------- .../github.com/Microsoft/go-winio/backup.go | 3 +- vendor/github.com/Microsoft/go-winio/ea.go | 2 +- vendor/github.com/Microsoft/go-winio/file.go | 14 +- .../github.com/Microsoft/go-winio/fileinfo.go | 1 - .../github.com/Microsoft/go-winio/hvsock.go | 1 - .../Microsoft/go-winio/internal/fs/fs.go | 2 +- .../go-winio/internal/fs/zsyscall_windows.go | 8 +- .../internal/socket/zsyscall_windows.go | 8 +- .../go-winio/internal/stringbuffer/wstring.go | 4 +- vendor/github.com/Microsoft/go-winio/pipe.go | 40 +-- .../Microsoft/go-winio/pkg/guid/guid.go | 2 +- .../go-winio/pkg/guid/guid_nonwindows.go | 1 - .../go-winio/pkg/guid/guid_windows.go | 1 - .../go-winio/pkg/guid/variant_string.go | 5 +- .../Microsoft/go-winio/privilege.go | 1 - .../github.com/Microsoft/go-winio/reparse.go | 61 +++- vendor/github.com/Microsoft/go-winio/sd.go | 1 - .../Microsoft/go-winio/zsyscall_windows.go | 8 +- vendor/modules.txt | 4 +- 22 files changed, 258 insertions(+), 195 deletions(-) diff --git a/vendor.mod b/vendor.mod index b1bfb7897a..897331811c 100644 --- a/vendor.mod +++ b/vendor.mod @@ -71,7 +71,7 @@ require ( require ( github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0 // indirect; see https://github.com/microsoft/hcsshim/pull/2545 github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect diff --git a/vendor.sum b/vendor.sum index 36d2533377..94304b0531 100644 --- a/vendor.sum +++ b/vendor.sum @@ -4,8 +4,8 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8af github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0 h1:71VU8kW/LCxJkx41+YYys1EgQO+AUnPa1TrxTSyYUCU= +github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0/go.mod h1:ma0QpxizD4fyyzJ1C7MIblymTD2Nxz5Mho/3CepwIZg= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= diff --git a/vendor/github.com/Microsoft/go-winio/.golangci.yml b/vendor/github.com/Microsoft/go-winio/.golangci.yml index faedfe937a..07a22649a0 100644 --- a/vendor/github.com/Microsoft/go-winio/.golangci.yml +++ b/vendor/github.com/Microsoft/go-winio/.golangci.yml @@ -1,9 +1,15 @@ +version: "2" +formatters: + enable: + - gofmt # files are gofmt'ed linters: enable: # style - containedctx # struct contains a context - dupl # duplicate code - - errname # erorrs are named correctly + - dupword # duplicate words in comments + - errname # errors are named correctly + - intrange # integer ranges in for loop - nolintlint # "//nolint" directives are properly explained - revive # golint replacement - unconvert # unnecessary conversions @@ -13,135 +19,155 @@ linters: - contextcheck # function uses a non-inherited context - errorlint # errors not wrapped for 1.13 - exhaustive # check exhaustiveness of enum switch statements - - gofmt # files are gofmt'ed + - gocritic # various code quality checks - gosec # security + - mirror # avoid allocations - nilerr # returns nil even with non-nil error - thelper # test helpers without t.Helper() - unparam # unused function params -issues: - exclude-dirs: - - pkg/etw/sample - - exclude-rules: - # err is very often shadowed in nested scopes - - linters: - - govet - text: '^shadow: declaration of "err" shadows declaration' - - # ignore long lines for skip autogen directives - - linters: - - revive - text: "^line-length-limit: " - source: "^//(go:generate|sys) " - - #TODO: remove after upgrading to go1.18 - # ignore comment spacing for nolint and sys directives - - linters: - - revive - text: "^comment-spacings: no space between comment delimiter and comment text" - source: "//(cspell:|nolint:|sys |todo)" - - # not on go 1.18 yet, so no any - - linters: - - revive - text: "^use-any: since GO 1.18 'interface{}' can be replaced by 'any'" - - # allow unjustified ignores of error checks in defer statements - - linters: - - nolintlint - text: "^directive `//nolint:errcheck` should provide explanation" - source: '^\s*defer ' - - # allow unjustified ignores of error lints for io.EOF - - linters: - - nolintlint - text: "^directive `//nolint:errorlint` should provide explanation" - source: '[=|!]= io.EOF' - - -linters-settings: - exhaustive: - default-signifies-exhaustive: true - govet: - enable-all: true - disable: - # struct order is often for Win32 compat - # also, ignore pointer bytes/GC issues for now until performance becomes an issue - - fieldalignment - nolintlint: - require-explanation: true - require-specific: true - revive: - # revive is more configurable than static check, so likely the preferred alternative to static-check - # (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997) - enable-all-rules: - true - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md + exclusions: + paths: + - pkg/etw/sample + presets: + - comments + - common-false-positives + - legacy + - std-error-handling rules: - # rules with required arguments - - name: argument-limit - disabled: true - - name: banned-characters - disabled: true - - name: cognitive-complexity - disabled: true - - name: cyclomatic - disabled: true - - name: file-header - disabled: true - - name: function-length - disabled: true - - name: function-result-limit - disabled: true - - name: max-public-structs - disabled: true - # geneally annoying rules - - name: add-constant # complains about any and all strings and integers - disabled: true - - name: confusing-naming # we frequently use "Foo()" and "foo()" together - disabled: true - - name: flag-parameter # excessive, and a common idiom we use - disabled: true - - name: unhandled-error # warns over common fmt.Print* and io.Close; rely on errcheck instead - disabled: true - # general config - - name: line-length-limit - arguments: - - 140 - - name: var-naming - arguments: - - [] - - - CID - - CRI - - CTRD - - DACL - - DLL - - DOS - - ETW - - FSCTL - - GCS - - GMSA - - HCS - - HV - - IO - - LCOW - - LDAP - - LPAC - - LTSC - - MMIO - - NT - - OCI - - PMEM - - PWSH - - RX - - SACl - - SID - - SMB - - TX - - VHD - - VHDX - - VMID - - VPCI - - WCOW - - WIM + # err is very often shadowed in nested scopes + - linters: + - govet + text: '^shadow: declaration of "err" shadows declaration' + + # ignore long lines for skip autogen directives + - linters: + - revive + text: "^line-length-limit: " + source: "^//(go:generate|sys) " + + # ignore comment spacing for sys directives + - linters: + - revive + text: "^comment-spacings: no space between comment delimiter and comment text" + source: "//(cspell:|sys )" + + # allow unjustified ignores of error checks in defer statements + - linters: + - nolintlint + text: "^directive `//nolint:errcheck` should provide explanation" + source: '^\s*defer ' + + # allow unjustified ignores of error lints for io.EOF + - linters: + - nolintlint + text: "^directive `//nolint:errorlint` should provide explanation" + source: '[=|!]= io.EOF' + + - linters: + - gosec + text: "^G115: integer overflow conversion" + + + settings: + exhaustive: + default-signifies-exhaustive: true + gocritic: + disable-all: true + enabled-checks: + - nilValReturn + - sprintfQuotedString + govet: + enable-all: true + disable: + # struct order is often for Win32 compat + # also, ignore pointer bytes/GC issues for now until performance becomes an issue + - fieldalignment + nolintlint: + require-explanation: true + require-specific: true + revive: + # revive is more configurable than static check, so likely the preferred alternative to static-check + # (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997) + enable-all-rules: + true + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md + rules: + # rules with required arguments + - name: argument-limit + disabled: true + - name: banned-characters + disabled: true + - name: cognitive-complexity + disabled: true + - name: cyclomatic + disabled: true + # covered by "exhaustive" linter + - name: enforce-switch-style + disabled: true + - name: file-header + disabled: true + - name: function-length + disabled: true + - name: function-result-limit + disabled: true + - name: max-public-structs + disabled: true + # generally annoying rules + - name: add-constant # complains about any and all strings and integers + disabled: true + - name: confusing-naming # we frequently use "Foo()" and "foo()" together + disabled: true + - name: flag-parameter # excessive, and a common idiom we use + disabled: true + - name: multiline-if-init # too opinionated; see https://github.com/microsoft/go-winio/pull/325#issuecomment-5822487436 + disabled: true + - name: unhandled-error # warns over common fmt.Print* and io.Close; rely on errcheck instead + disabled: true + # general config + - name: line-length-limit + arguments: + - 140 + - name: var-naming + arguments: + - [] + - - CID + - CRI + - CTRD + - DACL + - DLL + - DOS + - ETW + - FSCTL + - GCS + - GMSA + - HCS + - HV + - IO + - LCOW + - LDAP + - LPAC + - LTSC + - MMIO + - NT + - OCI + - PMEM + - PWSH + - RX + - SACl + - SID + - SMB + - TX + - VHD + - VHDX + - VMID + - VPCI + - WCOW + - WIM + staticcheck: + # Enable all options, with some exceptions. + # For defaults, see https://golangci-lint.run/usage/linters/#staticcheck + checks: + - all + - -QF1008 # Omit embedded fields from selector expression; https://staticcheck.dev/docs/checks/#QF1008 + - -ST1003 # Poorly chosen identifier; https://staticcheck.dev/docs/checks/#ST1003 diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go index b54341daac..37055fa6a9 100644 --- a/vendor/github.com/Microsoft/go-winio/backup.go +++ b/vendor/github.com/Microsoft/go-winio/backup.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package winio @@ -36,7 +35,7 @@ const ( StreamSparseAttributes = uint32(8) ) -//nolint:revive // var-naming: ALL_CAPS +//nolint:revive,nolintlint // var-naming: ALL_CAPS const ( WRITE_DAC = windows.WRITE_DAC WRITE_OWNER = windows.WRITE_OWNER diff --git a/vendor/github.com/Microsoft/go-winio/ea.go b/vendor/github.com/Microsoft/go-winio/ea.go index e104dbdfdf..00a4bd96c8 100644 --- a/vendor/github.com/Microsoft/go-winio/ea.go +++ b/vendor/github.com/Microsoft/go-winio/ea.go @@ -95,7 +95,7 @@ func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { return err } - _, err = buf.Write([]byte(ea.Name)) + _, err = buf.WriteString(ea.Name) if err != nil { return err } diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go index fe82a180db..19c5f8940e 100644 --- a/vendor/github.com/Microsoft/go-winio/file.go +++ b/vendor/github.com/Microsoft/go-winio/file.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package winio @@ -235,12 +234,17 @@ func (f *win32File) Read(b []byte) (int, error) { runtime.KeepAlive(b) // Handle EOF conditions. - if err == nil && n == 0 && len(b) != 0 { - return 0, io.EOF - } else if err == windows.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno + switch err { + case windows.ERROR_BROKEN_PIPE: //nolint:errorlint // err is Errno return 0, io.EOF + case nil: + if n == 0 && len(b) != 0 { + return 0, io.EOF + } + return n, nil + default: + return n, err } - return n, err } // Write writes to a file handle. diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go index c860eb9917..01cd891e84 100644 --- a/vendor/github.com/Microsoft/go-winio/fileinfo.go +++ b/vendor/github.com/Microsoft/go-winio/fileinfo.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package winio diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go index c4fdd9d4ae..d4960f5b0a 100644 --- a/vendor/github.com/Microsoft/go-winio/hvsock.go +++ b/vendor/github.com/Microsoft/go-winio/hvsock.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package winio diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go b/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go index 0cd9621df7..f3bc2aeb8a 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go +++ b/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go @@ -243,7 +243,7 @@ const ( // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew func GetFinalPathNameByHandle(h windows.Handle, flags GetFinalPathFlag) (string, error) { b := stringbuffer.NewWString() - //TODO: can loop infinitely if Win32 keeps returning the same (or a larger) n? + // TODO: can loop infinitely if Win32 keeps returning the same (or a larger) n? for { n, err := windows.GetFinalPathNameByHandle(h, b.Pointer(), b.Cap(), uint32(flags)) if err != nil { diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go index a94e234c70..f7b27abfcc 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go @@ -15,12 +15,8 @@ var _ unsafe.Pointer // Do the interface allocations only once for common // Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_IO_PENDING error = windows.ERROR_IO_PENDING errERROR_EINVAL error = syscall.EINVAL ) @@ -30,7 +26,7 @@ func errnoErr(e syscall.Errno) error { switch e { case 0: return errERROR_EINVAL - case errnoERROR_IO_PENDING: + case windows.ERROR_IO_PENDING: return errERROR_IO_PENDING } return e diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go index e1504126aa..06e84da653 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go @@ -15,12 +15,8 @@ var _ unsafe.Pointer // Do the interface allocations only once for common // Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_IO_PENDING error = windows.ERROR_IO_PENDING errERROR_EINVAL error = syscall.EINVAL ) @@ -30,7 +26,7 @@ func errnoErr(e syscall.Errno) error { switch e { case 0: return errERROR_EINVAL - case errnoERROR_IO_PENDING: + case windows.ERROR_IO_PENDING: return errERROR_IO_PENDING } return e diff --git a/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go b/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go index 42ebc019fc..2295408733 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go +++ b/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go @@ -7,7 +7,7 @@ import ( // TODO: worth exporting and using in mkwinsyscall? -// Uint16BufferSize is the buffer size in the pool, chosen somewhat arbitrarily to accommodate +// MinWStringCap is the buffer size in the pool, chosen somewhat arbitrarily to accommodate // large path strings: // MAX_PATH (260) + size of volume GUID prefix (49) + null terminator = 310. const MinWStringCap = 310 @@ -16,7 +16,7 @@ const MinWStringCap = 310 // is copied to heap and then referenced via pointer in the interface header that sync.Pool // stores. var pathPool = sync.Pool{ // if go1.18+ adds Pool[T], use that to store []uint16 directly - New: func() interface{} { + New: func() any { b := make([]uint16, MinWStringCap) return &b }, diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go index a2da6639d0..16a42584fc 100644 --- a/vendor/github.com/Microsoft/go-winio/pipe.go +++ b/vendor/github.com/Microsoft/go-winio/pipe.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package winio @@ -11,6 +10,7 @@ import ( "net" "os" "runtime" + "sync" "time" "unsafe" @@ -179,14 +179,15 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) { return 0, io.EOF } n, err := f.win32File.Read(b) - if err == io.EOF { //nolint:errorlint + switch err { + case io.EOF: //nolint:errorlint // error is not wrapped. // If this was the result of a zero-byte read, then // it is possible that the read was due to a zero-size // message. Since we are simulating CloseWrite with a // zero-byte message, ensure that all future Read() calls // also return EOF. f.readEOF = true - } else if err == windows.ERROR_MORE_DATA { //nolint:errorlint // err is Errno + case windows.ERROR_MORE_DATA: // ERROR_MORE_DATA indicates that the pipe's read mode is message mode // and the message still has more bytes. Treat this as a success, since // this package presents all named pipes as byte streams. @@ -316,8 +317,9 @@ type win32PipeListener struct { path string config PipeConfig acceptCh chan (chan acceptResponse) - closeCh chan int - doneCh chan int + closeOnce sync.Once + closeCh chan struct{} // closed (never sent on) to broadcast listener shutdown + doneCh chan struct{} } func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (windows.Handle, error) { @@ -344,7 +346,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (wi // The security descriptor is only needed for the first pipe. if first { if sd != nil { - //todo: does `sdb` need to be allocated on the heap, or can go allocate it? + // todo: does `sdb` need to be allocated on the heap, or can go allocate it? l := uint32(len(sd)) sdb, err := windows.LocalAlloc(0, l) if err != nil { @@ -445,13 +447,14 @@ func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) { p = nil } case <-l.closeCh: - // Abort the connect request by closing the handle. - p.Close() + // Abort the connect request by closing the handle. Listener closure is + // authoritative: ConnectNamedPipe may race the handle close and report a + // connection or error (e.g. ERROR_NO_DATA) instead of ErrFileClosed, and + // that result must not be surfaced or cause listenerRoutine to retry. + _ = p.Close() p = nil - err = <-ch - if err == nil || err == ErrFileClosed { //nolint:errorlint // err is Errno - err = ErrPipeListenerClosed - } + <-ch + err = ErrPipeListenerClosed } return p, err } @@ -530,8 +533,8 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) { path: path, config: *c, acceptCh: make(chan (chan acceptResponse)), - closeCh: make(chan int), - doneCh: make(chan int), + closeCh: make(chan struct{}), + doneCh: make(chan struct{}), } go l.listenerRoutine() return l, nil @@ -573,11 +576,10 @@ func (l *win32PipeListener) Accept() (net.Conn, error) { } func (l *win32PipeListener) Close() error { - select { - case l.closeCh <- 1: - <-l.doneCh - case <-l.doneCh: - } + l.closeOnce.Do(func() { + close(l.closeCh) + }) + <-l.doneCh return nil } diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go index 48ce4e9243..fa1bde3a90 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go @@ -14,7 +14,7 @@ import ( "strconv" ) -//go:generate go run golang.org/x/tools/cmd/stringer -type=Variant -trimprefix=Variant -linecomment +//go:generate go tool stringer -type=Variant -trimprefix=Variant -linecomment // Variant specifies which GUID variant (or "type") of the GUID. It determines // how the entirety of the rest of the GUID is interpreted. diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go index 805bd35484..b933821a54 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package guid diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go index 27e45ee5cc..4aa95a7068 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package guid diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go index 4076d3132f..76e387d111 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go @@ -20,8 +20,9 @@ const _Variant_name = "UnknownNCSRFC 4122MicrosoftFuture" var _Variant_index = [...]uint8{0, 7, 10, 18, 27, 33} func (i Variant) String() string { - if i >= Variant(len(_Variant_index)-1) { + idx := int(i) - 0 + if i < 0 || idx >= len(_Variant_index)-1 { return "Variant(" + strconv.FormatInt(int64(i), 10) + ")" } - return _Variant_name[_Variant_index[i]:_Variant_index[i+1]] + return _Variant_name[_Variant_index[idx]:_Variant_index[idx+1]] } diff --git a/vendor/github.com/Microsoft/go-winio/privilege.go b/vendor/github.com/Microsoft/go-winio/privilege.go index d9b90b6e86..747eefd326 100644 --- a/vendor/github.com/Microsoft/go-winio/privilege.go +++ b/vendor/github.com/Microsoft/go-winio/privilege.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package winio diff --git a/vendor/github.com/Microsoft/go-winio/reparse.go b/vendor/github.com/Microsoft/go-winio/reparse.go index 67d1a104a6..9847fbd6c5 100644 --- a/vendor/github.com/Microsoft/go-winio/reparse.go +++ b/vendor/github.com/Microsoft/go-winio/reparse.go @@ -1,11 +1,11 @@ //go:build windows -// +build windows package winio import ( "bytes" "encoding/binary" + "errors" "fmt" "strings" "unicode/utf16" @@ -15,6 +15,9 @@ import ( const ( reparseTagMountPoint = 0xA0000003 reparseTagSymlink = 0xA000000C + reparseTagLxSymlink = 0xA000001D // WSL/MSYS2 native symlinks + + lxSymlinkVersion = 2 // LX symlink format version ) type reparseDataBuffer struct { @@ -31,6 +34,7 @@ type reparseDataBuffer struct { type ReparsePoint struct { Target string IsMountPoint bool + IsLxSymlink bool // True if this is an LX symlink (WSL/MSYS2 native) } // UnsupportedReparsePointError is returned when trying to decode a non-symlink or @@ -51,14 +55,19 @@ func DecodeReparsePoint(b []byte) (*ReparsePoint, error) { } func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) { - isMountPoint := false switch tag { case reparseTagMountPoint: - isMountPoint = true + return decodeWindowsReparsePointData(b, true) case reparseTagSymlink: + return decodeWindowsReparsePointData(b, false) + case reparseTagLxSymlink: + return decodeLxReparsePointData(b) default: return nil, &UnsupportedReparsePointError{tag} } +} + +func decodeWindowsReparsePointData(b []byte, isMountPoint bool) (*ReparsePoint, error) { nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6]) if !isMountPoint { nameOffset += 4 @@ -69,16 +78,56 @@ func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) { if err != nil { return nil, err } - return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil + return &ReparsePoint{Target: string(utf16.Decode(name)), IsMountPoint: isMountPoint, IsLxSymlink: false}, nil +} + +func decodeLxReparsePointData(b []byte) (*ReparsePoint, error) { + // LX symlinks store the target as UTF-8 after a 4-byte version field + if len(b) < 4 { + return nil, errors.New("LX symlink buffer too short") + } + targetBytes := b[4:] + for i, c := range targetBytes { + if c == 0 { + targetBytes = targetBytes[:i] + break + } + } + target := string(targetBytes) + return &ReparsePoint{Target: target, IsMountPoint: false, IsLxSymlink: true}, nil } func isDriveLetter(c byte) bool { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') } -// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or -// mount point. +// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink, +// mount point, or LX symlink. func EncodeReparsePoint(rp *ReparsePoint) []byte { + if rp == nil { + return nil + } + if rp.IsLxSymlink { + return encodeLxReparsePoint(rp) + } + return encodeWindowsReparsePoint(rp) +} + +func encodeLxReparsePoint(rp *ReparsePoint) []byte { + // LX symlink: 4-byte version + UTF-8 target + targetBytes := []byte(rp.Target) + dataLength := 4 + len(targetBytes) + + var b bytes.Buffer + _ = binary.Write(&b, binary.LittleEndian, uint32(reparseTagLxSymlink)) + _ = binary.Write(&b, binary.LittleEndian, uint16(dataLength)) + _ = binary.Write(&b, binary.LittleEndian, uint16(0)) + _ = binary.Write(&b, binary.LittleEndian, uint32(lxSymlinkVersion)) + _, _ = b.Write(targetBytes) + return b.Bytes() +} + +func encodeWindowsReparsePoint(rp *ReparsePoint) []byte { // Generate an NT path and determine if this is a relative path. var ntTarget string relative := false diff --git a/vendor/github.com/Microsoft/go-winio/sd.go b/vendor/github.com/Microsoft/go-winio/sd.go index c3685e98e1..7834c6adcb 100644 --- a/vendor/github.com/Microsoft/go-winio/sd.go +++ b/vendor/github.com/Microsoft/go-winio/sd.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package winio diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go index 89b66eda8c..f4329bbfd6 100644 --- a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go @@ -15,12 +15,8 @@ var _ unsafe.Pointer // Do the interface allocations only once for common // Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_IO_PENDING error = windows.ERROR_IO_PENDING errERROR_EINVAL error = syscall.EINVAL ) @@ -30,7 +26,7 @@ func errnoErr(e syscall.Errno) error { switch e { case 0: return errERROR_EINVAL - case errnoERROR_IO_PENDING: + case windows.ERROR_IO_PENDING: return errERROR_IO_PENDING } return e diff --git a/vendor/modules.txt b/vendor/modules.txt index 501237c5a1..e647a4b54b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -5,8 +5,8 @@ dario.cat/mergo ## explicit; go 1.16 github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm -# github.com/Microsoft/go-winio v0.6.2 -## explicit; go 1.21 +# github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0 +## explicit; go 1.26.0 github.com/Microsoft/go-winio github.com/Microsoft/go-winio/internal/fs github.com/Microsoft/go-winio/internal/socket From 637be3d60c561464a39297d1516b06652c1317ea Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 15 Sep 2026 18:15:41 +0200 Subject: [PATCH 07/26] vendor: github.com/klauspost/compress v1.20.0 - Add lzw reader/writer - ci: test against go1.27.x, drop go1.24.x - flate: Writer L7-9 with dictionary can emit the dictionary to stream - gzhttp: limit jitter hash to jitterBuffer bytes - s2: arm64 assembly encoders, lowered from the amd64 avo program - s2: clamp the Go EncodeBetter skip to match the assembly - xpress: add Microsoft XPRESS (MS-XCA) decompression - xxhash: bound input of non-preemptive assembly - zstd, huff0: improved arm64 lowering, and narrow two table loads to MOVWQZX - zstd/huff0: break false partial-register dependencies in seqdec/4X decoders - zstd/huff0: fold two ISA-gap x86 idioms in the avo arm64 lowering full diff: https://github.com/klauspost/compress/compare/v1.19.2...v1.20.0 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 4 +- .../github.com/klauspost/compress/README.md | 2 + .../compress/huff0/decompress_amd64.s | 206 ++--- .../compress/huff0/decompress_arm64.s | 249 +++--- .../compress/zstd/fse_decoder_arm64.s | 25 +- .../compress/zstd/internal/xxhash/xxhash.go | 12 + .../zstd/internal/xxhash/xxhash_amd64.s | 6 +- .../zstd/internal/xxhash/xxhash_arm64.s | 6 +- .../klauspost/compress/zstd/seqdec_amd64.s | 732 +++++++++--------- .../klauspost/compress/zstd/seqdec_arm64.s | 606 +++++++-------- vendor/modules.txt | 4 +- 12 files changed, 875 insertions(+), 979 deletions(-) diff --git a/vendor.mod b/vendor.mod index b1bfb7897a..e6f777058e 100644 --- a/vendor.mod +++ b/vendor.mod @@ -87,7 +87,7 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.19.2 // indirect + github.com/klauspost/compress v1.20.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/sys/user v0.4.1 // indirect github.com/moby/sys/userns v0.2.1 // indirect diff --git a/vendor.sum b/vendor.sum index 36d2533377..a02c98915b 100644 --- a/vendor.sum +++ b/vendor.sum @@ -78,8 +78,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi26R8= -github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= +github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mattn/go-runewidth v0.0.29 h1:3oGF3R/S2N9DQ3ptftzVIvg2eicmojCzlwBEmqEPDfQ= diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md index 0e9f170d01..bf31b905f8 100644 --- a/vendor/github.com/klauspost/compress/README.md +++ b/vendor/github.com/klauspost/compress/README.md @@ -6,7 +6,9 @@ This package provides various compression algorithms. * [S2](https://github.com/klauspost/compress/tree/master/s2#s2-compression) is a high performance replacement for Snappy. * Optimized [deflate](https://godoc.org/github.com/klauspost/compress/flate) packages which can be used as a dropin replacement for [gzip](https://godoc.org/github.com/klauspost/compress/gzip), [zip](https://godoc.org/github.com/klauspost/compress/zip) and [zlib](https://godoc.org/github.com/klauspost/compress/zlib). * [snappy](https://github.com/klauspost/compress/tree/master/snappy) is a drop-in replacement for `github.com/golang/snappy` offering better compression and concurrent streams. +* [lzw](https://github.com/klauspost/compress/tree/master/lzw) is a drop-in replacement for `compress/lzw` with 1.4-4x faster decompression and 1.1-2.7x faster compression, depending on the data. * [huff0](https://github.com/klauspost/compress/tree/master/huff0) and [FSE](https://github.com/klauspost/compress/tree/master/fse) implementations for raw entropy encoding. +* [Xpress](https://github.com/klauspost/compress/tree/master/xpress) decompression of the Microsoft XPRESS (MS-XCA) plain LZ77 and LZ77+Huffman formats (the LZ77+Huffman variant is the one used in WIM images and Windows Compact OS / WOF data). * [gzhttp](https://github.com/klauspost/compress/tree/master/gzhttp) Provides client and server wrappers for handling gzipped/zstd HTTP requests efficiently. * [pgzip](https://github.com/klauspost/pgzip) is a separate package that provides a very fast parallel gzip implementation. diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s index c5d4a710a0..920628c514 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s @@ -47,12 +47,12 @@ skip_fill0: SHRQ CL, R13 // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br0.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVBLZX CH, AX + SHLQ CL, R11 + ADDB CL, R12 // val1 := br0.peekTopBits(peekBits) MOVQ DI, CX @@ -60,7 +60,7 @@ skip_fill0: SHRQ CL, R13 // v1 := table[val1&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br0.advance(uint8(v1.entry)) MOVB CH, AH @@ -104,12 +104,12 @@ skip_fill1: SHRQ CL, R13 // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br1.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVBLZX CH, AX + SHLQ CL, R11 + ADDB CL, R12 // val1 := br1.peekTopBits(peekBits) MOVQ DI, CX @@ -117,7 +117,7 @@ skip_fill1: SHRQ CL, R13 // v1 := table[val1&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br1.advance(uint8(v1.entry)) MOVB CH, AH @@ -161,12 +161,12 @@ skip_fill2: SHRQ CL, R13 // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br2.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVBLZX CH, AX + SHLQ CL, R11 + ADDB CL, R12 // val1 := br2.peekTopBits(peekBits) MOVQ DI, CX @@ -174,7 +174,7 @@ skip_fill2: SHRQ CL, R13 // v1 := table[val1&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br2.advance(uint8(v1.entry)) MOVB CH, AH @@ -218,12 +218,12 @@ skip_fill3: SHRQ CL, R13 // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br3.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVBLZX CH, AX + SHLQ CL, R11 + ADDB CL, R12 // val1 := br3.peekTopBits(peekBits) MOVQ DI, CX @@ -231,7 +231,7 @@ skip_fill3: SHRQ CL, R13 // v1 := table[val1&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br3.advance(uint8(v1.entry)) MOVB CH, AH @@ -259,13 +259,13 @@ skip_fill3: // func decompress4x_8b_main_loop_amd64(ctx *decompress4xContext) TEXT ·decompress4x_8b_main_loop_amd64(SB), $0-8 // Preload values - MOVQ ctx+0(FP), CX - MOVBQZX 8(CX), DI - MOVQ 16(CX), BX - MOVQ 48(CX), SI - MOVQ 24(CX), R8 - MOVQ 32(CX), R9 - MOVQ (CX), R10 + MOVQ ctx+0(FP), AX + MOVBQZX 8(AX), DI + MOVQ 16(AX), BX + MOVQ 48(AX), SI + MOVQ 24(AX), R8 + MOVQ 32(AX), R9 + MOVQ (AX), R10 // Main loop main_loop: @@ -278,35 +278,35 @@ main_loop: MOVBQZX 40(R10), R12 CMPQ R12, $0x20 JBE skip_fill0 - MOVQ 24(R10), R13 + MOVQ 24(R10), AX SUBQ $0x20, R12 - SUBQ $0x04, R13 - MOVQ (R10), R14 + SUBQ $0x04, AX + MOVQ (R10), R13 // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (R13)(R14*1), R14 + MOVL (AX)(R13*1), R13 MOVQ R12, CX - SHLQ CL, R14 - MOVQ R13, 24(R10) - ORQ R14, R11 + SHLQ CL, R13 + MOVQ AX, 24(R10) + ORQ R13, R11 // exhausted += (br0.off < 4) - CMPQ R13, $0x04 + CMPQ AX, $0x04 ADCB $+0, DL skip_fill0: // val0 := br0.peekTopBits(peekBits) - MOVQ R11, R13 + MOVQ R11, AX MOVQ DI, CX - SHRQ CL, R13 + SHRQ CL, AX // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(AX*2), CX // br0.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVBLZX CH, AX + SHLQ CL, R11 + ADDB CL, R12 // val1 := br0.peekTopBits(peekBits) MOVQ R11, R13 @@ -314,7 +314,7 @@ skip_fill0: SHRQ CL, R13 // v1 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br0.advance(uint8(v1.entry) MOVB CH, AH @@ -328,7 +328,7 @@ skip_fill0: SHRQ CL, R13 // v2 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br0.advance(uint8(v2.entry) MOVB CH, AH @@ -341,7 +341,7 @@ skip_fill0: SHRQ CL, R13 // v3 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br0.advance(uint8(v3.entry) MOVB CH, AL @@ -365,35 +365,35 @@ skip_fill0: MOVBQZX 88(R10), R12 CMPQ R12, $0x20 JBE skip_fill1 - MOVQ 72(R10), R13 + MOVQ 72(R10), AX SUBQ $0x20, R12 - SUBQ $0x04, R13 - MOVQ 48(R10), R14 + SUBQ $0x04, AX + MOVQ 48(R10), R13 // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (R13)(R14*1), R14 + MOVL (AX)(R13*1), R13 MOVQ R12, CX - SHLQ CL, R14 - MOVQ R13, 72(R10) - ORQ R14, R11 + SHLQ CL, R13 + MOVQ AX, 72(R10) + ORQ R13, R11 // exhausted += (br1.off < 4) - CMPQ R13, $0x04 + CMPQ AX, $0x04 ADCB $+0, DL skip_fill1: // val0 := br1.peekTopBits(peekBits) - MOVQ R11, R13 + MOVQ R11, AX MOVQ DI, CX - SHRQ CL, R13 + SHRQ CL, AX // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(AX*2), CX // br1.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVBLZX CH, AX + SHLQ CL, R11 + ADDB CL, R12 // val1 := br1.peekTopBits(peekBits) MOVQ R11, R13 @@ -401,7 +401,7 @@ skip_fill1: SHRQ CL, R13 // v1 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br1.advance(uint8(v1.entry) MOVB CH, AH @@ -415,7 +415,7 @@ skip_fill1: SHRQ CL, R13 // v2 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br1.advance(uint8(v2.entry) MOVB CH, AH @@ -428,7 +428,7 @@ skip_fill1: SHRQ CL, R13 // v3 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br1.advance(uint8(v3.entry) MOVB CH, AL @@ -452,35 +452,35 @@ skip_fill1: MOVBQZX 136(R10), R12 CMPQ R12, $0x20 JBE skip_fill2 - MOVQ 120(R10), R13 + MOVQ 120(R10), AX SUBQ $0x20, R12 - SUBQ $0x04, R13 - MOVQ 96(R10), R14 + SUBQ $0x04, AX + MOVQ 96(R10), R13 // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (R13)(R14*1), R14 + MOVL (AX)(R13*1), R13 MOVQ R12, CX - SHLQ CL, R14 - MOVQ R13, 120(R10) - ORQ R14, R11 + SHLQ CL, R13 + MOVQ AX, 120(R10) + ORQ R13, R11 // exhausted += (br2.off < 4) - CMPQ R13, $0x04 + CMPQ AX, $0x04 ADCB $+0, DL skip_fill2: // val0 := br2.peekTopBits(peekBits) - MOVQ R11, R13 + MOVQ R11, AX MOVQ DI, CX - SHRQ CL, R13 + SHRQ CL, AX // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(AX*2), CX // br2.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVBLZX CH, AX + SHLQ CL, R11 + ADDB CL, R12 // val1 := br2.peekTopBits(peekBits) MOVQ R11, R13 @@ -488,7 +488,7 @@ skip_fill2: SHRQ CL, R13 // v1 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br2.advance(uint8(v1.entry) MOVB CH, AH @@ -502,7 +502,7 @@ skip_fill2: SHRQ CL, R13 // v2 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br2.advance(uint8(v2.entry) MOVB CH, AH @@ -515,7 +515,7 @@ skip_fill2: SHRQ CL, R13 // v3 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br2.advance(uint8(v3.entry) MOVB CH, AL @@ -539,35 +539,35 @@ skip_fill2: MOVBQZX 184(R10), R12 CMPQ R12, $0x20 JBE skip_fill3 - MOVQ 168(R10), R13 + MOVQ 168(R10), AX SUBQ $0x20, R12 - SUBQ $0x04, R13 - MOVQ 144(R10), R14 + SUBQ $0x04, AX + MOVQ 144(R10), R13 // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (R13)(R14*1), R14 + MOVL (AX)(R13*1), R13 MOVQ R12, CX - SHLQ CL, R14 - MOVQ R13, 168(R10) - ORQ R14, R11 + SHLQ CL, R13 + MOVQ AX, 168(R10) + ORQ R13, R11 // exhausted += (br3.off < 4) - CMPQ R13, $0x04 + CMPQ AX, $0x04 ADCB $+0, DL skip_fill3: // val0 := br3.peekTopBits(peekBits) - MOVQ R11, R13 + MOVQ R11, AX MOVQ DI, CX - SHRQ CL, R13 + SHRQ CL, AX // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(AX*2), CX // br3.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVBLZX CH, AX + SHLQ CL, R11 + ADDB CL, R12 // val1 := br3.peekTopBits(peekBits) MOVQ R11, R13 @@ -575,7 +575,7 @@ skip_fill3: SHRQ CL, R13 // v1 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br3.advance(uint8(v1.entry) MOVB CH, AH @@ -589,7 +589,7 @@ skip_fill3: SHRQ CL, R13 // v2 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br3.advance(uint8(v2.entry) MOVB CH, AH @@ -602,7 +602,7 @@ skip_fill3: SHRQ CL, R13 // v3 := table[val0&mask] - MOVW (R9)(R13*2), CX + MOVWQZX (R9)(R13*2), CX // br3.advance(uint8(v3.entry) MOVB CH, AL @@ -667,7 +667,7 @@ bitReader_fillFast_1_end: MOVQ DI, CX MOVQ R10, R12 SHRQ CL, R12 - MOVW (SI)(R12*2), CX + MOVWQZX (SI)(R12*2), CX MOVB CH, AL MOVBQZX CL, CX ADDQ CX, R11 @@ -675,7 +675,7 @@ bitReader_fillFast_1_end: MOVQ DI, CX MOVQ R10, R12 SHRQ CL, R12 - MOVW (SI)(R12*2), CX + MOVWQZX (SI)(R12*2), CX MOVB CH, AH MOVBQZX CL, CX ADDQ CX, R11 @@ -694,7 +694,7 @@ bitReader_fillFast_2_end: MOVQ DI, CX MOVQ R10, R12 SHRQ CL, R12 - MOVW (SI)(R12*2), CX + MOVWQZX (SI)(R12*2), CX MOVB CH, AH MOVBQZX CL, CX ADDQ CX, R11 @@ -702,7 +702,7 @@ bitReader_fillFast_2_end: MOVQ DI, CX MOVQ R10, R12 SHRQ CL, R12 - MOVW (SI)(R12*2), CX + MOVWQZX (SI)(R12*2), CX MOVB CH, AL MOVBQZX CL, CX ADDQ CX, R11 @@ -769,13 +769,13 @@ main_loop: bitReader_fillFast_1_end: SHRXQ DI, R10, CX - MOVW (SI)(CX*2), CX + MOVWQZX (SI)(CX*2), CX MOVB CH, AL MOVBQZX CL, CX ADDQ CX, R11 SHLXQ CX, R10, R10 SHRXQ DI, R10, CX - MOVW (SI)(CX*2), CX + MOVWQZX (SI)(CX*2), CX MOVB CH, AH MOVBQZX CL, CX ADDQ CX, R11 @@ -791,13 +791,13 @@ bitReader_fillFast_1_end: bitReader_fillFast_2_end: SHRXQ DI, R10, CX - MOVW (SI)(CX*2), CX + MOVWQZX (SI)(CX*2), CX MOVB CH, AH MOVBQZX CL, CX ADDQ CX, R11 SHLXQ CX, R10, R10 SHRXQ DI, R10, CX - MOVW (SI)(CX*2), CX + MOVWQZX (SI)(CX*2), CX MOVB CH, AL MOVBQZX CL, CX ADDQ CX, R11 diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s b/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s index e16012721a..357df28e9d 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s +++ b/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s @@ -1,7 +1,7 @@ // Code generated by command: go run gen.go -out ../decompress.s -arch amd64,arm64 -pkg=huff0. DO NOT EDIT. // EXPERIMENTAL arm64 output lowered from an amd64 avo program. -//go:build arm64 && !appengine && !noasm && gc +//go:build arm64 && (!appengine && !noasm && gc) // func decompress4x_main_loop_amd64(ctx *decompress4xContext) TEXT ·decompress4x_main_loop_arm64(SB), $0-8 @@ -32,8 +32,7 @@ main_loop: MOVD (R9), R12 // b.value |= uint64(low) << (b.bitsRead & 63) - ADD R12, R0, R15 - MOVWU (R15), R12 + MOVWU (R0)(R12), R12 MOVD R11, R1 LSL R1, R12, R12 MOVD R0, 24(R9) @@ -51,12 +50,10 @@ skip_fill0: LSR R1, R12, R12 // v0 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br0.advance(uint8(v0.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 + UBFX $8, R1, $8, R0 LSL R1, R10, R10 ADD R1, R11, R15 BFI $0, R15, $8, R11 @@ -67,8 +64,7 @@ skip_fill0: LSR R1, R12, R12 // v1 := table[val1&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br0.advance(uint8(v1.entry)) UBFX $8, R1, $8, R16 @@ -97,8 +93,7 @@ skip_fill0: MOVD 48(R9), R12 // b.value |= uint64(low) << (b.bitsRead & 63) - ADD R12, R0, R15 - MOVWU (R15), R12 + MOVWU (R0)(R12), R12 MOVD R11, R1 LSL R1, R12, R12 MOVD R0, 72(R9) @@ -116,12 +111,10 @@ skip_fill1: LSR R1, R12, R12 // v0 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br1.advance(uint8(v0.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 + UBFX $8, R1, $8, R0 LSL R1, R10, R10 ADD R1, R11, R15 BFI $0, R15, $8, R11 @@ -132,8 +125,7 @@ skip_fill1: LSR R1, R12, R12 // v1 := table[val1&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br1.advance(uint8(v1.entry)) UBFX $8, R1, $8, R16 @@ -145,8 +137,7 @@ skip_fill1: // these two writes get coalesced // out[id * dstEvery + 0] = uint8(v0.entry >> 8) // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - ADD R7, R3, R15 - MOVH R0, (R15) + MOVH R0, (R3)(R7) // update the bitreader structure MOVD R10, 80(R9) @@ -163,8 +154,7 @@ skip_fill1: MOVD 96(R9), R12 // b.value |= uint64(low) << (b.bitsRead & 63) - ADD R12, R0, R15 - MOVWU (R15), R12 + MOVWU (R0)(R12), R12 MOVD R11, R1 LSL R1, R12, R12 MOVD R0, 120(R9) @@ -182,12 +172,10 @@ skip_fill2: LSR R1, R12, R12 // v0 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br2.advance(uint8(v0.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 + UBFX $8, R1, $8, R0 LSL R1, R10, R10 ADD R1, R11, R15 BFI $0, R15, $8, R11 @@ -198,8 +186,7 @@ skip_fill2: LSR R1, R12, R12 // v1 := table[val1&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br2.advance(uint8(v1.entry)) UBFX $8, R1, $8, R16 @@ -211,8 +198,7 @@ skip_fill2: // these two writes get coalesced // out[id * dstEvery + 0] = uint8(v0.entry >> 8) // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - ADD R7<<1, R3, R15 - MOVH R0, (R15) + MOVH R0, (R3)(R7<<1) // update the bitreader structure MOVD R10, 128(R9) @@ -229,8 +215,7 @@ skip_fill2: MOVD 144(R9), R12 // b.value |= uint64(low) << (b.bitsRead & 63) - ADD R12, R0, R15 - MOVWU (R15), R12 + MOVWU (R0)(R12), R12 MOVD R11, R1 LSL R1, R12, R12 MOVD R0, 168(R9) @@ -248,12 +233,10 @@ skip_fill3: LSR R1, R12, R12 // v0 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br3.advance(uint8(v0.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 + UBFX $8, R1, $8, R0 LSL R1, R10, R10 ADD R1, R11, R15 BFI $0, R15, $8, R11 @@ -264,8 +247,7 @@ skip_fill3: LSR R1, R12, R12 // v1 := table[val1&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br3.advance(uint8(v1.entry)) UBFX $8, R1, $8, R16 @@ -278,16 +260,13 @@ skip_fill3: // out[id * dstEvery + 0] = uint8(v0.entry >> 8) // out[id * dstEvery + 1] = uint8(v1.entry >> 8) ADD R7<<1, R7, R1 - ADD R1, R3, R15 - MOVH R0, (R15) + MOVH R0, (R3)(R1) // update the bitreader structure MOVD R10, 176(R9) MOVB R11, 184(R9) ADD $0x02, R3, R3 - AND $0xff, R2, R15 - AND $0xff, R2, R16 - TST R16, R15 + TST $0xff, R2 BEQ main_loop MOVD ctx+0(FP), R0 MOVD 16(R0), R16 @@ -299,13 +278,13 @@ skip_fill3: // func decompress4x_8b_main_loop_amd64(ctx *decompress4xContext) TEXT ·decompress4x_8b_main_loop_arm64(SB), $0-8 // Preload values - MOVD ctx+0(FP), R1 - MOVBU 8(R1), R6 - MOVD 16(R1), R3 - MOVD 48(R1), R5 - MOVD 24(R1), R7 - MOVD 32(R1), R8 - MOVD (R1), R9 + MOVD ctx+0(FP), R0 + MOVBU 8(R0), R6 + MOVD 16(R0), R3 + MOVD 48(R0), R5 + MOVD 24(R0), R7 + MOVD 32(R0), R8 + MOVD (R0), R9 // Main loop main_loop: @@ -319,37 +298,34 @@ main_loop: MOVBU 40(R9), R11 CMP $0x20, R11 BLS skip_fill0 - MOVD 24(R9), R12 + MOVD 24(R9), R0 SUB $0x20, R11, R11 - SUB $0x04, R12, R12 - MOVD (R9), R13 + SUB $0x04, R0, R0 + MOVD (R9), R12 // b.value |= uint64(low) << (b.bitsRead & 63) - ADD R13, R12, R15 - MOVWU (R15), R13 + MOVWU (R0)(R12), R12 MOVD R11, R1 - LSL R1, R13, R13 - MOVD R12, 24(R9) - ORR R13, R10, R10 + LSL R1, R12, R12 + MOVD R0, 24(R9) + ORR R12, R10, R10 // exhausted += (br0.off < 4) - CMP $0x04, R12 + CMP $0x04, R0 CSINC HS, R2, R2, R16 BFI $0, R16, $8, R2 skip_fill0: // val0 := br0.peekTopBits(peekBits) - MOVD R10, R12 + MOVD R10, R0 MOVD R6, R1 - LSR R1, R12, R12 + LSR R1, R0, R0 // v0 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R0<<1), R1 // br0.advance(uint8(v0.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 + UBFX $8, R1, $8, R0 LSL R1, R10, R10 ADD R1, R11, R15 BFI $0, R15, $8, R11 @@ -360,8 +336,7 @@ skip_fill0: LSR R1, R12, R12 // v1 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br0.advance(uint8(v1.entry) UBFX $8, R1, $8, R16 @@ -377,8 +352,7 @@ skip_fill0: LSR R1, R12, R12 // v2 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br0.advance(uint8(v2.entry) UBFX $8, R1, $8, R16 @@ -393,8 +367,7 @@ skip_fill0: LSR R1, R12, R12 // v3 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br0.advance(uint8(v3.entry) UBFX $8, R1, $8, R16 @@ -420,37 +393,34 @@ skip_fill0: MOVBU 88(R9), R11 CMP $0x20, R11 BLS skip_fill1 - MOVD 72(R9), R12 + MOVD 72(R9), R0 SUB $0x20, R11, R11 - SUB $0x04, R12, R12 - MOVD 48(R9), R13 + SUB $0x04, R0, R0 + MOVD 48(R9), R12 // b.value |= uint64(low) << (b.bitsRead & 63) - ADD R13, R12, R15 - MOVWU (R15), R13 + MOVWU (R0)(R12), R12 MOVD R11, R1 - LSL R1, R13, R13 - MOVD R12, 72(R9) - ORR R13, R10, R10 + LSL R1, R12, R12 + MOVD R0, 72(R9) + ORR R12, R10, R10 // exhausted += (br1.off < 4) - CMP $0x04, R12 + CMP $0x04, R0 CSINC HS, R2, R2, R16 BFI $0, R16, $8, R2 skip_fill1: // val0 := br1.peekTopBits(peekBits) - MOVD R10, R12 + MOVD R10, R0 MOVD R6, R1 - LSR R1, R12, R12 + LSR R1, R0, R0 // v0 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R0<<1), R1 // br1.advance(uint8(v0.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 + UBFX $8, R1, $8, R0 LSL R1, R10, R10 ADD R1, R11, R15 BFI $0, R15, $8, R11 @@ -461,8 +431,7 @@ skip_fill1: LSR R1, R12, R12 // v1 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br1.advance(uint8(v1.entry) UBFX $8, R1, $8, R16 @@ -478,8 +447,7 @@ skip_fill1: LSR R1, R12, R12 // v2 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br1.advance(uint8(v2.entry) UBFX $8, R1, $8, R16 @@ -494,8 +462,7 @@ skip_fill1: LSR R1, R12, R12 // v3 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br1.advance(uint8(v3.entry) UBFX $8, R1, $8, R16 @@ -510,8 +477,7 @@ skip_fill1: // out[id * dstEvery + 1] = uint8(v1.entry >> 8) // out[id * dstEvery + 3] = uint8(v2.entry >> 8) // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - ADD R7, R3, R15 - MOVW R0, (R15) + MOVW R0, (R3)(R7) // update the bitreader structure MOVD R10, 80(R9) @@ -522,37 +488,34 @@ skip_fill1: MOVBU 136(R9), R11 CMP $0x20, R11 BLS skip_fill2 - MOVD 120(R9), R12 + MOVD 120(R9), R0 SUB $0x20, R11, R11 - SUB $0x04, R12, R12 - MOVD 96(R9), R13 + SUB $0x04, R0, R0 + MOVD 96(R9), R12 // b.value |= uint64(low) << (b.bitsRead & 63) - ADD R13, R12, R15 - MOVWU (R15), R13 + MOVWU (R0)(R12), R12 MOVD R11, R1 - LSL R1, R13, R13 - MOVD R12, 120(R9) - ORR R13, R10, R10 + LSL R1, R12, R12 + MOVD R0, 120(R9) + ORR R12, R10, R10 // exhausted += (br2.off < 4) - CMP $0x04, R12 + CMP $0x04, R0 CSINC HS, R2, R2, R16 BFI $0, R16, $8, R2 skip_fill2: // val0 := br2.peekTopBits(peekBits) - MOVD R10, R12 + MOVD R10, R0 MOVD R6, R1 - LSR R1, R12, R12 + LSR R1, R0, R0 // v0 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R0<<1), R1 // br2.advance(uint8(v0.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 + UBFX $8, R1, $8, R0 LSL R1, R10, R10 ADD R1, R11, R15 BFI $0, R15, $8, R11 @@ -563,8 +526,7 @@ skip_fill2: LSR R1, R12, R12 // v1 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br2.advance(uint8(v1.entry) UBFX $8, R1, $8, R16 @@ -580,8 +542,7 @@ skip_fill2: LSR R1, R12, R12 // v2 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br2.advance(uint8(v2.entry) UBFX $8, R1, $8, R16 @@ -596,8 +557,7 @@ skip_fill2: LSR R1, R12, R12 // v3 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br2.advance(uint8(v3.entry) UBFX $8, R1, $8, R16 @@ -624,37 +584,34 @@ skip_fill2: MOVBU 184(R9), R11 CMP $0x20, R11 BLS skip_fill3 - MOVD 168(R9), R12 + MOVD 168(R9), R0 SUB $0x20, R11, R11 - SUB $0x04, R12, R12 - MOVD 144(R9), R13 + SUB $0x04, R0, R0 + MOVD 144(R9), R12 // b.value |= uint64(low) << (b.bitsRead & 63) - ADD R13, R12, R15 - MOVWU (R15), R13 + MOVWU (R0)(R12), R12 MOVD R11, R1 - LSL R1, R13, R13 - MOVD R12, 168(R9) - ORR R13, R10, R10 + LSL R1, R12, R12 + MOVD R0, 168(R9) + ORR R12, R10, R10 // exhausted += (br3.off < 4) - CMP $0x04, R12 + CMP $0x04, R0 CSINC HS, R2, R2, R16 BFI $0, R16, $8, R2 skip_fill3: // val0 := br3.peekTopBits(peekBits) - MOVD R10, R12 + MOVD R10, R0 MOVD R6, R1 - LSR R1, R12, R12 + LSR R1, R0, R0 // v0 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R0<<1), R1 // br3.advance(uint8(v0.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 + UBFX $8, R1, $8, R0 LSL R1, R10, R10 ADD R1, R11, R15 BFI $0, R15, $8, R11 @@ -665,8 +622,7 @@ skip_fill3: LSR R1, R12, R12 // v1 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br3.advance(uint8(v1.entry) UBFX $8, R1, $8, R16 @@ -682,8 +638,7 @@ skip_fill3: LSR R1, R12, R12 // v2 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br3.advance(uint8(v2.entry) UBFX $8, R1, $8, R16 @@ -698,8 +653,7 @@ skip_fill3: LSR R1, R12, R12 // v3 := table[val0&mask] - ADD R12<<1, R8, R15 - MOVHU (R15), R1 + MOVHU (R8)(R12<<1), R1 // br3.advance(uint8(v3.entry) UBFX $8, R1, $8, R16 @@ -715,16 +669,13 @@ skip_fill3: // out[id * dstEvery + 3] = uint8(v2.entry >> 8) // out[id * dstEvery + 4] = uint8(v3.entry >> 8) ADD R7<<1, R7, R1 - ADD R1, R3, R15 - MOVW R0, (R15) + MOVW R0, (R3)(R1) // update the bitreader structure MOVD R10, 176(R9) MOVB R11, 184(R9) ADD $0x04, R3, R3 - AND $0xff, R2, R15 - AND $0xff, R2, R16 - TST R16, R15 + TST $0xff, R2 BEQ main_loop MOVD ctx+0(FP), R0 MOVD 16(R0), R16 @@ -761,8 +712,7 @@ main_loop: BLT bitReader_fillFast_1_end SUB $0x20, R10, R10 SUB $0x04, R8, R8 - ADD R8, R7, R15 - MOVWU (R15), R11 + MOVWU (R7)(R8), R11 MOVD R10, R1 LSL R1, R11, R11 ORR R11, R9, R9 @@ -771,8 +721,7 @@ bitReader_fillFast_1_end: MOVD R6, R1 MOVD R9, R11 LSR R1, R11, R11 - ADD R11<<1, R5, R15 - MOVHU (R15), R1 + MOVHU (R5)(R11<<1), R1 UBFX $8, R1, $8, R16 BFI $0, R16, $8, R0 MOVBU R1, R1 @@ -781,8 +730,7 @@ bitReader_fillFast_1_end: MOVD R6, R1 MOVD R9, R11 LSR R1, R11, R11 - ADD R11<<1, R5, R15 - MOVHU (R15), R1 + MOVHU (R5)(R11<<1), R1 UBFX $8, R1, $8, R16 BFI $8, R16, $8, R0 MOVBU R1, R1 @@ -793,8 +741,7 @@ bitReader_fillFast_1_end: BLT bitReader_fillFast_2_end SUB $0x20, R10, R10 SUB $0x04, R8, R8 - ADD R8, R7, R15 - MOVWU (R15), R11 + MOVWU (R7)(R8), R11 MOVD R10, R1 LSL R1, R11, R11 ORR R11, R9, R9 @@ -803,8 +750,7 @@ bitReader_fillFast_2_end: MOVD R6, R1 MOVD R9, R11 LSR R1, R11, R11 - ADD R11<<1, R5, R15 - MOVHU (R15), R1 + MOVHU (R5)(R11<<1), R1 UBFX $8, R1, $8, R16 BFI $8, R16, $8, R0 MOVBU R1, R1 @@ -813,8 +759,7 @@ bitReader_fillFast_2_end: MOVD R6, R1 MOVD R9, R11 LSR R1, R11, R11 - ADD R11<<1, R5, R15 - MOVHU (R15), R1 + MOVHU (R5)(R11<<1), R1 UBFX $8, R1, $8, R16 BFI $0, R16, $8, R0 MOVBU R1, R1 diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s b/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s index 77ee3913f0..b6b4607878 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s @@ -1,7 +1,7 @@ // Code generated by command: go run gen_fse.go -out ../fse_decoder.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT. // EXPERIMENTAL arm64 output lowered from an amd64 avo program. -//go:build arm64 && !appengine && !noasm && gc && !noasm +//go:build arm64 && (!appengine && !noasm && gc && !noasm) // func buildDtable_asm(s *fseDecoder, ctx *buildDtableAsmContext) int TEXT ·buildDtable_asm(SB), $0-24 @@ -26,11 +26,10 @@ TEXT ·buildDtable_asm(SB), $0-24 JMP init_main_loop_condition init_main_loop: - ADD R8<<1, R1, R15 - MOVH (R15), R9 - AND $0xffff, R9, R15 + MOVH (R1)(R8<<1), R9 MOVD $-1, R16 AND $0xffff, R16, R16 + AND $0xffff, R9, R15 CMP R16, R15 BNE do_not_update_high_threshold ADD R7<<3, R5, R15 @@ -39,8 +38,7 @@ init_main_loop: MOVD $0x0000000000000001, R9 do_not_update_high_threshold: - ADD R8<<1, R3, R15 - MOVH R9, (R15) + MOVH R9, (R3)(R8<<1) ADD $1, R8, R8 init_main_loop_condition: @@ -64,8 +62,7 @@ init_main_loop_condition: spread_main_loop: MOVD $0, R12 - ADD R11<<1, R1, R15 - MOVH (R15), R13 + MOVH (R1)(R11<<1), R13 JMP spread_inner_loop_condition spread_inner_loop: @@ -102,11 +99,9 @@ spread_check_ok: build_table_main_table: ADD R6<<3, R5, R15 MOVBU 1(R15), R1 - ADD R1<<1, R3, R15 - MOVHU (R15), R7 + MOVHU (R3)(R1<<1), R7 ADD $1, R7, R8 - ADD R1<<1, R3, R15 - MOVH R8, (R15) + MOVH R8, (R3)(R1<<1) MOVD R7, R8 CLZ R8, R16 MOVD $63, R8 @@ -129,12 +124,10 @@ build_table_main_table: RET build_table_check1_ok: - AND $0xff, R1, R15 - AND $0xff, R1, R16 - TST R16, R15 + TST $0xff, R1 BNE build_table_check2_ok - AND $0xffff, R7, R15 AND $0xffff, R6, R16 + AND $0xffff, R7, R15 CMP R16, R15 BNE build_table_check2_ok MOVD ctx+8(FP), R0 diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go index fc40c82001..9c0cbc1681 100644 --- a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go @@ -52,6 +52,11 @@ func (d *Digest) Reset() { d.n = 0 } +// maxAsmSize bounds the input handed to a single writeBlocks call. Assembly is +// never preemptible, so an unbounded call holds every P in stop-the-world for +// its duration. Whole 32-byte blocks, so Write can feed it in pieces. +const maxAsmSize = 128 << 10 // 4096 whole 32-byte blocks + // Size always returns 8 bytes. func (d *Digest) Size() int { return 8 } @@ -83,6 +88,13 @@ func (d *Digest) Write(b []byte) (n int, err error) { d.n = 0 } + for len(b) >= maxAsmSize { + // Assembly is not preemptible, so hashing a large buffer in one call + // blocks every stop-the-world for the whole call. Feed it in chunks. + writeBlocks(d, b[:maxAsmSize]) + b = b[maxAsmSize:] + } + if len(b) >= 32 { // One or more full blocks left. nw := writeBlocks(d, b) diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s index ddb63aa91b..e4c688efd3 100644 --- a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s @@ -175,7 +175,11 @@ finalize: RET // func writeBlocks(d *Digest, b []byte) int -TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 +// +// Deliberately not NOSPLIT: the stack check is the preemption point that lets a +// stop-the-world proceed between chunks. The frame must be >= abi.StackSmall +// (128), or the assembler marks this leaf NOSPLIT anyway and drops that check. +TEXT ·writeBlocks(SB), $128-40 // Load fixed primes needed for round. MOVQ ·primes+0(SB), prime1 MOVQ ·primes+8(SB), prime2 diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s index ae7d4d3295..e88cc2fc91 100644 --- a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s @@ -163,7 +163,11 @@ finalize: RET // func writeBlocks(s *Digest, b []byte) int -TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 +// +// Deliberately not NOSPLIT: the stack check is the preemption point that lets a +// stop-the-world proceed between chunks. The frame must be >= abi.StackSmall +// (128), or the assembler marks this leaf NOSPLIT anyway and drops that check. +TEXT ·writeBlocks(SB), $128-40 LDP ·primes+0(SB), (prime1, prime2) // Load state. Assume v[1-4] are stored contiguously. diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s index 4d3188ff49..9c4f8d3528 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s @@ -55,43 +55,43 @@ sequenceDecs_decode_amd64_fill_check_overread: sequenceDecs_decode_amd64_fill_end: // Update offset - MOVQ R9, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_of_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_of_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_amd64_of_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_amd64_of_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_amd64_of_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX sequenceDecs_decode_amd64_of_update_zero: MOVQ AX, 16(R10) // Update match length - MOVQ R8, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_ml_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_ml_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_amd64_ml_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_amd64_ml_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_amd64_ml_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX sequenceDecs_decode_amd64_ml_update_zero: MOVQ AX, 8(R10) @@ -126,22 +126,22 @@ sequenceDecs_decode_amd64_fill_2_check_overread: sequenceDecs_decode_amd64_fill_2_end: // Update literal length - MOVQ DI, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_ll_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_ll_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_amd64_ll_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_amd64_ll_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_amd64_ll_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX sequenceDecs_decode_amd64_ll_update_zero: MOVQ AX, (R10) @@ -163,7 +163,7 @@ sequenceDecs_decode_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R15 MOVL $0x00000001, BP - MOVB R14, CL + MOVBLZX R14, CX SHLL CL, BP DECL BP ANDQ BP, R15 @@ -182,7 +182,7 @@ sequenceDecs_decode_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R15 MOVL $0x00000001, BP - MOVB R14, CL + MOVBLZX R14, CX SHLL CL, BP DECL BP ANDQ BP, R15 @@ -201,7 +201,7 @@ sequenceDecs_decode_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R15 MOVL $0x00000001, BP - MOVB R14, CL + MOVBLZX R14, CX SHLL CL, BP DECL BP ANDQ BP, R15 @@ -383,64 +383,64 @@ sequenceDecs_decode_56_amd64_fill_check_overread: sequenceDecs_decode_56_amd64_fill_end: // Update offset - MOVQ R9, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_of_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_of_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_56_amd64_of_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_56_amd64_of_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_56_amd64_of_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX sequenceDecs_decode_56_amd64_of_update_zero: MOVQ AX, 16(R10) // Update match length - MOVQ R8, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_ml_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_ml_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_56_amd64_ml_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_56_amd64_ml_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_56_amd64_ml_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX sequenceDecs_decode_56_amd64_ml_update_zero: MOVQ AX, 8(R10) // Update literal length - MOVQ DI, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_ll_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_ll_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_56_amd64_ll_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_56_amd64_ll_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_56_amd64_ll_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX sequenceDecs_decode_56_amd64_ll_update_zero: MOVQ AX, (R10) @@ -462,7 +462,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R15 MOVL $0x00000001, BP - MOVB R14, CL + MOVBLZX R14, CX SHLL CL, BP DECL BP ANDQ BP, R15 @@ -481,7 +481,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R15 MOVL $0x00000001, BP - MOVB R14, CL + MOVBLZX R14, CX SHLL CL, BP DECL BP ANDQ BP, R15 @@ -500,7 +500,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R15 MOVL $0x00000001, BP - MOVB R14, CL + MOVBLZX R14, CX SHLL CL, BP DECL BP ANDQ BP, R15 @@ -1258,13 +1258,13 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), R11 - MOVB 2(R14), R12 - MOVW R11, (BX) - MOVB R12, 2(BX) - ADDQ R13, R14 - ADDQ R13, BX - JMP copy_4_end + MOVWQZX (R14), R11 + MOVB 2(R14), R12 + MOVW R11, (BX) + MOVB R12, 2(BX) + ADDQ R13, R14 + ADDQ R13, BX + JMP copy_4_end copy_4_move_4through7: MOVL (R14), R11 @@ -1327,13 +1327,13 @@ copy_5_move_1or2: JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (BX) - MOVB BP, 2(BX) - ADDQ R11, R14 - ADDQ R11, BX - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (BX) + MOVB BP, 2(BX) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 @@ -1384,12 +1384,12 @@ copy_overlapping_match: ADDQ R13, DI copy_slow_3: - MOVB (R11), R12 - MOVB R12, (BX) - INCQ R11 - INCQ BX - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (R11), R12 + MOVB R12, (BX) + INCQ R11 + INCQ BX + DECQ R13 + JNZ copy_slow_3 handle_loop: ADDQ $0x18, AX @@ -1494,13 +1494,13 @@ copy_1_move_1or2: JMP copy_1_end copy_1_move_3: - MOVW (SI), R14 - MOVB 2(SI), R15 - MOVW R14, (BX) - MOVB R15, 2(BX) - ADDQ R11, SI - ADDQ R11, BX - JMP copy_1_end + MOVWQZX (SI), R14 + MOVB 2(SI), R15 + MOVW R14, (BX) + MOVB R15, 2(BX) + ADDQ R11, SI + ADDQ R11, BX + JMP copy_1_end copy_1_move_4through7: MOVL (SI), R14 @@ -1563,13 +1563,13 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), R11 - MOVB 2(R14), R12 - MOVW R11, (BX) - MOVB R12, 2(BX) - ADDQ R13, R14 - ADDQ R13, BX - JMP copy_4_end + MOVWQZX (R14), R11 + MOVB 2(R14), R12 + MOVW R11, (BX) + MOVB R12, 2(BX) + ADDQ R13, R14 + ADDQ R13, BX + JMP copy_4_end copy_4_move_4through7: MOVL (R14), R11 @@ -1632,13 +1632,13 @@ copy_5_move_1or2: JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (BX) - MOVB BP, 2(BX) - ADDQ R11, R14 - ADDQ R11, BX - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (BX) + MOVB BP, 2(BX) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 @@ -1707,13 +1707,13 @@ copy_2_move_1or2: JMP copy_2_end copy_2_move_3: - MOVW (R11), R12 - MOVB 2(R11), R14 - MOVW R12, (BX) - MOVB R14, 2(BX) - ADDQ R13, R11 - ADDQ R13, BX - JMP copy_2_end + MOVWQZX (R11), R12 + MOVB 2(R11), R14 + MOVW R12, (BX) + MOVB R14, 2(BX) + ADDQ R13, R11 + ADDQ R13, BX + JMP copy_2_end copy_2_move_4through7: MOVL (R11), R12 @@ -1740,12 +1740,12 @@ copy_overlapping_match: ADDQ R13, DI copy_slow_3: - MOVB (R11), R12 - MOVB R12, (BX) - INCQ R11 - INCQ BX - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (R11), R12 + MOVB R12, (BX) + INCQ R11 + INCQ BX + DECQ R13 + JNZ copy_slow_3 handle_loop: ADDQ $0x18, AX @@ -1853,43 +1853,43 @@ sequenceDecs_decodeSync_amd64_fill_check_overread: sequenceDecs_decodeSync_amd64_fill_end: // Update offset - MOVQ R9, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_of_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_of_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_amd64_of_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_amd64_of_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_amd64_of_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX sequenceDecs_decodeSync_amd64_of_update_zero: MOVQ AX, 8(SP) // Update match length - MOVQ R8, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_ml_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_ml_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_amd64_ml_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_amd64_ml_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_amd64_ml_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX sequenceDecs_decodeSync_amd64_ml_update_zero: MOVQ AX, 16(SP) @@ -1924,22 +1924,22 @@ sequenceDecs_decodeSync_amd64_fill_2_check_overread: sequenceDecs_decodeSync_amd64_fill_2_end: // Update literal length - MOVQ DI, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_ll_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_ll_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_amd64_ll_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_amd64_ll_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_amd64_ll_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX sequenceDecs_decodeSync_amd64_ll_update_zero: MOVQ AX, 24(SP) @@ -1961,7 +1961,7 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R14 MOVL $0x00000001, R15 - MOVB R13, CL + MOVBLZX R13, CX SHLL CL, R15 DECL R15 ANDQ R15, R14 @@ -1980,7 +1980,7 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R14 MOVL $0x00000001, R15 - MOVB R13, CL + MOVBLZX R13, CX SHLL CL, R15 DECL R15 ANDQ R15, R14 @@ -1999,7 +1999,7 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R14 MOVL $0x00000001, R15 - MOVB R13, CL + MOVBLZX R13, CX SHLL CL, R15 DECL R15 ANDQ R15, R14 @@ -2143,13 +2143,13 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), AX - MOVB 2(R14), CL - MOVW AX, (R10) - MOVB CL, 2(R10) - ADDQ R13, R14 - ADDQ R13, R10 - JMP copy_4_end + MOVWQZX (R14), AX + MOVB 2(R14), CL + MOVW AX, (R10) + MOVB CL, 2(R10) + ADDQ R13, R14 + ADDQ R13, R10 + JMP copy_4_end copy_4_move_4through7: MOVL (R14), AX @@ -2209,13 +2209,13 @@ copy_5_move_1or2: JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (R10) - MOVB BP, 2(R10) - ADDQ AX, R14 - ADDQ AX, R10 - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R10) + MOVB BP, 2(R10) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 @@ -2266,12 +2266,12 @@ copy_overlapping_match: ADDQ R13, R12 copy_slow_3: - MOVB (AX), CL - MOVB CL, (R10) - INCQ AX - INCQ R10 - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (AX), CX + MOVB CL, (R10) + INCQ AX + INCQ R10 + DECQ R13 + JNZ copy_slow_3 handle_loop: MOVQ ctx+16(FP), AX @@ -2663,13 +2663,13 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), CX - MOVB 2(R14), R12 - MOVW CX, (R9) - MOVB R12, 2(R9) - ADDQ R13, R14 - ADDQ R13, R9 - JMP copy_4_end + MOVWQZX (R14), CX + MOVB 2(R14), R12 + MOVW CX, (R9) + MOVB R12, 2(R9) + ADDQ R13, R14 + ADDQ R13, R9 + JMP copy_4_end copy_4_move_4through7: MOVL (R14), CX @@ -2729,13 +2729,13 @@ copy_5_move_1or2: JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (R9) - MOVB BP, 2(R9) - ADDQ CX, R14 - ADDQ CX, R9 - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R9) + MOVB BP, 2(R9) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 @@ -2786,12 +2786,12 @@ copy_overlapping_match: ADDQ R13, R11 copy_slow_3: - MOVB (CX), R12 - MOVB R12, (R9) - INCQ CX - INCQ R9 - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (CX), R12 + MOVB R12, (R9) + INCQ CX + INCQ R9 + DECQ R13 + JNZ copy_slow_3 handle_loop: MOVQ ctx+16(FP), CX @@ -2935,43 +2935,43 @@ sequenceDecs_decodeSync_safe_amd64_fill_check_overread: sequenceDecs_decodeSync_safe_amd64_fill_end: // Update offset - MOVQ R9, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_of_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_of_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_safe_amd64_of_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_safe_amd64_of_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_safe_amd64_of_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX sequenceDecs_decodeSync_safe_amd64_of_update_zero: MOVQ AX, 8(SP) // Update match length - MOVQ R8, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_ml_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_ml_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_safe_amd64_ml_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_safe_amd64_ml_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_safe_amd64_ml_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX sequenceDecs_decodeSync_safe_amd64_ml_update_zero: MOVQ AX, 16(SP) @@ -3006,22 +3006,22 @@ sequenceDecs_decodeSync_safe_amd64_fill_2_check_overread: sequenceDecs_decodeSync_safe_amd64_fill_2_end: // Update literal length - MOVQ DI, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_ll_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_ll_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_safe_amd64_ll_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_safe_amd64_ll_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_safe_amd64_ll_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX sequenceDecs_decodeSync_safe_amd64_ll_update_zero: MOVQ AX, 24(SP) @@ -3043,7 +3043,7 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R14 MOVL $0x00000001, R15 - MOVB R13, CL + MOVBLZX R13, CX SHLL CL, R15 DECL R15 ANDQ R15, R14 @@ -3062,7 +3062,7 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R14 MOVL $0x00000001, R15 - MOVB R13, CL + MOVBLZX R13, CX SHLL CL, R15 DECL R15 ANDQ R15, R14 @@ -3081,7 +3081,7 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: MOVQ CX, BX ROLQ CL, R14 MOVL $0x00000001, R15 - MOVB R13, CL + MOVBLZX R13, CX SHLL CL, R15 DECL R15 ANDQ R15, R14 @@ -3206,13 +3206,13 @@ copy_1_move_1or2: JMP copy_1_end copy_1_move_3: - MOVW (R11), R14 - MOVB 2(R11), R15 - MOVW R14, (R10) - MOVB R15, 2(R10) - ADDQ AX, R11 - ADDQ AX, R10 - JMP copy_1_end + MOVWQZX (R11), R14 + MOVB 2(R11), R15 + MOVW R14, (R10) + MOVB R15, 2(R10) + ADDQ AX, R11 + ADDQ AX, R10 + JMP copy_1_end copy_1_move_4through7: MOVL (R11), R14 @@ -3276,13 +3276,13 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), AX - MOVB 2(R14), CL - MOVW AX, (R10) - MOVB CL, 2(R10) - ADDQ R13, R14 - ADDQ R13, R10 - JMP copy_4_end + MOVWQZX (R14), AX + MOVB 2(R14), CL + MOVW AX, (R10) + MOVB CL, 2(R10) + ADDQ R13, R14 + ADDQ R13, R10 + JMP copy_4_end copy_4_move_4through7: MOVL (R14), AX @@ -3342,13 +3342,13 @@ copy_5_move_1or2: JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (R10) - MOVB BP, 2(R10) - ADDQ AX, R14 - ADDQ AX, R10 - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R10) + MOVB BP, 2(R10) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 @@ -3417,13 +3417,13 @@ copy_2_move_1or2: JMP copy_2_end copy_2_move_3: - MOVW (AX), CX - MOVB 2(AX), R14 - MOVW CX, (R10) - MOVB R14, 2(R10) - ADDQ R13, AX - ADDQ R13, R10 - JMP copy_2_end + MOVWQZX (AX), CX + MOVB 2(AX), R14 + MOVW CX, (R10) + MOVB R14, 2(R10) + ADDQ R13, AX + ADDQ R13, R10 + JMP copy_2_end copy_2_move_4through7: MOVL (AX), CX @@ -3450,12 +3450,12 @@ copy_overlapping_match: ADDQ R13, R12 copy_slow_3: - MOVB (AX), CL - MOVB CL, (R10) - INCQ AX - INCQ R10 - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (AX), CX + MOVB CL, (R10) + INCQ AX + INCQ R10 + DECQ R13 + JNZ copy_slow_3 handle_loop: MOVQ ctx+16(FP), AX @@ -3828,13 +3828,13 @@ copy_1_move_1or2: JMP copy_1_end copy_1_move_3: - MOVW (R10), R14 - MOVB 2(R10), R15 - MOVW R14, (R9) - MOVB R15, 2(R9) - ADDQ CX, R10 - ADDQ CX, R9 - JMP copy_1_end + MOVWQZX (R10), R14 + MOVB 2(R10), R15 + MOVW R14, (R9) + MOVB R15, 2(R9) + ADDQ CX, R10 + ADDQ CX, R9 + JMP copy_1_end copy_1_move_4through7: MOVL (R10), R14 @@ -3898,13 +3898,13 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), CX - MOVB 2(R14), R12 - MOVW CX, (R9) - MOVB R12, 2(R9) - ADDQ R13, R14 - ADDQ R13, R9 - JMP copy_4_end + MOVWQZX (R14), CX + MOVB 2(R14), R12 + MOVW CX, (R9) + MOVB R12, 2(R9) + ADDQ R13, R14 + ADDQ R13, R9 + JMP copy_4_end copy_4_move_4through7: MOVL (R14), CX @@ -3964,13 +3964,13 @@ copy_5_move_1or2: JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (R9) - MOVB BP, 2(R9) - ADDQ CX, R14 - ADDQ CX, R9 - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R9) + MOVB BP, 2(R9) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 @@ -4039,13 +4039,13 @@ copy_2_move_1or2: JMP copy_2_end copy_2_move_3: - MOVW (CX), R12 - MOVB 2(CX), R14 - MOVW R12, (R9) - MOVB R14, 2(R9) - ADDQ R13, CX - ADDQ R13, R9 - JMP copy_2_end + MOVWQZX (CX), R12 + MOVB 2(CX), R14 + MOVW R12, (R9) + MOVB R14, 2(R9) + ADDQ R13, CX + ADDQ R13, R9 + JMP copy_2_end copy_2_move_4through7: MOVL (CX), R12 @@ -4072,12 +4072,12 @@ copy_overlapping_match: ADDQ R13, R11 copy_slow_3: - MOVB (CX), R12 - MOVB R12, (R9) - INCQ CX - INCQ R9 - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (CX), R12 + MOVB R12, (R9) + INCQ CX + INCQ R9 + DECQ R13 + JNZ copy_slow_3 handle_loop: MOVQ ctx+16(FP), CX diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s index 6f54ef21ba..fa48be19e4 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s @@ -1,7 +1,7 @@ // Code generated by command: go run gen.go -out ../seqdec.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT. // EXPERIMENTAL arm64 output lowered from an amd64 avo program. -//go:build arm64 && !appengine && !noasm && gc && !noasm +//go:build arm64 && (!appengine && !noasm && gc && !noasm) // func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV @@ -60,8 +60,7 @@ sequenceDecs_decode_amd64_fill_end: MOVD R3, R1 MOVD R2, R14 LSL R1, R14, R14 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decode_amd64_of_update_zero @@ -82,8 +81,7 @@ sequenceDecs_decode_amd64_of_update_zero: MOVD R3, R1 MOVD R2, R14 LSL R1, R14, R14 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decode_amd64_ml_update_zero @@ -133,8 +131,7 @@ sequenceDecs_decode_amd64_fill_2_end: MOVD R3, R1 MOVD R2, R14 LSL R1, R14, R14 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decode_amd64_ll_update_zero @@ -151,14 +148,12 @@ sequenceDecs_decode_amd64_ll_update_zero: MOVD R0, (R9) // Fill bitreader for state updates - MOVD R13, 8(RSP) - MOVD R8, R0 - LSR $0x08, R0, R0 - MOVBU R0, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 - CMP $0x00, R16 - BEQ sequenceDecs_decode_amd64_skip_update + MOVD R13, 8(RSP) + UBFX $8, R8, $8, R0 + MOVD ctx+16(FP), R1 + MOVD 96(R1), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decode_amd64_skip_update // Update Literal Length State MOVBU R6, R13 @@ -169,7 +164,7 @@ sequenceDecs_decode_amd64_ll_update_zero: NEG R1, R16 ROR R16, R14, R14 MOVD $0x00000001, R4 - BFI $0, R13, $8, R1 + MOVBU R13, R1 LSLW R1, R4, R4 SUBW $1, R4, R4 AND R4, R14, R14 @@ -178,8 +173,7 @@ sequenceDecs_decode_amd64_ll_update_zero: // Load ctx.llTable MOVD ctx+16(FP), R1 MOVD (R1), R1 - ADD R6<<3, R1, R15 - MOVD (R15), R6 + MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R13 @@ -190,7 +184,7 @@ sequenceDecs_decode_amd64_ll_update_zero: NEG R1, R16 ROR R16, R14, R14 MOVD $0x00000001, R4 - BFI $0, R13, $8, R1 + MOVBU R13, R1 LSLW R1, R4, R4 SUBW $1, R4, R4 AND R4, R14, R14 @@ -199,8 +193,7 @@ sequenceDecs_decode_amd64_ll_update_zero: // Load ctx.mlTable MOVD ctx+16(FP), R1 MOVD 24(R1), R1 - ADD R7<<3, R1, R15 - MOVD (R15), R7 + MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R13 @@ -211,7 +204,7 @@ sequenceDecs_decode_amd64_ll_update_zero: NEG R1, R16 ROR R16, R14, R14 MOVD $0x00000001, R4 - BFI $0, R13, $8, R1 + MOVBU R13, R1 LSLW R1, R4, R4 SUBW $1, R4, R4 AND R4, R14, R14 @@ -220,8 +213,7 @@ sequenceDecs_decode_amd64_ll_update_zero: // Load ctx.ofTable MOVD ctx+16(FP), R1 MOVD 48(R1), R1 - ADD R8<<3, R1, R15 - MOVD (R15), R8 + MOVD (R1)(R8<<3), R8 sequenceDecs_decode_amd64_skip_update: // Adjust offset @@ -411,8 +403,7 @@ sequenceDecs_decode_56_amd64_fill_end: MOVD R3, R1 MOVD R2, R14 LSL R1, R14, R14 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decode_56_amd64_of_update_zero @@ -433,8 +424,7 @@ sequenceDecs_decode_56_amd64_of_update_zero: MOVD R3, R1 MOVD R2, R14 LSL R1, R14, R14 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decode_56_amd64_ml_update_zero @@ -455,8 +445,7 @@ sequenceDecs_decode_56_amd64_ml_update_zero: MOVD R3, R1 MOVD R2, R14 LSL R1, R14, R14 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decode_56_amd64_ll_update_zero @@ -473,14 +462,12 @@ sequenceDecs_decode_56_amd64_ll_update_zero: MOVD R0, (R9) // Fill bitreader for state updates - MOVD R13, 8(RSP) - MOVD R8, R0 - LSR $0x08, R0, R0 - MOVBU R0, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 - CMP $0x00, R16 - BEQ sequenceDecs_decode_56_amd64_skip_update + MOVD R13, 8(RSP) + UBFX $8, R8, $8, R0 + MOVD ctx+16(FP), R1 + MOVD 96(R1), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decode_56_amd64_skip_update // Update Literal Length State MOVBU R6, R13 @@ -491,7 +478,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: NEG R1, R16 ROR R16, R14, R14 MOVD $0x00000001, R4 - BFI $0, R13, $8, R1 + MOVBU R13, R1 LSLW R1, R4, R4 SUBW $1, R4, R4 AND R4, R14, R14 @@ -500,8 +487,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: // Load ctx.llTable MOVD ctx+16(FP), R1 MOVD (R1), R1 - ADD R6<<3, R1, R15 - MOVD (R15), R6 + MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R13 @@ -512,7 +498,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: NEG R1, R16 ROR R16, R14, R14 MOVD $0x00000001, R4 - BFI $0, R13, $8, R1 + MOVBU R13, R1 LSLW R1, R4, R4 SUBW $1, R4, R4 AND R4, R14, R14 @@ -521,8 +507,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: // Load ctx.mlTable MOVD ctx+16(FP), R1 MOVD 24(R1), R1 - ADD R7<<3, R1, R15 - MOVD (R15), R7 + MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R13 @@ -533,7 +518,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: NEG R1, R16 ROR R16, R14, R14 MOVD $0x00000001, R4 - BFI $0, R13, $8, R1 + MOVBU R13, R1 LSLW R1, R4, R4 SUBW $1, R4, R4 AND R4, R14, R14 @@ -542,8 +527,7 @@ sequenceDecs_decode_56_amd64_ll_update_zero: // Load ctx.ofTable MOVD ctx+16(FP), R1 MOVD 48(R1), R1 - ADD R8<<3, R1, R15 - MOVD (R15), R8 + MOVD (R1)(R8<<3), R8 sequenceDecs_decode_56_amd64_skip_update: // Adjust offset @@ -716,16 +700,16 @@ main_loop: MOVD $0, R13 copy_1: - ADD R13, R5, R15 - VLD1 (R15), [V0.B16] - ADD R13, R3, R15 - VST1 [V0.B16], (R15) - ADD $0x10, R13, R13 - CMP R10, R13 - BLO copy_1 - ADD R10, R5, R5 - ADD R10, R3, R3 - ADD R10, R6, R6 + ADD R13, R5, R15 + FMOVQ (R15), F0 + ADD R13, R3, R15 + FMOVQ F0, (R15) + ADD $0x10, R13, R13 + CMP R10, R13 + BLO copy_1 + ADD R10, R5, R5 + ADD R10, R3, R3 + ADD R10, R6, R6 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) check_offset: @@ -748,21 +732,19 @@ check_offset: BLO copy_4_small copy_4_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R13, R13 - ADD $0x10, R3, R3 - SUBS $0x10, R10, R10 - BHS copy_4_loop - ADD R10, R13, R13 - ADD $16, R13, R13 - ADD R10, R3, R3 - ADD $16, R3, R3 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_4_end + FMOVQ (R13), F0 + FMOVQ F0, (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R10, R10 + BHS copy_4_loop + ADD R10, R13, R13 + ADD $16, R13, R13 + ADD R10, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R3) + JMP copy_4_end copy_4_small: CMP $0x03, R12 @@ -816,21 +798,19 @@ copy_all_from_history: BLO copy_5_small copy_5_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R13, R13 - ADD $0x10, R3, R3 - SUBS $0x10, R14, R14 - BHS copy_5_loop - ADD R14, R13, R13 - ADD $16, R13, R13 - ADD R14, R3, R3 - ADD $16, R3, R3 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_5_end + FMOVQ (R13), F0 + FMOVQ F0, (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R3) + JMP copy_5_end copy_5_small: CMP $0x03, R10 @@ -903,21 +883,20 @@ copy_match: ADD R12, R3, R3 copy_2: - VLD1 (R10), [V0.B16] - VST1 [V0.B16], (R11) - ADD $0x10, R10, R10 - ADD $0x10, R11, R11 - SUBS $0x10, R12, R12 - BHI copy_2 - JMP handle_loop + FMOVQ (R10), F0 + FMOVQ F0, (R11) + ADD $0x10, R10, R10 + ADD $0x10, R11, R11 + SUBS $0x10, R12, R12 + BHI copy_2 + JMP handle_loop // Copy overlapping match copy_overlapping_match: ADD R12, R6, R6 copy_slow_3: - MOVBU (R10), R16 - BFI $0, R16, $8, R11 + MOVBU (R10), R11 MOVB R11, (R3) ADD $1, R10, R10 ADD $1, R3, R3 @@ -1002,21 +981,19 @@ main_loop: BLO copy_1_small copy_1_loop: - VLD1 (R5), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R5, R5 - ADD $0x10, R3, R3 - SUBS $0x10, R13, R13 - BHS copy_1_loop - ADD R13, R5, R5 - ADD $16, R5, R5 - ADD R13, R3, R3 - ADD $16, R3, R3 - ADD $-16, R5, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_1_end + FMOVQ (R5), F0 + FMOVQ F0, (R3) + ADD $0x10, R5, R5 + ADD $0x10, R3, R3 + SUBS $0x10, R13, R13 + BHS copy_1_loop + ADD R13, R5, R5 + ADD $16, R5, R5 + ADD R13, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R5), F0 + FMOVQ F0, -16(R3) + JMP copy_1_end copy_1_small: CMP $0x03, R10 @@ -1094,21 +1071,19 @@ check_offset: BLO copy_4_small copy_4_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R13, R13 - ADD $0x10, R3, R3 - SUBS $0x10, R10, R10 - BHS copy_4_loop - ADD R10, R13, R13 - ADD $16, R13, R13 - ADD R10, R3, R3 - ADD $16, R3, R3 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_4_end + FMOVQ (R13), F0 + FMOVQ F0, (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R10, R10 + BHS copy_4_loop + ADD R10, R13, R13 + ADD $16, R13, R13 + ADD R10, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R3) + JMP copy_4_end copy_4_small: CMP $0x03, R12 @@ -1162,21 +1137,19 @@ copy_all_from_history: BLO copy_5_small copy_5_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R13, R13 - ADD $0x10, R3, R3 - SUBS $0x10, R14, R14 - BHS copy_5_loop - ADD R14, R13, R13 - ADD $16, R13, R13 - ADD R14, R3, R3 - ADD $16, R3, R3 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_5_end + FMOVQ (R13), F0 + FMOVQ F0, (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R3) + JMP copy_5_end copy_5_small: CMP $0x03, R10 @@ -1250,21 +1223,19 @@ copy_match: BLO copy_2_small copy_2_loop: - VLD1 (R10), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R10, R10 - ADD $0x10, R3, R3 - SUBS $0x10, R11, R11 - BHS copy_2_loop - ADD R11, R10, R10 - ADD $16, R10, R10 - ADD R11, R3, R3 - ADD $16, R3, R3 - ADD $-16, R10, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_2_end + FMOVQ (R10), F0 + FMOVQ F0, (R3) + ADD $0x10, R10, R10 + ADD $0x10, R3, R3 + SUBS $0x10, R11, R11 + BHS copy_2_loop + ADD R11, R10, R10 + ADD $16, R10, R10 + ADD R11, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R10), F0 + FMOVQ F0, -16(R3) + JMP copy_2_end copy_2_small: CMP $0x03, R12 @@ -1326,8 +1297,7 @@ copy_overlapping_match: ADD R12, R6, R6 copy_slow_3: - MOVBU (R10), R16 - BFI $0, R16, $8, R11 + MOVBU (R10), R11 MOVB R11, (R3) ADD $1, R10, R10 ADD $1, R3, R3 @@ -1453,8 +1423,7 @@ sequenceDecs_decodeSync_amd64_fill_end: MOVD R3, R1 MOVD R2, R13 LSL R1, R13, R13 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decodeSync_amd64_of_update_zero @@ -1475,8 +1444,7 @@ sequenceDecs_decodeSync_amd64_of_update_zero: MOVD R3, R1 MOVD R2, R13 LSL R1, R13, R13 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decodeSync_amd64_ml_update_zero @@ -1526,8 +1494,7 @@ sequenceDecs_decodeSync_amd64_fill_2_end: MOVD R3, R1 MOVD R2, R13 LSL R1, R13, R13 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decodeSync_amd64_ll_update_zero @@ -1544,14 +1511,12 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: MOVD R0, 32(RSP) // Fill bitreader for state updates - MOVD R12, 8(RSP) - MOVD R8, R0 - LSR $0x08, R0, R0 - MOVBU R0, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 - CMP $0x00, R16 - BEQ sequenceDecs_decodeSync_amd64_skip_update + MOVD R12, 8(RSP) + UBFX $8, R8, $8, R0 + MOVD ctx+16(FP), R1 + MOVD 96(R1), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decodeSync_amd64_skip_update // Update Literal Length State MOVBU R6, R12 @@ -1562,7 +1527,7 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: NEG R1, R16 ROR R16, R13, R13 MOVD $0x00000001, R14 - BFI $0, R12, $8, R1 + MOVBU R12, R1 LSLW R1, R14, R14 SUBW $1, R14, R14 AND R14, R13, R13 @@ -1571,8 +1536,7 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: // Load ctx.llTable MOVD ctx+16(FP), R1 MOVD (R1), R1 - ADD R6<<3, R1, R15 - MOVD (R15), R6 + MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R12 @@ -1583,7 +1547,7 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: NEG R1, R16 ROR R16, R13, R13 MOVD $0x00000001, R14 - BFI $0, R12, $8, R1 + MOVBU R12, R1 LSLW R1, R14, R14 SUBW $1, R14, R14 AND R14, R13, R13 @@ -1592,8 +1556,7 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: // Load ctx.mlTable MOVD ctx+16(FP), R1 MOVD 24(R1), R1 - ADD R7<<3, R1, R15 - MOVD (R15), R7 + MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R12 @@ -1604,7 +1567,7 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: NEG R1, R16 ROR R16, R13, R13 MOVD $0x00000001, R14 - BFI $0, R12, $8, R1 + MOVBU R12, R1 LSLW R1, R14, R14 SUBW $1, R14, R14 AND R14, R13, R13 @@ -1613,21 +1576,18 @@ sequenceDecs_decodeSync_amd64_ll_update_zero: // Load ctx.ofTable MOVD ctx+16(FP), R1 MOVD 48(R1), R1 - ADD R8<<3, R1, R15 - MOVD (R15), R8 + MOVD (R1)(R8<<3), R8 sequenceDecs_decodeSync_amd64_skip_update: // Adjust offset - MOVD s+0(FP), R1 - MOVD 16(RSP), R12 - CMP $0x01, R0 - BLS sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 - ADD $144, R1, R15 - VLD1 (R15), [V0.B16] - MOVD R12, 144(R1) - ADD $152, R1, R15 - VST1 [V0.B16], (R15) - JMP sequenceDecs_decodeSync_amd64_after_adjust + MOVD s+0(FP), R1 + MOVD 16(RSP), R12 + CMP $0x01, R0 + BLS sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 + FMOVQ 144(R1), F0 + MOVD R12, 144(R1) + FMOVQ F0, 152(R1) + JMP sequenceDecs_decodeSync_amd64_after_adjust sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0: MOVD 32(RSP), R16 @@ -1709,16 +1669,16 @@ sequenceDecs_decodeSync_amd64_match_len_ofs_ok: MOVD $0, R13 copy_1: - ADD R13, R10, R15 - VLD1 (R15), [V0.B16] - ADD R13, R9, R15 - VST1 [V0.B16], (R15) - ADD $0x10, R13, R13 - CMP R0, R13 - BLO copy_1 - ADD R0, R10, R10 - ADD R0, R9, R9 - ADD R0, R11, R11 + ADD R13, R10, R15 + FMOVQ (R15), F0 + ADD R13, R9, R15 + FMOVQ F0, (R15) + ADD $0x10, R13, R13 + CMP R0, R13 + BLO copy_1 + ADD R0, R10, R10 + ADD R0, R9, R9 + ADD R0, R11, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) check_offset: @@ -1744,21 +1704,19 @@ check_offset: BLO copy_4_small copy_4_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R13, R13 - ADD $0x10, R9, R9 - SUBS $0x10, R0, R0 - BHS copy_4_loop - ADD R0, R13, R13 - ADD $16, R13, R13 - ADD R0, R9, R9 - ADD $16, R9, R9 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_4_end + FMOVQ (R13), F0 + FMOVQ F0, (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R0, R0 + BHS copy_4_loop + ADD R0, R13, R13 + ADD $16, R13, R13 + ADD R0, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R9) + JMP copy_4_end copy_4_small: CMP $0x03, R12 @@ -1809,21 +1767,19 @@ copy_all_from_history: BLO copy_5_small copy_5_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R13, R13 - ADD $0x10, R9, R9 - SUBS $0x10, R14, R14 - BHS copy_5_loop - ADD R14, R13, R13 - ADD $16, R13, R13 - ADD R14, R9, R9 - ADD $16, R9, R9 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_5_end + FMOVQ (R13), F0 + FMOVQ F0, (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R9) + JMP copy_5_end copy_5_small: CMP $0x03, R0 @@ -1896,21 +1852,20 @@ copy_match: ADD R12, R9, R9 copy_2: - VLD1 (R0), [V0.B16] - VST1 [V0.B16], (R1) - ADD $0x10, R0, R0 - ADD $0x10, R1, R1 - SUBS $0x10, R12, R12 - BHI copy_2 - JMP handle_loop + FMOVQ (R0), F0 + FMOVQ F0, (R1) + ADD $0x10, R0, R0 + ADD $0x10, R1, R1 + SUBS $0x10, R12, R12 + BHI copy_2 + JMP handle_loop // Copy overlapping match copy_overlapping_match: ADD R12, R11, R11 copy_slow_3: - MOVBU (R0), R16 - BFI $0, R16, $8, R1 + MOVBU (R0), R1 MOVB R1, (R9) ADD $1, R0, R0 ADD $1, R9, R9 @@ -2078,8 +2033,7 @@ sequenceDecs_decodeSync_safe_amd64_fill_end: MOVD R3, R1 MOVD R2, R13 LSL R1, R13, R13 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decodeSync_safe_amd64_of_update_zero @@ -2100,8 +2054,7 @@ sequenceDecs_decodeSync_safe_amd64_of_update_zero: MOVD R3, R1 MOVD R2, R13 LSL R1, R13, R13 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decodeSync_safe_amd64_ml_update_zero @@ -2151,8 +2104,7 @@ sequenceDecs_decodeSync_safe_amd64_fill_2_end: MOVD R3, R1 MOVD R2, R13 LSL R1, R13, R13 - UBFX $8, R0, $8, R16 - BFI $0, R16, $8, R1 + UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 TST R1, R1 BEQ sequenceDecs_decodeSync_safe_amd64_ll_update_zero @@ -2169,14 +2121,12 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: MOVD R0, 32(RSP) // Fill bitreader for state updates - MOVD R12, 8(RSP) - MOVD R8, R0 - LSR $0x08, R0, R0 - MOVBU R0, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 - CMP $0x00, R16 - BEQ sequenceDecs_decodeSync_safe_amd64_skip_update + MOVD R12, 8(RSP) + UBFX $8, R8, $8, R0 + MOVD ctx+16(FP), R1 + MOVD 96(R1), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decodeSync_safe_amd64_skip_update // Update Literal Length State MOVBU R6, R12 @@ -2187,7 +2137,7 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: NEG R1, R16 ROR R16, R13, R13 MOVD $0x00000001, R14 - BFI $0, R12, $8, R1 + MOVBU R12, R1 LSLW R1, R14, R14 SUBW $1, R14, R14 AND R14, R13, R13 @@ -2196,8 +2146,7 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: // Load ctx.llTable MOVD ctx+16(FP), R1 MOVD (R1), R1 - ADD R6<<3, R1, R15 - MOVD (R15), R6 + MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R12 @@ -2208,7 +2157,7 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: NEG R1, R16 ROR R16, R13, R13 MOVD $0x00000001, R14 - BFI $0, R12, $8, R1 + MOVBU R12, R1 LSLW R1, R14, R14 SUBW $1, R14, R14 AND R14, R13, R13 @@ -2217,8 +2166,7 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: // Load ctx.mlTable MOVD ctx+16(FP), R1 MOVD 24(R1), R1 - ADD R7<<3, R1, R15 - MOVD (R15), R7 + MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R12 @@ -2229,7 +2177,7 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: NEG R1, R16 ROR R16, R13, R13 MOVD $0x00000001, R14 - BFI $0, R12, $8, R1 + MOVBU R12, R1 LSLW R1, R14, R14 SUBW $1, R14, R14 AND R14, R13, R13 @@ -2238,21 +2186,18 @@ sequenceDecs_decodeSync_safe_amd64_ll_update_zero: // Load ctx.ofTable MOVD ctx+16(FP), R1 MOVD 48(R1), R1 - ADD R8<<3, R1, R15 - MOVD (R15), R8 + MOVD (R1)(R8<<3), R8 sequenceDecs_decodeSync_safe_amd64_skip_update: // Adjust offset - MOVD s+0(FP), R1 - MOVD 16(RSP), R12 - CMP $0x01, R0 - BLS sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 - ADD $144, R1, R15 - VLD1 (R15), [V0.B16] - MOVD R12, 144(R1) - ADD $152, R1, R15 - VST1 [V0.B16], (R15) - JMP sequenceDecs_decodeSync_safe_amd64_after_adjust + MOVD s+0(FP), R1 + MOVD 16(RSP), R12 + CMP $0x01, R0 + BLS sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 + FMOVQ 144(R1), F0 + MOVD R12, 144(R1) + FMOVQ F0, 152(R1) + JMP sequenceDecs_decodeSync_safe_amd64_after_adjust sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0: MOVD 32(RSP), R16 @@ -2335,21 +2280,19 @@ sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok: BLO copy_1_small copy_1_loop: - VLD1 (R10), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R10, R10 - ADD $0x10, R9, R9 - SUBS $0x10, R13, R13 - BHS copy_1_loop - ADD R13, R10, R10 - ADD $16, R10, R10 - ADD R13, R9, R9 - ADD $16, R9, R9 - ADD $-16, R10, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_1_end + FMOVQ (R10), F0 + FMOVQ F0, (R9) + ADD $0x10, R10, R10 + ADD $0x10, R9, R9 + SUBS $0x10, R13, R13 + BHS copy_1_loop + ADD R13, R10, R10 + ADD $16, R10, R10 + ADD R13, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R10), F0 + FMOVQ F0, -16(R9) + JMP copy_1_end copy_1_small: CMP $0x03, R0 @@ -2430,21 +2373,19 @@ check_offset: BLO copy_4_small copy_4_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R13, R13 - ADD $0x10, R9, R9 - SUBS $0x10, R0, R0 - BHS copy_4_loop - ADD R0, R13, R13 - ADD $16, R13, R13 - ADD R0, R9, R9 - ADD $16, R9, R9 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_4_end + FMOVQ (R13), F0 + FMOVQ F0, (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R0, R0 + BHS copy_4_loop + ADD R0, R13, R13 + ADD $16, R13, R13 + ADD R0, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R9) + JMP copy_4_end copy_4_small: CMP $0x03, R12 @@ -2495,21 +2436,19 @@ copy_all_from_history: BLO copy_5_small copy_5_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R13, R13 - ADD $0x10, R9, R9 - SUBS $0x10, R14, R14 - BHS copy_5_loop - ADD R14, R13, R13 - ADD $16, R13, R13 - ADD R14, R9, R9 - ADD $16, R9, R9 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_5_end + FMOVQ (R13), F0 + FMOVQ F0, (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R9) + JMP copy_5_end copy_5_small: CMP $0x03, R0 @@ -2583,21 +2522,19 @@ copy_match: BLO copy_2_small copy_2_loop: - VLD1 (R0), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R0, R0 - ADD $0x10, R9, R9 - SUBS $0x10, R1, R1 - BHS copy_2_loop - ADD R1, R0, R0 - ADD $16, R0, R0 - ADD R1, R9, R9 - ADD $16, R9, R9 - ADD $-16, R0, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_2_end + FMOVQ (R0), F0 + FMOVQ F0, (R9) + ADD $0x10, R0, R0 + ADD $0x10, R9, R9 + SUBS $0x10, R1, R1 + BHS copy_2_loop + ADD R1, R0, R0 + ADD $16, R0, R0 + ADD R1, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R0), F0 + FMOVQ F0, -16(R9) + JMP copy_2_end copy_2_small: CMP $0x03, R12 @@ -2659,8 +2596,7 @@ copy_overlapping_match: ADD R12, R11, R11 copy_slow_3: - MOVBU (R0), R16 - BFI $0, R16, $8, R1 + MOVBU (R0), R1 MOVB R1, (R9) ADD $1, R0, R0 ADD $1, R9, R9 diff --git a/vendor/modules.txt b/vendor/modules.txt index 501237c5a1..d1e1f791be 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -145,8 +145,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2/utilities # github.com/inconshreveable/mousetrap v1.1.0 ## explicit; go 1.18 github.com/inconshreveable/mousetrap -# github.com/klauspost/compress v1.19.2 -## explicit; go 1.24 +# github.com/klauspost/compress v1.20.0 +## explicit; go 1.25 github.com/klauspost/compress github.com/klauspost/compress/fse github.com/klauspost/compress/huff0 From 07339fa78f92d29941a2a02380a1948e2e7b632d Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 1 Oct 2026 19:34:03 +0200 Subject: [PATCH 08/26] vendor: github.com/klauspost/compress v1.20.1 full diff: https://github.com/klauspost/compress/compare/v1.20.0...v1.20.1 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 4 +- .../klauspost/compress/huff0/bitreader.go | 63 + .../compress/huff0/decompress_amd64.go | 95 +- .../compress/huff0/decompress_amd64.s | 4102 +++++++++++++---- .../compress/huff0/decompress_arm64.go | 43 +- .../compress/huff0/decompress_arm64.s | 2399 +++++++--- .../compress/huff0/decompress_asm.go | 98 +- .../klauspost/compress/zstd/blockdec.go | 3 + .../klauspost/compress/zstd/decoder.go | 125 +- .../klauspost/compress/zstd/framedec.go | 11 +- .../compress/zstd/fse_decoder_arm64.s | 10 +- .../klauspost/compress/zstd/seqdec.go | 23 + .../klauspost/compress/zstd/seqdec_amd64.s | 1669 +++---- .../klauspost/compress/zstd/seqdec_arm64.s | 1125 +++-- .../klauspost/compress/zstd/seqdec_asm.go | 7 +- vendor/modules.txt | 2 +- 17 files changed, 6720 insertions(+), 3061 deletions(-) diff --git a/vendor.mod b/vendor.mod index e6f777058e..f334409c13 100644 --- a/vendor.mod +++ b/vendor.mod @@ -87,7 +87,7 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.20.0 // indirect + github.com/klauspost/compress v1.20.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/sys/user v0.4.1 // indirect github.com/moby/sys/userns v0.2.1 // indirect diff --git a/vendor.sum b/vendor.sum index a02c98915b..d1581457c7 100644 --- a/vendor.sum +++ b/vendor.sum @@ -78,8 +78,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= -github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= +github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ= +github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mattn/go-runewidth v0.0.29 h1:3oGF3R/S2N9DQ3ptftzVIvg2eicmojCzlwBEmqEPDfQ= diff --git a/vendor/github.com/klauspost/compress/huff0/bitreader.go b/vendor/github.com/klauspost/compress/huff0/bitreader.go index bfc7a523de..faaa418a75 100644 --- a/vendor/github.com/klauspost/compress/huff0/bitreader.go +++ b/vendor/github.com/klauspost/compress/huff0/bitreader.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "math/bits" "github.com/klauspost/compress/internal/le" ) @@ -210,6 +211,68 @@ func (b *bitReaderShifted) remaining() uint { return b.off*8 + uint(64-b.bitsRead) } +// canUseAsm reports whether the reader has a full 8-byte window ahead of +// its read pointer, which the Decompress4X asm loops need to take over. +func (b *bitReaderShifted) canUseAsm() bool { + return b.off >= 8 +} + +// prepareForAsm establishes the invariant the Decompress4X asm loops rely +// on: value == load64(in[off:off+8]) << bitsRead with bitsRead <= 7, so +// that a full group of symbols can never shift their sentinel bit out of +// the container. init leaves bitsRead == 8 when the final byte of the +// stream is exactly 0x01; that whole byte is consumed, so the same position +// is the window one byte lower with nothing consumed. Requires canUseAsm. +func (b *bitReaderShifted) prepareForAsm() { + if b.bitsRead >= 8 { + b.off-- + b.value = le.Load64(b.in, b.off) + b.bitsRead -= 8 + } +} + +// restoreFromAsm converts the state left behind by the Decompress4X asm +// loops back to the invariant the Go code relies on: value holds the 8 +// bytes at in[off:off+8] shifted left by bitsRead, with the low bitsRead +// bits zero. +// +// The asm keeps a sentinel bit in value just below the unread bits, so its +// trailing zero count is the number of consumed bits. The sentinel is ORed +// over the lowest bit of the window, which the loop never consumes before +// re-reading memory, so the window is re-read here too rather than taken +// from value. The asm reports off as the signed distance from the start of +// the stream, and it can be negative: a reload always reads a whole 8-byte +// window, so a stream that is nearly drained ends with up to 7 bytes of the +// previous stream (or the jump table) below its start inside the window. +// Those bytes sit below the stream's own bits and count as consumed. +// Anything further below, or more bits consumed than the stream holds, is +// corruption. +func (b *bitReaderShifted) restoreFromAsm() error { + off := int(b.off) + consumed := uint(bits.TrailingZeros64(b.value)) + if off < 0 { + if off < -7 { + return errors.New("corruption detected: stream underrun") + } + consumed += uint(-off) * 8 + if consumed > 64 { + return errors.New("corruption detected: stream underrun") + } + off = 0 + } + if off+8 > len(b.in) { + return errors.New("corruption detected: stream overrun") + } + b.off = uint(off) + b.bitsRead = uint8(consumed) + if consumed >= 64 { + b.value = 0 + } else { + b.value = le.Load64(b.in, b.off) << consumed + } + return nil +} + // close the bitstream and returns an error if out-of-buffer reads occurred. func (b *bitReaderShifted) close() error { // Release reference. diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go index 7035d656d9..e651f30ecb 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go @@ -8,36 +8,99 @@ import ( ) // decompress4x_main_loop_amd64 is an x86 assembler implementation -// of Decompress4X when tablelog > 8. +// of Decompress4X when tablelog > 8, decoding fastSymbols symbols per +// stream between bit container reloads. // //go:noescape func decompress4x_main_loop_amd64(ctx *decompress4xContext) // decompress4x_8b_main_loop_amd64 is an x86 assembler implementation -// of Decompress4X when tablelog <= 8 which decodes 4 entries -// per loop. +// of Decompress4X when tablelog <= 8, decoding fast8bSymbols symbols +// per stream between bit container reloads. // //go:noescape func decompress4x_8b_main_loop_amd64(ctx *decompress4xContext) +// decompress4x_4b_main_loop_amd64 is an x86 assembler implementation +// of Decompress4X when tablelog <= 4, decoding fast4bSymbols symbols +// per stream between bit container reloads. +// +//go:noescape +func decompress4x_4b_main_loop_amd64(ctx *decompress4xContext) + +// decompress4x_4b_main_loop_bmi2 is the BMI2 twin of decompress4x_4b_main_loop_amd64. +// +//go:noescape +func decompress4x_4b_main_loop_bmi2(ctx *decompress4xContext) + +// decompress4x_main_loop_bmi2 is the BMI2 twin of decompress4x_main_loop_amd64. +// +//go:noescape +func decompress4x_main_loop_bmi2(ctx *decompress4xContext) + +// decompress4x_8b_main_loop_bmi2 is the BMI2 twin of decompress4x_8b_main_loop_amd64. +// +//go:noescape +func decompress4x_8b_main_loop_bmi2(ctx *decompress4xContext) + // decompress1x_main_loop_amd64 is an x86 assembler implementation -// of Decompress1X when tablelog > 8. +// of Decompress1X when tablelog > 8, decoding fastSymbols symbols +// between bit container reloads. // //go:noescape func decompress1x_main_loop_amd64(ctx *decompress1xContext) -// decompress1x_main_loop_bmi2 is an x86 with BMI2 assembler implementation -// of Decompress1X when tablelog > 8. +// decompress1x_8b_main_loop_amd64 is an x86 assembler implementation +// of Decompress1X when tablelog <= 8, decoding fast8bSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_8b_main_loop_amd64(ctx *decompress1xContext) + +// decompress1x_4b_main_loop_amd64 is an x86 assembler implementation +// of Decompress1X when tablelog <= 4, decoding fast4bSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_4b_main_loop_amd64(ctx *decompress1xContext) + +// decompress1x_main_loop_bmi2 is the BMI2 twin of decompress1x_main_loop_amd64. // //go:noescape func decompress1x_main_loop_bmi2(ctx *decompress1xContext) +// decompress1x_8b_main_loop_bmi2 is the BMI2 twin of decompress1x_8b_main_loop_amd64. +// +//go:noescape +func decompress1x_8b_main_loop_bmi2(ctx *decompress1xContext) + +// decompress1x_4b_main_loop_bmi2 is the BMI2 twin of decompress1x_4b_main_loop_amd64. +// +//go:noescape +func decompress1x_4b_main_loop_bmi2(ctx *decompress1xContext) + func decompress4x_main_loop_asm(ctx *decompress4xContext) { - decompress4x_main_loop_amd64(ctx) + if cpuinfo.HasBMI2() { + decompress4x_main_loop_bmi2(ctx) + } else { + decompress4x_main_loop_amd64(ctx) + } } func decompress4x_8b_main_loop_asm(ctx *decompress4xContext) { - decompress4x_8b_main_loop_amd64(ctx) + if cpuinfo.HasBMI2() { + decompress4x_8b_main_loop_bmi2(ctx) + } else { + decompress4x_8b_main_loop_amd64(ctx) + } +} + +func decompress4x_4b_main_loop_asm(ctx *decompress4xContext) { + if cpuinfo.HasBMI2() { + decompress4x_4b_main_loop_bmi2(ctx) + } else { + decompress4x_4b_main_loop_amd64(ctx) + } } func decompress1x_main_loop_asm(ctx *decompress1xContext) { @@ -47,3 +110,19 @@ func decompress1x_main_loop_asm(ctx *decompress1xContext) { decompress1x_main_loop_amd64(ctx) } } + +func decompress1x_8b_main_loop_asm(ctx *decompress1xContext) { + if cpuinfo.HasBMI2() { + decompress1x_8b_main_loop_bmi2(ctx) + } else { + decompress1x_8b_main_loop_amd64(ctx) + } +} + +func decompress1x_4b_main_loop_asm(ctx *decompress1xContext) { + if cpuinfo.HasBMI2() { + decompress1x_4b_main_loop_bmi2(ctx) + } else { + decompress1x_4b_main_loop_amd64(ctx) + } +} diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s index 920628c514..f072c18f04 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s @@ -3,828 +3,3384 @@ //go:build !appengine && !noasm && gc // func decompress4x_main_loop_amd64(ctx *decompress4xContext) +// Requires: BMI, CMOV TEXT ·decompress4x_main_loop_amd64(SB), $0-8 + MOVQ ctx+0(FP), AX + // Preload values - MOVQ ctx+0(FP), AX - MOVBQZX 8(AX), DI - MOVQ 16(AX), BX - MOVQ 48(AX), SI - MOVQ 24(AX), R8 - MOVQ 32(AX), R9 - MOVQ (AX), R10 + MOVBQZX 8(AX), DX + MOVQ 32(AX), BX + MOVQ 16(AX), SI + MOVQ 24(AX), CX + LEAQ (SI)(CX*1), R8 + LEAQ (SI)(CX*2), R10 + LEAQ (CX)(CX*2), R12 + ADDQ SI, R12 - // Main loop -main_loop: - XORL DX, DX - CMPQ BX, SI - SETGE DL + // Convert each bit reader to sentinel form: bits = value | 1<> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVW AX, (BX) - - // update the bitreader structure - MOVQ R11, 32(R10) - MOVB R12, 40(R10) - - // br1.fillFast32() - MOVQ 80(R10), R11 - MOVBQZX 88(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill1 - MOVQ 72(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 48(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 72(R10) - ORQ R13, R11 - - // exhausted += (br1.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill1: - // val0 := br1.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br1.advance(uint8(v0.entry) - MOVBLZX CH, AX + // stream 2, symbol 1 + MOVQ DX, CX + MOVQ R11, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX SHLQ CL, R11 - ADDB CL, R12 + SHRQ $0x08, CX + MOVB CL, 1(R10) - // val1 := br1.peekTopBits(peekBits) - MOVQ DI, CX - MOVQ R11, R13 - SHRQ CL, R13 + // stream 3, symbol 1 + MOVQ DX, CX + MOVQ R13, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, R13 + SHRQ $0x08, CX + MOVB CL, 1(R12) - // v1 := table[val1&mask] - MOVWQZX (R9)(R13*2), CX + // stream 0, symbol 2 + MOVQ DX, CX + MOVQ DI, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, DI + SHRQ $0x08, CX + MOVB CL, 2(SI) - // br1.advance(uint8(v1.entry)) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 + // stream 1, symbol 2 + MOVQ DX, CX + MOVQ R9, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, R9 + SHRQ $0x08, CX + MOVB CL, 2(R8) - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVW AX, (BX)(R8*1) - - // update the bitreader structure - MOVQ R11, 80(R10) - MOVB R12, 88(R10) - - // br2.fillFast32() - MOVQ 128(R10), R11 - MOVBQZX 136(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill2 - MOVQ 120(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 96(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 120(R10) - ORQ R13, R11 - - // exhausted += (br2.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill2: - // val0 := br2.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br2.advance(uint8(v0.entry) - MOVBLZX CH, AX + // stream 2, symbol 2 + MOVQ DX, CX + MOVQ R11, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX SHLQ CL, R11 - ADDB CL, R12 + SHRQ $0x08, CX + MOVB CL, 2(R10) - // val1 := br2.peekTopBits(peekBits) - MOVQ DI, CX - MOVQ R11, R13 - SHRQ CL, R13 + // stream 3, symbol 2 + MOVQ DX, CX + MOVQ R13, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, R13 + SHRQ $0x08, CX + MOVB CL, 2(R12) - // v1 := table[val1&mask] - MOVWQZX (R9)(R13*2), CX + // stream 0, symbol 3 + MOVQ DX, CX + MOVQ DI, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, DI + SHRQ $0x08, CX + MOVB CL, 3(SI) - // br2.advance(uint8(v1.entry)) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 + // stream 1, symbol 3 + MOVQ DX, CX + MOVQ R9, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, R9 + SHRQ $0x08, CX + MOVB CL, 3(R8) - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVW AX, (BX)(R8*2) - - // update the bitreader structure - MOVQ R11, 128(R10) - MOVB R12, 136(R10) - - // br3.fillFast32() - MOVQ 176(R10), R11 - MOVBQZX 184(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill3 - MOVQ 168(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 144(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 168(R10) - ORQ R13, R11 - - // exhausted += (br3.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill3: - // val0 := br3.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br3.advance(uint8(v0.entry) - MOVBLZX CH, AX + // stream 2, symbol 3 + MOVQ DX, CX + MOVQ R11, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX SHLQ CL, R11 - ADDB CL, R12 + SHRQ $0x08, CX + MOVB CL, 3(R10) - // val1 := br3.peekTopBits(peekBits) - MOVQ DI, CX - MOVQ R11, R13 - SHRQ CL, R13 + // stream 3, symbol 3 + MOVQ DX, CX + MOVQ R13, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, R13 + SHRQ $0x08, CX + MOVB CL, 3(R12) - // v1 := table[val1&mask] - MOVWQZX (R9)(R13*2), CX + // stream 0, symbol 4 + MOVQ DX, CX + MOVQ DI, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, DI + SHRQ $0x08, CX + MOVB CL, 4(SI) - // br3.advance(uint8(v1.entry)) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 + // stream 1, symbol 4 + MOVQ DX, CX + MOVQ R9, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, R9 + SHRQ $0x08, CX + MOVB CL, 4(R8) - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - LEAQ (R8)(R8*2), CX - MOVW AX, (BX)(CX*1) + // stream 2, symbol 4 + MOVQ DX, CX + MOVQ R11, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, R11 + SHRQ $0x08, CX + MOVB CL, 4(R10) - // update the bitreader structure - MOVQ R11, 176(R10) - MOVB R12, 184(R10) - ADDQ $0x02, BX - TESTB DL, DL - JZ main_loop - MOVQ ctx+0(FP), AX - SUBQ 16(AX), BX - SHLQ $0x02, BX - MOVQ BX, 40(AX) + // stream 3, symbol 4 + MOVQ DX, CX + MOVQ R13, R14 + SHRQ CL, R14 + MOVWQZX (BX)(R14*2), CX + SHLQ CL, R13 + SHRQ $0x08, CX + MOVB CL, 4(R12) + + // Reload the four bit containers + TZCNTQ DI, R14 + MOVQ R14, CX + ANDQ $0x07, CX + SHRQ $0x03, R14 + MOVQ 64(AX), DI + SUBQ R14, DI + MOVQ DI, 64(AX) + MOVQ (DI), DI + ORQ $0x01, DI + SHLQ CL, DI + TZCNTQ R9, R14 + MOVQ R14, CX + ANDQ $0x07, CX + SHRQ $0x03, R14 + MOVQ 72(AX), R9 + SUBQ R14, R9 + MOVQ R9, 72(AX) + MOVQ (R9), R9 + ORQ $0x01, R9 + SHLQ CL, R9 + TZCNTQ R11, R14 + MOVQ R14, CX + ANDQ $0x07, CX + SHRQ $0x03, R14 + MOVQ 80(AX), R11 + SUBQ R14, R11 + MOVQ R11, 80(AX) + MOVQ (R11), R11 + ORQ $0x01, R11 + SHLQ CL, R11 + TZCNTQ R13, R14 + MOVQ R14, CX + ANDQ $0x07, CX + SHRQ $0x03, R14 + MOVQ 88(AX), R13 + SUBQ R14, R13 + MOVQ R13, 88(AX) + MOVQ (R13), R13 + ORQ $0x01, R13 + SHLQ CL, R13 + ADDQ $0x05, SI + ADDQ $0x05, R8 + ADDQ $0x05, R10 + ADDQ $0x05, R12 + CMPQ SI, 96(AX) + JB inner_loop + JMP outer_loop + +done: + // Hand the state back: off = ip - in (negative when the window reached below the stream start), + // value = the sentinel-form container. bitReaderShifted.restoreFromAsm normalizes both. + MOVQ (AX), CX + MOVQ 64(AX), DX + SUBQ (CX), DX + MOVQ DX, 24(CX) + MOVQ DI, 32(CX) + MOVQ 72(AX), DX + SUBQ 48(CX), DX + MOVQ DX, 72(CX) + MOVQ R9, 80(CX) + MOVQ 80(AX), DX + SUBQ 96(CX), DX + MOVQ DX, 120(CX) + MOVQ R11, 128(CX) + MOVQ 88(AX), DX + SUBQ 144(CX), DX + MOVQ DX, 168(CX) + MOVQ R13, 176(CX) + SUBQ 16(AX), SI + SHLQ $0x02, SI + MOVQ SI, 40(AX) RET // func decompress4x_8b_main_loop_amd64(ctx *decompress4xContext) +// Requires: BMI, CMOV TEXT ·decompress4x_8b_main_loop_amd64(SB), $0-8 + MOVQ ctx+0(FP), AX + // Preload values - MOVQ ctx+0(FP), AX - MOVBQZX 8(AX), DI + MOVBQZX 8(AX), DX + MOVQ 32(AX), BX + MOVQ 16(AX), SI + MOVQ 24(AX), CX + LEAQ (SI)(CX*1), R8 + LEAQ (SI)(CX*2), R10 + LEAQ (CX)(CX*2), R12 + ADDQ SI, R12 + + // Convert each bit reader to sentinel form: bits = value | 1<> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - MOVL AX, (BX) - - // update the bitreader structure - MOVQ R11, 32(R10) - MOVB R12, 40(R10) - - // br1.fillFast32() - MOVQ 80(R10), R11 - MOVBQZX 88(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill1 - MOVQ 72(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 48(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 72(R10) - ORQ R13, R11 - - // exhausted += (br1.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill1: - // val0 := br1.peekTopBits(peekBits) - MOVQ R11, AX - MOVQ DI, CX - SHRQ CL, AX - - // v0 := table[val0&mask] - MOVWQZX (R9)(AX*2), CX - - // br1.advance(uint8(v0.entry) - MOVBLZX CH, AX - SHLQ CL, R11 - ADDB CL, R12 - - // val1 := br1.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v1 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br1.advance(uint8(v1.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // val2 := br1.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v2 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br1.advance(uint8(v2.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - - // val3 := br1.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v3 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br1.advance(uint8(v3.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // these four writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - MOVL AX, (BX)(R8*1) - - // update the bitreader structure - MOVQ R11, 80(R10) - MOVB R12, 88(R10) - - // br2.fillFast32() - MOVQ 128(R10), R11 - MOVBQZX 136(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill2 - MOVQ 120(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 96(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 120(R10) - ORQ R13, R11 - - // exhausted += (br2.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill2: - // val0 := br2.peekTopBits(peekBits) - MOVQ R11, AX - MOVQ DI, CX - SHRQ CL, AX - - // v0 := table[val0&mask] - MOVWQZX (R9)(AX*2), CX - - // br2.advance(uint8(v0.entry) - MOVBLZX CH, AX - SHLQ CL, R11 - ADDB CL, R12 - - // val1 := br2.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v1 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br2.advance(uint8(v1.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // val2 := br2.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v2 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br2.advance(uint8(v2.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - - // val3 := br2.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v3 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br2.advance(uint8(v3.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // these four writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - MOVL AX, (BX)(R8*2) - - // update the bitreader structure - MOVQ R11, 128(R10) - MOVB R12, 136(R10) - - // br3.fillFast32() - MOVQ 176(R10), R11 - MOVBQZX 184(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill3 - MOVQ 168(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 144(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 168(R10) - ORQ R13, R11 - - // exhausted += (br3.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill3: - // val0 := br3.peekTopBits(peekBits) - MOVQ R11, AX - MOVQ DI, CX - SHRQ CL, AX - - // v0 := table[val0&mask] - MOVWQZX (R9)(AX*2), CX - - // br3.advance(uint8(v0.entry) - MOVBLZX CH, AX - SHLQ CL, R11 - ADDB CL, R12 - - // val1 := br3.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v1 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br3.advance(uint8(v1.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // val2 := br3.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v2 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br3.advance(uint8(v2.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - - // val3 := br3.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v3 := table[val0&mask] - MOVWQZX (R9)(R13*2), CX - - // br3.advance(uint8(v3.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // these four writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - LEAQ (R8)(R8*2), CX - MOVL AX, (BX)(CX*1) - - // update the bitreader structure - MOVQ R11, 176(R10) - MOVB R12, 184(R10) - ADDQ $0x04, BX - TESTB DL, DL - JZ main_loop - MOVQ ctx+0(FP), AX - SUBQ 16(AX), BX - SHLQ $0x02, BX - MOVQ BX, 40(AX) + MOVQ 24(AX), SI + LEAQ (BX)(SI*1), DI + LEAQ (BX)(SI*2), R9 + LEAQ (SI)(SI*2), R11 + ADDQ BX, R11 + + // Convert each bit reader to sentinel form: bits = value | 1< 8. +// of Decompress4X when tablelog > 8, decoding fastSymbols symbols per +// stream between bit container reloads. // //go:noescape func decompress4x_main_loop_arm64(ctx *decompress4xContext) // decompress4x_8b_main_loop_arm64 is an arm64 assembler implementation -// of Decompress4X when tablelog <= 8 which decodes 4 entries -// per loop. +// of Decompress4X when tablelog <= 8, decoding fast8bSymbols symbols +// per stream between bit container reloads. // //go:noescape func decompress4x_8b_main_loop_arm64(ctx *decompress4xContext) +// decompress4x_4b_main_loop_arm64 is an arm64 assembler implementation +// of Decompress4X when tablelog <= 4, decoding fast4bSymbols symbols +// per stream between bit container reloads. +// +//go:noescape +func decompress4x_4b_main_loop_arm64(ctx *decompress4xContext) + // decompress1x_main_loop_arm64 is an arm64 assembler implementation -// of Decompress1X when tablelog > 8. +// of Decompress1X when tablelog > 8, decoding fastSymbols symbols +// between bit container reloads. // //go:noescape func decompress1x_main_loop_arm64(ctx *decompress1xContext) +// decompress1x_8b_main_loop_arm64 is an arm64 assembler implementation +// of Decompress1X when tablelog <= 8, decoding fast8bSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_8b_main_loop_arm64(ctx *decompress1xContext) + +// decompress1x_4b_main_loop_arm64 is an arm64 assembler implementation +// of Decompress1X when tablelog <= 4, decoding fast4bSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_4b_main_loop_arm64(ctx *decompress1xContext) + func decompress4x_main_loop_asm(ctx *decompress4xContext) { decompress4x_main_loop_arm64(ctx) } @@ -32,6 +55,18 @@ func decompress4x_8b_main_loop_asm(ctx *decompress4xContext) { decompress4x_8b_main_loop_arm64(ctx) } +func decompress4x_4b_main_loop_asm(ctx *decompress4xContext) { + decompress4x_4b_main_loop_arm64(ctx) +} + func decompress1x_main_loop_asm(ctx *decompress1xContext) { decompress1x_main_loop_arm64(ctx) } + +func decompress1x_8b_main_loop_asm(ctx *decompress1xContext) { + decompress1x_8b_main_loop_arm64(ctx) +} + +func decompress1x_4b_main_loop_asm(ctx *decompress1xContext) { + decompress1x_4b_main_loop_arm64(ctx) +} diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s b/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s index 357df28e9d..971b8eb8bd 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s +++ b/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s @@ -4,793 +4,1654 @@ //go:build arm64 && (!appengine && !noasm && gc) // func decompress4x_main_loop_amd64(ctx *decompress4xContext) +// Requires: BMI, CMOV TEXT ·decompress4x_main_loop_arm64(SB), $0-8 - // Preload values - MOVD ctx+0(FP), R0 - MOVBU 8(R0), R6 - MOVD 16(R0), R3 - MOVD 48(R0), R5 - MOVD 24(R0), R7 - MOVD 32(R0), R8 - MOVD (R0), R9 - - // Main loop -main_loop: - MOVD $0, R2 - CMP R5, R3 - CSET GE, R16 - BFI $0, R16, $8, R2 - - // br0.fillFast32() - MOVD 32(R9), R10 - MOVBU 40(R9), R11 - CMP $0x20, R11 - BLS skip_fill0 - MOVD 24(R9), R0 - SUB $0x20, R11, R11 - SUB $0x04, R0, R0 - MOVD (R9), R12 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVWU (R0)(R12), R12 - MOVD R11, R1 - LSL R1, R12, R12 - MOVD R0, 24(R9) - ORR R12, R10, R10 - - // exhausted += (br0.off < 4) - CMP $0x04, R0 - CSINC HS, R2, R2, R16 - BFI $0, R16, $8, R2 - -skip_fill0: - // val0 := br0.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v0 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br0.advance(uint8(v0.entry) - UBFX $8, R1, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val1 := br0.peekTopBits(peekBits) - MOVD R6, R1 - MOVD R10, R12 - LSR R1, R12, R12 - - // v1 := table[val1&mask] - MOVHU (R8)(R12<<1), R1 - - // br0.advance(uint8(v1.entry)) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVH R0, (R3) - - // update the bitreader structure - MOVD R10, 32(R9) - MOVB R11, 40(R9) - - // br1.fillFast32() - MOVD 80(R9), R10 - MOVBU 88(R9), R11 - CMP $0x20, R11 - BLS skip_fill1 - MOVD 72(R9), R0 - SUB $0x20, R11, R11 - SUB $0x04, R0, R0 - MOVD 48(R9), R12 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVWU (R0)(R12), R12 - MOVD R11, R1 - LSL R1, R12, R12 - MOVD R0, 72(R9) - ORR R12, R10, R10 - - // exhausted += (br1.off < 4) - CMP $0x04, R0 - CSINC HS, R2, R2, R16 - BFI $0, R16, $8, R2 - -skip_fill1: - // val0 := br1.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v0 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br1.advance(uint8(v0.entry) - UBFX $8, R1, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val1 := br1.peekTopBits(peekBits) - MOVD R6, R1 - MOVD R10, R12 - LSR R1, R12, R12 - - // v1 := table[val1&mask] - MOVHU (R8)(R12<<1), R1 - - // br1.advance(uint8(v1.entry)) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVH R0, (R3)(R7) - - // update the bitreader structure - MOVD R10, 80(R9) - MOVB R11, 88(R9) - - // br2.fillFast32() - MOVD 128(R9), R10 - MOVBU 136(R9), R11 - CMP $0x20, R11 - BLS skip_fill2 - MOVD 120(R9), R0 - SUB $0x20, R11, R11 - SUB $0x04, R0, R0 - MOVD 96(R9), R12 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVWU (R0)(R12), R12 - MOVD R11, R1 - LSL R1, R12, R12 - MOVD R0, 120(R9) - ORR R12, R10, R10 - - // exhausted += (br2.off < 4) - CMP $0x04, R0 - CSINC HS, R2, R2, R16 - BFI $0, R16, $8, R2 - -skip_fill2: - // val0 := br2.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v0 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br2.advance(uint8(v0.entry) - UBFX $8, R1, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val1 := br2.peekTopBits(peekBits) - MOVD R6, R1 - MOVD R10, R12 - LSR R1, R12, R12 - - // v1 := table[val1&mask] - MOVHU (R8)(R12<<1), R1 - - // br2.advance(uint8(v1.entry)) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVH R0, (R3)(R7<<1) - - // update the bitreader structure - MOVD R10, 128(R9) - MOVB R11, 136(R9) - - // br3.fillFast32() - MOVD 176(R9), R10 - MOVBU 184(R9), R11 - CMP $0x20, R11 - BLS skip_fill3 - MOVD 168(R9), R0 - SUB $0x20, R11, R11 - SUB $0x04, R0, R0 - MOVD 144(R9), R12 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVWU (R0)(R12), R12 - MOVD R11, R1 - LSL R1, R12, R12 - MOVD R0, 168(R9) - ORR R12, R10, R10 - - // exhausted += (br3.off < 4) - CMP $0x04, R0 - CSINC HS, R2, R2, R16 - BFI $0, R16, $8, R2 - -skip_fill3: - // val0 := br3.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v0 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br3.advance(uint8(v0.entry) - UBFX $8, R1, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val1 := br3.peekTopBits(peekBits) - MOVD R6, R1 - MOVD R10, R12 - LSR R1, R12, R12 - - // v1 := table[val1&mask] - MOVHU (R8)(R12<<1), R1 - - // br3.advance(uint8(v1.entry)) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - ADD R7<<1, R7, R1 - MOVH R0, (R3)(R1) - - // update the bitreader structure - MOVD R10, 176(R9) - MOVB R11, 184(R9) - ADD $0x02, R3, R3 - TST $0xff, R2 - BEQ main_loop MOVD ctx+0(FP), R0 + + // Preload values + MOVBU 8(R0), R2 + MOVD 32(R0), R3 + MOVD 16(R0), R5 + MOVD 24(R0), R1 + ADD R1, R5, R7 + ADD R1<<1, R5, R9 + ADD R1<<1, R1, R11 + ADD R5, R11, R11 + + // Convert each bit reader to sentinel form: bits = value | 1<> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - MOVW R0, (R3) - - // update the bitreader structure - MOVD R10, 32(R9) - MOVB R11, 40(R9) - - // br1.fillFast32() - MOVD 80(R9), R10 - MOVBU 88(R9), R11 - CMP $0x20, R11 - BLS skip_fill1 - MOVD 72(R9), R0 - SUB $0x20, R11, R11 - SUB $0x04, R0, R0 - MOVD 48(R9), R12 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVWU (R0)(R12), R12 - MOVD R11, R1 - LSL R1, R12, R12 - MOVD R0, 72(R9) - ORR R12, R10, R10 - - // exhausted += (br1.off < 4) - CMP $0x04, R0 - CSINC HS, R2, R2, R16 - BFI $0, R16, $8, R2 - -skip_fill1: - // val0 := br1.peekTopBits(peekBits) - MOVD R10, R0 - MOVD R6, R1 - LSR R1, R0, R0 - - // v0 := table[val0&mask] - MOVHU (R8)(R0<<1), R1 - - // br1.advance(uint8(v0.entry) - UBFX $8, R1, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val1 := br1.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v1 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br1.advance(uint8(v1.entry) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - REVW R0, R0 - - // val2 := br1.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v2 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br1.advance(uint8(v2.entry) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val3 := br1.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v3 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br1.advance(uint8(v3.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - REVW R0, R0 - - // these four writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - MOVW R0, (R3)(R7) - - // update the bitreader structure - MOVD R10, 80(R9) - MOVB R11, 88(R9) - - // br2.fillFast32() - MOVD 128(R9), R10 - MOVBU 136(R9), R11 - CMP $0x20, R11 - BLS skip_fill2 - MOVD 120(R9), R0 - SUB $0x20, R11, R11 - SUB $0x04, R0, R0 - MOVD 96(R9), R12 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVWU (R0)(R12), R12 - MOVD R11, R1 - LSL R1, R12, R12 - MOVD R0, 120(R9) - ORR R12, R10, R10 - - // exhausted += (br2.off < 4) - CMP $0x04, R0 - CSINC HS, R2, R2, R16 - BFI $0, R16, $8, R2 - -skip_fill2: - // val0 := br2.peekTopBits(peekBits) - MOVD R10, R0 - MOVD R6, R1 - LSR R1, R0, R0 - - // v0 := table[val0&mask] - MOVHU (R8)(R0<<1), R1 - - // br2.advance(uint8(v0.entry) - UBFX $8, R1, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val1 := br2.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v1 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br2.advance(uint8(v1.entry) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - REVW R0, R0 - - // val2 := br2.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v2 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br2.advance(uint8(v2.entry) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val3 := br2.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v3 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br2.advance(uint8(v3.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - REVW R0, R0 - - // these four writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - ADD R7<<1, R3, R15 - MOVW R0, (R15) - - // update the bitreader structure - MOVD R10, 128(R9) - MOVB R11, 136(R9) - - // br3.fillFast32() - MOVD 176(R9), R10 - MOVBU 184(R9), R11 - CMP $0x20, R11 - BLS skip_fill3 - MOVD 168(R9), R0 - SUB $0x20, R11, R11 - SUB $0x04, R0, R0 - MOVD 144(R9), R12 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVWU (R0)(R12), R12 - MOVD R11, R1 - LSL R1, R12, R12 - MOVD R0, 168(R9) - ORR R12, R10, R10 - - // exhausted += (br3.off < 4) - CMP $0x04, R0 - CSINC HS, R2, R2, R16 - BFI $0, R16, $8, R2 - -skip_fill3: - // val0 := br3.peekTopBits(peekBits) - MOVD R10, R0 - MOVD R6, R1 - LSR R1, R0, R0 - - // v0 := table[val0&mask] - MOVHU (R8)(R0<<1), R1 - - // br3.advance(uint8(v0.entry) - UBFX $8, R1, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val1 := br3.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v1 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br3.advance(uint8(v1.entry) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - REVW R0, R0 - - // val2 := br3.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v2 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br3.advance(uint8(v2.entry) - UBFX $8, R1, $8, R16 - BFI $8, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - - // val3 := br3.peekTopBits(peekBits) - MOVD R10, R12 - MOVD R6, R1 - LSR R1, R12, R12 - - // v3 := table[val0&mask] - MOVHU (R8)(R12<<1), R1 - - // br3.advance(uint8(v3.entry) - UBFX $8, R1, $8, R16 - BFI $0, R16, $8, R0 - LSL R1, R10, R10 - ADD R1, R11, R15 - BFI $0, R15, $8, R11 - REVW R0, R0 - - // these four writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - ADD R7<<1, R7, R1 - MOVW R0, (R3)(R1) - - // update the bitreader structure - MOVD R10, 176(R9) - MOVB R11, 184(R9) - ADD $0x04, R3, R3 - TST $0xff, R2 - BEQ main_loop MOVD ctx+0(FP), R0 + + // Preload values + MOVBU 8(R0), R2 + MOVD 32(R0), R3 + MOVD 16(R0), R5 + MOVD 24(R0), R1 + ADD R1, R5, R7 + ADD R1<<1, R5, R9 + ADD R1<<1, R1, R11 + ADD R5, R11, R11 + + // Convert each bit reader to sentinel form: bits = value | 1< 4*4 && !(br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4) { + nSyms := fastSymbols + if d.actualTableLog <= 4 { + nSyms = fast4bSymbols + } else if use8BitTables { + nSyms = fast8bSymbols + } + // The asm writes nSyms bytes per stream per iteration and only re-checks + // its bounds between batches of iterations (the batch size is derived + // from limit in _generate/gen.go), so stream 0 must stop early enough + // that stream 3 (which may be up to 3 bytes shorter than dstEvery) + // never writes past the end of out. Every stream needs a full 8-byte + // window ahead of its read pointer to enter the loop. + if limit := dstEvery - nSyms - 2; limit > 0 && br[0].canUseAsm() && br[1].canUseAsm() && br[2].canUseAsm() && br[3].canUseAsm() { + for i := range br { + br[i].prepareForAsm() + } ctx := decompress4xContext{ pbr: &br, peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast() out: &out[0], dstEvery: dstEvery, tbl: &single[0], - limit: &out[dstEvery-4], // Always stop decoding when first buffer gets here to avoid writing OOB on last. + limit: &out[limit], + // The 6-byte jump table sits below stream 0 inside src, so the + // lowest window may reach into it; restoreFromAsm accounts for + // bytes below a stream's start. Bounding by src rather than by + // stream 0 keeps the asm running about six bytes longer, which + // matters for streams with very short codes. + ilowest: &src[0], } - if use8BitTables { + for i := range br { + ctx.ip[i] = &br[i].in[br[i].off] + } + switch nSyms { + case fast4bSymbols: + decompress4x_4b_main_loop_asm(&ctx) + case fast8bSymbols: decompress4x_8b_main_loop_asm(&ctx) - } else { + default: decompress4x_main_loop_asm(&ctx) } decoded = ctx.decoded out = out[decoded/4:] + for i := range br { + if err := br[i].restoreFromAsm(); err != nil { + return nil, err + } + } } // Decode remaining. @@ -128,18 +175,20 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { return dst, nil } +// decompress1xContext is the argument block of the Decompress1X asm loops. +// Go fills every field but decoded; the asm advances ip, and on return +// leaves the bit reader in the form bitReaderShifted.restoreFromAsm expects. type decompress1xContext struct { pbr *bitReaderShifted peekBits uint8 out *byte - outCap int + outCap int // no write reaches out[outCap] tbl *dEntrySingle decoded int + ilowest *byte // start of the stream; no read goes below it + ip *byte // the 8-byte input window, advanced by the asm } -// Error reported by asm implementations -const error_max_decoded_size_exeeded = -1 - // Decompress1X will decompress a 1X encoded stream. // The cap of the output buffer will be the maximum decompressed size. // The length of the supplied input must match the end of a block exactly. @@ -158,25 +207,36 @@ func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) { const tlSize = 1 << tableLogMax const tlMask = tlSize - 1 - if maxDecodedSize >= 4 { + // The asm decodes whole batches of symbols and only re-checks its + // bounds between them, so it needs at least one batch of room (the + // output bound rounds nSyms up to 16, see _generate/gen.go) and a full + // 8-byte window ahead of the read pointer to enter the loop. It also + // needs at most 7 bits consumed on entry so that a batch cannot run + // the container dry, which prepareForAsm establishes. + decoded := 0 + if maxDecodedSize >= 16 && br.canUseAsm() { + br.prepareForAsm() ctx := decompress1xContext{ pbr: &br, out: &dst[0], outCap: maxDecodedSize, peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast() tbl: &d.dt.single[0], + ilowest: &src[0], + ip: &br.in[br.off], } - - decompress1x_main_loop_asm(&ctx) - if ctx.decoded == error_max_decoded_size_exeeded { - return nil, ErrMaxDecodedSizeExceeded + if d.actualTableLog <= 4 { + decompress1x_4b_main_loop_asm(&ctx) + } else if d.actualTableLog <= 8 { + decompress1x_8b_main_loop_asm(&ctx) + } else { + decompress1x_main_loop_asm(&ctx) } - - dst = dst[:ctx.decoded] + decoded = ctx.decoded } + dst = dst[:decoded] - // br < 8, so uint8 is fine - bitsLeft := uint8(br.off)*8 + 64 - br.bitsRead + bitsLeft := br.remaining() for bitsLeft > 0 { br.fill() if len(dst) >= maxDecodedSize { @@ -186,7 +246,7 @@ func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) { v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask] nBits := uint8(v.entry) br.advance(nBits) - bitsLeft -= nBits + bitsLeft -= uint(nBits) dst = append(dst, uint8(v.entry>>8)) } return dst, br.close() diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go index 51f9da0387..89b20d6a84 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockdec.go +++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -240,9 +240,11 @@ func (b *blockDec) decodeBuf(hist *history) error { b.dst[i] = v } hist.appendKeep(b.dst) + hist.decoders.consumeSyncLen(len(b.dst)) return nil case blockTypeRaw: hist.appendKeep(b.data) + hist.decoders.consumeSyncLen(len(b.data)) return nil case blockTypeCompressed: saved := b.dst @@ -487,6 +489,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { } if hist.decoders.nSeqs == 0 { b.dst = append(b.dst, hist.decoders.literals...) + hist.decoders.consumeSyncLen(len(hist.decoders.literals)) return nil } before := len(hist.decoders.out) diff --git a/vendor/github.com/klauspost/compress/zstd/decoder.go b/vendor/github.com/klauspost/compress/zstd/decoder.go index c7e500f02a..90ef3bb03f 100644 --- a/vendor/github.com/klauspost/compress/zstd/decoder.go +++ b/vendor/github.com/klauspost/compress/zstd/decoder.go @@ -7,8 +7,11 @@ package zstd import ( "context" "encoding/binary" + "errors" "io" + "maps" "sync" + "sync/atomic" "github.com/klauspost/compress/zstd/internal/xxhash" ) @@ -20,7 +23,8 @@ import ( // A decoder can safely be re-used even if the previous stream failed. // To release the resources, you must call the Close() function on a decoder. type Decoder struct { - o decoderOptions + // publishedOptions contains the current immutable decoder options. + publishedOptions atomic.Pointer[decoderOptions] // Unreferenced decoders, ready for use. decoders chan *blockDec @@ -84,9 +88,10 @@ var ( func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) { initPredefined() var d Decoder - d.o.setDefault() - for _, o := range opts { - err := o(&d.o) + var o decoderOptions + o.setDefault() + for _, opt := range opts { + err := opt(&o) if err != nil { return nil, err } @@ -99,17 +104,19 @@ func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) { } // Initialize dict map if needed. - if d.o.dicts == nil { - d.o.dicts = make(map[uint32]*dict) + if o.dicts == nil { + o.dicts = make(map[uint32]*dict) } // Create decoders - d.decoders = make(chan *blockDec, d.o.concurrent) - for i := 0; i < d.o.concurrent; i++ { - dec := newBlockDec(d.o.lowMem) - dec.localFrame = newFrameDec(d.o) + d.decoders = make(chan *blockDec, o.concurrent) + for i := 0; i < o.concurrent; i++ { + dec := newBlockDec(o.lowMem) + dec.localFrame = newFrameDec(o) + dec.localFrame.o.dicts = nil d.decoders <- dec } + d.publishedOptions.Store(&o) if r == nil { return &d, nil @@ -171,6 +178,9 @@ func (d *Decoder) Reset(r io.Reader) error { d.drainOutput() d.syncStream.br.r = nil + if d.frame != nil { + d.frame.o.dicts = nil + } if r == nil { d.current.err = ErrDecoderNilInput if len(d.current.b) > 0 { @@ -180,8 +190,10 @@ func (d *Decoder) Reset(r io.Reader) error { return nil } + o := *d.publishedOptions.Load() + // If bytes buffer and < 5MB, do sync decoding anyway. - if bb, ok := r.(byter); ok && bb.Len() < d.o.decodeBufsBelow && !d.o.limitToCap { + if bb, ok := r.(byter); ok && bb.Len() < o.decodeBufsBelow && !o.limitToCap { bb2 := bb if debugDecoder { println("*bytes.Buffer detected, doing sync decode, len:", bb.Len()) @@ -193,18 +205,30 @@ func (d *Decoder) Reset(r io.Reader) error { } dst, err := d.DecodeAll(b, dst) - if err == nil { - err = io.EOF + if !errors.Is(err, ErrDecoderSizeExceeded) { + if err == nil { + err = io.EOF + } + // Save output buffer + d.syncStream.dstBuf = dst + d.current.b = dst + d.current.err = err + d.current.flushed = true + if debugDecoder { + println("sync decode to", len(dst), "bytes, err:", err) + } + return nil } - // Save output buffer - d.syncStream.dstBuf = dst - d.current.b = dst - d.current.err = err - d.current.flushed = true + // The output does not fit WithDecoderMaxMemory, which caps the total + // decoded size when decoding in memory. A Reader follows the + // streaming contract, where the option caps the window instead, so + // decode this input as a stream after all; the shortcut has not + // consumed the reader. Drop the oversized buffer rather than keep it + // for reuse. if debugDecoder { - println("sync decode to", len(dst), "bytes, err:", err) + println("sync decode exceeded max memory after", len(dst), "bytes; streaming instead") } - return nil + d.syncStream.dstBuf = nil } // Remove current block. d.stashDecoder() @@ -217,14 +241,16 @@ func (d *Decoder) Reset(r io.Reader) error { // Ensure no-one else is still running... d.streamWg.Wait() if d.frame == nil { - d.frame = newFrameDec(d.o) + d.frame = newFrameDec(o) + } else { + d.frame.setOptions(o) } - if d.o.concurrent == 1 { + if o.concurrent == 1 { return d.startSyncDecoder(r) } - d.current.output = make(chan decodeOutput, d.o.concurrent) + d.current.output = make(chan decodeOutput, o.concurrent) ctx, cancel := context.WithCancel(context.Background()) d.current.cancel = cancel d.streamWg.Add(1) @@ -238,13 +264,21 @@ func (d *Decoder) Reset(r io.Reader) error { // Options are applied on top of the existing options. // Some options cannot be changed on reset and will return an error. func (d *Decoder) ResetWithOptions(r io.Reader, opts ...DOption) error { - d.o.resetOpt = true - defer func() { d.o.resetOpt = false }() + if d.current.err == ErrDecoderClosed { + return d.current.err + } + next := *d.publishedOptions.Load() + next.dicts = maps.Clone(next.dicts) + next.resetOpt = true for _, o := range opts { - if err := o(&d.o); err != nil { + if err := o(&next); err != nil { + next.resetOpt = false + d.publishedOptions.Store(&next) return err } } + next.resetOpt = false + d.publishedOptions.Store(&next) return d.Reset(r) } @@ -324,6 +358,8 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { // Grab a block decoder and frame decoder. block := <-d.decoders frame := block.localFrame + o := *d.publishedOptions.Load() + frame.setOptions(o) initialSize := len(dst) defer func() { if debugDecoder { @@ -335,6 +371,7 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { frame.history.decoders.br.in = nil frame.history.decoders.br.cursor = 0 } + frame.o.dicts = nil d.decoders <- block }() frame.bBuf = input @@ -354,20 +391,20 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { if err = d.setDict(frame); err != nil { return nil, err } - if frame.WindowSize > d.o.maxWindowSize { + if frame.WindowSize > frame.o.maxWindowSize { if debugDecoder { - println("window size exceeded:", frame.WindowSize, ">", d.o.maxWindowSize) + println("window size exceeded:", frame.WindowSize, ">", frame.o.maxWindowSize) } return dst, ErrWindowSizeExceeded } if frame.FrameContentSize != fcsUnknown { - if frame.FrameContentSize > d.o.maxDecodedSize-uint64(len(dst)-initialSize) { + if frame.FrameContentSize > frame.o.maxDecodedSize-uint64(len(dst)-initialSize) { if debugDecoder { - println("decoder size exceeded; fcs:", frame.FrameContentSize, "> mcs:", d.o.maxDecodedSize-uint64(len(dst)-initialSize), "len:", len(dst)) + println("decoder size exceeded; fcs:", frame.FrameContentSize, "> mcs:", frame.o.maxDecodedSize-uint64(len(dst)-initialSize), "len:", len(dst)) } return dst, ErrDecoderSizeExceeded } - if d.o.limitToCap && frame.FrameContentSize > uint64(cap(dst)-len(dst)) { + if frame.o.limitToCap && frame.FrameContentSize > uint64(cap(dst)-len(dst)) { if debugDecoder { println("decoder size exceeded; fcs:", frame.FrameContentSize, "> (cap-len)", cap(dst)-len(dst)) } @@ -380,14 +417,14 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { } } - if cap(dst) == 0 && !d.o.limitToCap { + if cap(dst) == 0 && !frame.o.limitToCap { // Allocate len(input) * 2 by default if nothing is provided // and we didn't get frame content size. size := min( // Cap to 1 MB. len(input)*2, 1<<20) - if uint64(size) > d.o.maxDecodedSize { - size = int(d.o.maxDecodedSize) + if uint64(size) > frame.o.maxDecodedSize { + size = int(frame.o.maxDecodedSize) } dst = make([]byte, 0, size) } @@ -396,7 +433,7 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { if err != nil { return dst, err } - if uint64(len(dst)-initialSize) > d.o.maxDecodedSize { + if uint64(len(dst)-initialSize) > frame.o.maxDecodedSize { return dst, ErrDecoderSizeExceeded } if len(frame.bBuf) == 0 { @@ -459,7 +496,7 @@ func (d *Decoder) nextBlock(blocking bool) (ok bool) { println("got", len(d.current.b), "bytes, error:", d.current.err, "data crc:", tmp) } - if d.o.ignoreChecksum { + if d.frame.o.ignoreChecksum { return true } @@ -497,7 +534,7 @@ func (d *Decoder) nextBlockSync() (ok bool) { if d.current.err != nil { return false } - if d.frame.WindowSize > d.o.maxDecodedSize || d.frame.WindowSize > d.o.maxWindowSize { + if d.frame.WindowSize > d.frame.o.maxDecodedSize || d.frame.WindowSize > d.frame.o.maxWindowSize { d.current.err = ErrDecoderSizeExceeded return false } @@ -546,11 +583,11 @@ func (d *Decoder) nextBlockSync() (ok bool) { // Update/Check CRC if d.frame.HasCheckSum { - if !d.o.ignoreChecksum { + if !d.frame.o.ignoreChecksum { d.frame.crc.Write(d.current.b) } if d.current.d.Last { - if !d.o.ignoreChecksum { + if !d.frame.o.ignoreChecksum { d.current.err = d.frame.checkCRC() } else { d.current.err = d.frame.consumeCRC() @@ -656,8 +693,8 @@ func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output ch defer d.streamWg.Done() br := readerWrapper{r: r} - var seqDecode = make(chan *blockDec, d.o.concurrent) - var seqExecute = make(chan *blockDec, d.o.concurrent) + var seqDecode = make(chan *blockDec, d.frame.o.concurrent) + var seqExecute = make(chan *blockDec, d.frame.o.concurrent) // Async 1: Decode sequences... go func() { @@ -858,9 +895,9 @@ decodeStream: if err == nil { err = d.setDict(frame) } - if err == nil && d.frame.WindowSize > d.o.maxWindowSize { + if err == nil && d.frame.WindowSize > d.frame.o.maxWindowSize { if debugDecoder { - println("decoder size exceeded, fws:", d.frame.WindowSize, "> mws:", d.o.maxWindowSize) + println("decoder size exceeded, fws:", d.frame.WindowSize, "> mws:", d.frame.o.maxWindowSize) } err = ErrDecoderSizeExceeded @@ -940,7 +977,7 @@ decodeStream: } func (d *Decoder) setDict(frame *frameDec) (err error) { - dict, ok := d.o.dicts[frame.DictionaryID] + dict, ok := frame.o.dicts[frame.DictionaryID] if ok { if debugDecoder { println("setting dict", frame.DictionaryID) diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go index d88f067e5c..81d8b9c922 100644 --- a/vendor/github.com/klauspost/compress/zstd/framedec.go +++ b/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -49,13 +49,16 @@ const ( ) func newFrameDec(o decoderOptions) *frameDec { + d := frameDec{} + d.setOptions(o) + return &d +} + +func (d *frameDec) setOptions(o decoderOptions) { if o.maxWindowSize > o.maxDecodedSize { o.maxWindowSize = o.maxDecodedSize } - d := frameDec{ - o: o, - } - return &d + d.o = o } // reset will read the frame header and prepare for block decoding. diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s b/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s index b6b4607878..8ca913eaec 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s @@ -47,12 +47,10 @@ init_main_loop_condition: // Spread symbols // Calculate table step - MOVD R0, R8 - LSR $0x01, R8, R8 - MOVD R0, R9 - LSR $0x03, R9, R9 - ADD R9, R8, R8 - ADD $3, R8, R8 + LSR $0x01, R0, R8 + LSR $0x03, R0, R9 + ADD R9, R8, R8 + ADD $3, R8, R8 // Fill add bits values SUB $1, R0, R9 diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec.go b/vendor/github.com/klauspost/compress/zstd/seqdec.go index 0bfb0e43c7..d1a7732fcc 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec.go @@ -99,6 +99,29 @@ func (s *sequenceDecs) initialize(br *bitReader, hist *history, out []byte) erro return nil } +// consumeSyncLen accounts for n bytes of frame output produced outside +// decodeSync. maxSyncLen bounds how much the frame may still produce and +// decodeSyncSimple compares it with the output buffer's slack to decide +// whether the extended 16-byte copies are safe. Blocks with sequences +// subtracted their output; raw blocks, RLE blocks and compressed blocks +// holding only literals did not, so a frame that opened with a raw block +// overstated its remaining size for every block after it and ran the +// bounds-exact copies for the rest of the frame. +// +// Zero means "no bound" and selects the conservative paths, so a block that +// meets or exceeds the bound lands there; the frame-size checks in +// runDecoder reject the excess afterwards. +func (s *sequenceDecs) consumeSyncLen(n int) { + if s.maxSyncLen == 0 { + return + } + if uint64(n) >= s.maxSyncLen { + s.maxSyncLen = 0 + return + } + s.maxSyncLen -= uint64(n) +} + func (s *sequenceDecs) freeDecoders() { if f := s.litLengths.fse; f != nil && !f.preDefined { fseDecoderPool.Put(f) diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s index 9c4f8d3528..798d940231 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s @@ -4,7 +4,7 @@ // func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV -TEXT ·sequenceDecs_decode_amd64(SB), $8-32 +TEXT ·sequenceDecs_decode_amd64(SB), $40-32 MOVQ br+8(FP), CX MOVQ 24(CX), DX MOVBQZX 40(CX), BX @@ -16,6 +16,14 @@ TEXT ·sequenceDecs_decode_amd64(SB), $8-32 MOVQ 72(AX), DI MOVQ 80(AX), R8 MOVQ 88(AX), R9 + MOVQ (AX), CX + MOVQ CX, 8(SP) + MOVQ 24(AX), CX + MOVQ CX, 16(SP) + MOVQ 48(AX), CX + MOVQ CX, 24(SP) + MOVQ 96(AX), CX + MOVQ CX, 32(SP) MOVQ 104(AX), R10 MOVQ s+0(FP), AX MOVQ 144(AX), R11 @@ -59,42 +67,28 @@ sequenceDecs_decode_amd64_fill_end: MOVQ BX, CX MOVQ DX, R15 SHLQ CL, R15 + SHRQ $0x01, R15 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_of_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_of_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R15 ADDQ R15, AX - -sequenceDecs_decode_amd64_of_update_zero: - MOVQ AX, 16(R10) + MOVQ AX, 16(R10) // Update match length MOVQ R8, AX MOVQ BX, CX MOVQ DX, R15 SHLQ CL, R15 + SHRQ $0x01, R15 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_ml_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_ml_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R15 ADDQ R15, AX - -sequenceDecs_decode_amd64_ml_update_zero: - MOVQ AX, 8(R10) + MOVQ AX, 8(R10) // Fill bitreader to have enough for the remaining CMPQ SI, $0x08 @@ -130,86 +124,72 @@ sequenceDecs_decode_amd64_fill_2_end: MOVQ BX, CX MOVQ DX, R15 SHLQ CL, R15 + SHRQ $0x01, R15 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_ll_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_ll_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R15 ADDQ R15, AX - -sequenceDecs_decode_amd64_ll_update_zero: - MOVQ AX, (R10) + MOVQ AX, (R10) // Fill bitreader for state updates MOVQ R14, (SP) MOVQ R9, AX SHRQ $0x08, AX MOVBQZX AL, AX - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decode_amd64_skip_update // Update Literal Length State MOVBQZX DI, R14 SHRL $0x10, DI - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVBLZX R14, CX - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, DI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(DI*8), DI // Update Match Length State MOVBQZX R8, R14 SHRL $0x10, R8 - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVBLZX R14, CX - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, R8 // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(R8*8), R8 // Update Offset State MOVBQZX R9, R14 SHRL $0x10, R9 - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVBLZX R14, CX - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, R9 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R9*8), R9 sequenceDecs_decode_amd64_skip_update: @@ -290,8 +270,7 @@ sequenceDecs_decode_amd64_after_adjust: sequenceDecs_decode_amd64_match_len_ofs_ok: ADDQ $0x18, R10 - MOVQ ctx+16(FP), AX - DECQ 96(AX) + DECQ 32(SP) JNS sequenceDecs_decode_amd64_main_loop MOVQ s+0(FP), AX MOVQ R11, 144(AX) @@ -303,36 +282,54 @@ sequenceDecs_decode_amd64_match_len_ofs_ok: MOVQ SI, 32(AX) // Return success + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000000, ret+24(FP) RET // Return with match length error sequenceDecs_decode_amd64_error_match_len_ofs_mismatch: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000001, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_amd64_error_match_len_too_big: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000002, ret+24(FP) RET // Return with match offset too long error + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000003, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000004, ret+24(FP) RET // Return with overread error error_overread: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000006, ret+24(FP) RET // func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV -TEXT ·sequenceDecs_decode_56_amd64(SB), $8-32 +TEXT ·sequenceDecs_decode_56_amd64(SB), $40-32 MOVQ br+8(FP), CX MOVQ 24(CX), DX MOVBQZX 40(CX), BX @@ -344,6 +341,14 @@ TEXT ·sequenceDecs_decode_56_amd64(SB), $8-32 MOVQ 72(AX), DI MOVQ 80(AX), R8 MOVQ 88(AX), R9 + MOVQ (AX), CX + MOVQ CX, 8(SP) + MOVQ 24(AX), CX + MOVQ CX, 16(SP) + MOVQ 48(AX), CX + MOVQ CX, 24(SP) + MOVQ 96(AX), CX + MOVQ CX, 32(SP) MOVQ 104(AX), R10 MOVQ s+0(FP), AX MOVQ 144(AX), R11 @@ -387,128 +392,100 @@ sequenceDecs_decode_56_amd64_fill_end: MOVQ BX, CX MOVQ DX, R15 SHLQ CL, R15 + SHRQ $0x01, R15 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_of_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_of_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R15 ADDQ R15, AX - -sequenceDecs_decode_56_amd64_of_update_zero: - MOVQ AX, 16(R10) + MOVQ AX, 16(R10) // Update match length MOVQ R8, AX MOVQ BX, CX MOVQ DX, R15 SHLQ CL, R15 + SHRQ $0x01, R15 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_ml_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_ml_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R15 ADDQ R15, AX - -sequenceDecs_decode_56_amd64_ml_update_zero: - MOVQ AX, 8(R10) + MOVQ AX, 8(R10) // Update literal length MOVQ DI, AX MOVQ BX, CX MOVQ DX, R15 SHLQ CL, R15 + SHRQ $0x01, R15 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_ll_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_ll_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R15 ADDQ R15, AX - -sequenceDecs_decode_56_amd64_ll_update_zero: - MOVQ AX, (R10) + MOVQ AX, (R10) // Fill bitreader for state updates MOVQ R14, (SP) MOVQ R9, AX SHRQ $0x08, AX MOVBQZX AL, AX - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decode_56_amd64_skip_update // Update Literal Length State MOVBQZX DI, R14 SHRL $0x10, DI - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVBLZX R14, CX - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, DI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(DI*8), DI // Update Match Length State MOVBQZX R8, R14 SHRL $0x10, R8 - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVBLZX R14, CX - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, R8 // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(R8*8), R8 // Update Offset State MOVBQZX R9, R14 SHRL $0x10, R9 - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVBLZX R14, CX - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, R9 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R9*8), R9 sequenceDecs_decode_56_amd64_skip_update: @@ -589,8 +566,7 @@ sequenceDecs_decode_56_amd64_after_adjust: sequenceDecs_decode_56_amd64_match_len_ofs_ok: ADDQ $0x18, R10 - MOVQ ctx+16(FP), AX - DECQ 96(AX) + DECQ 32(SP) JNS sequenceDecs_decode_56_amd64_main_loop MOVQ s+0(FP), AX MOVQ R11, 144(AX) @@ -602,36 +578,54 @@ sequenceDecs_decode_56_amd64_match_len_ofs_ok: MOVQ SI, 32(AX) // Return success + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000000, ret+24(FP) RET // Return with match length error sequenceDecs_decode_56_amd64_error_match_len_ofs_mismatch: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000001, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_56_amd64_error_match_len_too_big: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000002, ret+24(FP) RET // Return with match offset too long error + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000003, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000004, ret+24(FP) RET // Return with overread error error_overread: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000006, ret+24(FP) RET // func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: BMI, BMI2, CMOV -TEXT ·sequenceDecs_decode_bmi2(SB), $8-32 +TEXT ·sequenceDecs_decode_bmi2(SB), $40-32 MOVQ br+8(FP), BX MOVQ 24(BX), AX MOVBQZX 40(BX), DX @@ -643,6 +637,14 @@ TEXT ·sequenceDecs_decode_bmi2(SB), $8-32 MOVQ 72(CX), SI MOVQ 80(CX), DI MOVQ 88(CX), R8 + MOVQ (CX), R9 + MOVQ R9, 8(SP) + MOVQ 24(CX), R9 + MOVQ R9, 16(SP) + MOVQ 48(CX), R9 + MOVQ R9, 24(SP) + MOVQ 96(CX), R9 + MOVQ R9, 32(SP) MOVQ 104(CX), R9 MOVQ s+0(FP), CX MOVQ 144(CX), R10 @@ -753,8 +755,7 @@ sequenceDecs_decode_bmi2_fill_2_end: MOVQ R13, (SP) MOVQ $0x00000808, CX BEXTRQ CX, R8, R13 - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decode_bmi2_skip_update LEAQ (SI)(DI*1), R14 ADDQ R8, R14 @@ -772,8 +773,7 @@ sequenceDecs_decode_bmi2_fill_2_end: ADDQ CX, R8 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R8*8), R8 // Update Match Length State @@ -783,8 +783,7 @@ sequenceDecs_decode_bmi2_fill_2_end: ADDQ CX, DI // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(DI*8), DI // Update Literal Length State @@ -793,8 +792,7 @@ sequenceDecs_decode_bmi2_fill_2_end: ADDQ CX, SI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(SI*8), SI sequenceDecs_decode_bmi2_skip_update: @@ -875,8 +873,7 @@ sequenceDecs_decode_bmi2_after_adjust: sequenceDecs_decode_bmi2_match_len_ofs_ok: ADDQ $0x18, R9 - MOVQ ctx+16(FP), CX - DECQ 96(CX) + DECQ 32(SP) JNS sequenceDecs_decode_bmi2_main_loop MOVQ s+0(FP), CX MOVQ R10, 144(CX) @@ -888,36 +885,54 @@ sequenceDecs_decode_bmi2_match_len_ofs_ok: MOVQ BX, 32(CX) // Return success + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000000, ret+24(FP) RET // Return with match length error sequenceDecs_decode_bmi2_error_match_len_ofs_mismatch: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000001, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_bmi2_error_match_len_too_big: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000002, ret+24(FP) RET // Return with match offset too long error + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000003, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000004, ret+24(FP) RET // Return with overread error error_overread: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000006, ret+24(FP) RET // func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: BMI, BMI2, CMOV -TEXT ·sequenceDecs_decode_56_bmi2(SB), $8-32 +TEXT ·sequenceDecs_decode_56_bmi2(SB), $40-32 MOVQ br+8(FP), BX MOVQ 24(BX), AX MOVBQZX 40(BX), DX @@ -929,6 +944,14 @@ TEXT ·sequenceDecs_decode_56_bmi2(SB), $8-32 MOVQ 72(CX), SI MOVQ 80(CX), DI MOVQ 88(CX), R8 + MOVQ (CX), R9 + MOVQ R9, 8(SP) + MOVQ 24(CX), R9 + MOVQ R9, 16(SP) + MOVQ 48(CX), R9 + MOVQ R9, 24(SP) + MOVQ 96(CX), R9 + MOVQ R9, 32(SP) MOVQ 104(CX), R9 MOVQ s+0(FP), CX MOVQ 144(CX), R10 @@ -1010,8 +1033,7 @@ sequenceDecs_decode_56_bmi2_fill_end: MOVQ R13, (SP) MOVQ $0x00000808, CX BEXTRQ CX, R8, R13 - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decode_56_bmi2_skip_update LEAQ (SI)(DI*1), R14 ADDQ R8, R14 @@ -1029,8 +1051,7 @@ sequenceDecs_decode_56_bmi2_fill_end: ADDQ CX, R8 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R8*8), R8 // Update Match Length State @@ -1040,8 +1061,7 @@ sequenceDecs_decode_56_bmi2_fill_end: ADDQ CX, DI // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(DI*8), DI // Update Literal Length State @@ -1050,8 +1070,7 @@ sequenceDecs_decode_56_bmi2_fill_end: ADDQ CX, SI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(SI*8), SI sequenceDecs_decode_56_bmi2_skip_update: @@ -1132,8 +1151,7 @@ sequenceDecs_decode_56_bmi2_after_adjust: sequenceDecs_decode_56_bmi2_match_len_ofs_ok: ADDQ $0x18, R9 - MOVQ ctx+16(FP), CX - DECQ 96(CX) + DECQ 32(SP) JNS sequenceDecs_decode_56_bmi2_main_loop MOVQ s+0(FP), CX MOVQ R10, 144(CX) @@ -1145,30 +1163,48 @@ sequenceDecs_decode_56_bmi2_match_len_ofs_ok: MOVQ BX, 32(CX) // Return success + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000000, ret+24(FP) RET // Return with match length error sequenceDecs_decode_56_bmi2_error_match_len_ofs_mismatch: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000001, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_56_bmi2_error_match_len_too_big: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000002, ret+24(FP) RET // Return with match offset too long error + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000003, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000004, ret+24(FP) RET // Return with overread error error_overread: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000006, ret+24(FP) RET @@ -1203,9 +1239,11 @@ main_loop: MOVQ 8(AX), R13 // Copy literals - TESTQ R11, R11 - JZ check_offset - XORQ R14, R14 + MOVUPS (SI), X0 + MOVUPS X0, (BX) + CMPQ R11, $0x10 + JBE copy_1_end + MOVQ $0x00000010, R14 copy_1: MOVUPS (SI)(R14*1), X0 @@ -1213,12 +1251,13 @@ copy_1: ADDQ $0x10, R14 CMPQ R14, R11 JB copy_1 - ADDQ R11, SI - ADDQ R11, BX - ADDQ R11, DI + +copy_1_end: + ADDQ R11, SI + ADDQ R11, BX + ADDQ R11, DI // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: LEAQ (DI)(R10*1), R11 CMPQ R12, R11 JG error_match_off_too_big @@ -1366,9 +1405,19 @@ copy_match: JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, DI - MOVQ BX, R12 + ADDQ R13, DI + MOVUPS (R11), X0 + MOVUPS X0, (BX) + CMPQ R13, $0x10 + JA copy_2_long + ADDQ R13, BX + JMP handle_loop + +copy_2_long: + LEAQ 16(BX), R12 ADDQ R13, BX + ADDQ $0x10, R11 + SUBQ $0x10, R13 copy_2: MOVUPS (R11), X0 @@ -1784,7 +1833,7 @@ empty_seqs: // func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: CMOV, SSE -TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_amd64(SB), $96-32 MOVQ br+8(FP), CX MOVQ 24(CX), DX MOVBQZX 40(CX), BX @@ -1796,26 +1845,34 @@ TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32 MOVQ 72(AX), DI MOVQ 80(AX), R8 MOVQ 88(AX), R9 - XORQ CX, CX + MOVQ (AX), CX MOVQ CX, 8(SP) + MOVQ 24(AX), CX MOVQ CX, 16(SP) + MOVQ 48(AX), CX MOVQ CX, 24(SP) + MOVQ 96(AX), CX + MOVQ CX, 32(SP) + XORQ CX, CX + MOVQ CX, 40(SP) + MOVQ CX, 48(SP) + MOVQ CX, 56(SP) MOVQ 112(AX), R10 MOVQ 128(AX), CX - MOVQ CX, 32(SP) + MOVQ CX, 64(SP) MOVQ 144(AX), R11 MOVQ 136(AX), R12 MOVQ 200(AX), CX - MOVQ CX, 56(SP) + MOVQ CX, 88(SP) MOVQ 176(AX), CX - MOVQ CX, 48(SP) + MOVQ CX, 80(SP) MOVQ 184(AX), AX - MOVQ AX, 40(SP) - MOVQ 40(SP), AX - ADDQ AX, 48(SP) + MOVQ AX, 72(SP) + MOVQ 72(SP), AX + ADDQ AX, 80(SP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - ADDQ R10, 32(SP) + ADDQ R10, 64(SP) // outBase += outPosition ADDQ R12, R10 @@ -1857,42 +1914,28 @@ sequenceDecs_decodeSync_amd64_fill_end: MOVQ BX, CX MOVQ DX, R14 SHLQ CL, R14 + SHRQ $0x01, R14 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_of_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_of_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R14 ADDQ R14, AX - -sequenceDecs_decodeSync_amd64_of_update_zero: - MOVQ AX, 8(SP) + MOVQ AX, 40(SP) // Update match length MOVQ R8, AX MOVQ BX, CX MOVQ DX, R14 SHLQ CL, R14 + SHRQ $0x01, R14 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_ml_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_ml_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R14 ADDQ R14, AX - -sequenceDecs_decodeSync_amd64_ml_update_zero: - MOVQ AX, 16(SP) + MOVQ AX, 48(SP) // Fill bitreader to have enough for the remaining CMPQ SI, $0x08 @@ -1928,92 +1971,78 @@ sequenceDecs_decodeSync_amd64_fill_2_end: MOVQ BX, CX MOVQ DX, R14 SHLQ CL, R14 + SHRQ $0x01, R14 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_ll_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_ll_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R14 ADDQ R14, AX - -sequenceDecs_decodeSync_amd64_ll_update_zero: - MOVQ AX, 24(SP) + MOVQ AX, 56(SP) // Fill bitreader for state updates MOVQ R13, (SP) MOVQ R9, AX SHRQ $0x08, AX MOVBQZX AL, AX - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decodeSync_amd64_skip_update // Update Literal Length State MOVBQZX DI, R13 SHRL $0x10, DI - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVBLZX R13, CX - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, DI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(DI*8), DI // Update Match Length State MOVBQZX R8, R13 SHRL $0x10, R8 - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVBLZX R13, CX - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, R8 // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(R8*8), R8 // Update Offset State MOVBQZX R9, R13 SHRL $0x10, R9 - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVBLZX R13, CX - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, R9 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R9*8), R9 sequenceDecs_decodeSync_amd64_skip_update: // Adjust offset MOVQ s+0(FP), CX - MOVQ 8(SP), R13 + MOVQ 40(SP), R13 CMPQ AX, $0x01 JBE sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 MOVUPS 144(CX), X0 @@ -2022,7 +2051,7 @@ sequenceDecs_decodeSync_amd64_skip_update: JMP sequenceDecs_decodeSync_amd64_after_adjust sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0: - CMPQ 24(SP), $0x00000000 + CMPQ 56(SP), $0x00000000 JNE sequenceDecs_decodeSync_amd64_adjust_offset_maybezero INCQ R13 JMP sequenceDecs_decodeSync_amd64_adjust_offset_nonzero @@ -2057,14 +2086,11 @@ sequenceDecs_decodeSync_amd64_adjust_skip: MOVQ R14, R13 sequenceDecs_decodeSync_amd64_after_adjust: - MOVQ R13, 8(SP) + MOVQ R13, 40(SP) // Check values - MOVQ 16(SP), AX - MOVQ 24(SP), CX - LEAQ (AX)(CX*1), R14 - MOVQ s+0(FP), R15 - ADDQ R14, 256(R15) + MOVQ 48(SP), AX + MOVQ 56(SP), CX MOVQ ctx+16(FP), R14 SUBQ CX, 104(R14) JS error_not_enough_literals @@ -2076,50 +2102,49 @@ sequenceDecs_decodeSync_amd64_after_adjust: JNZ sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch sequenceDecs_decodeSync_amd64_match_len_ofs_ok: - MOVQ 24(SP), AX - MOVQ 8(SP), CX - MOVQ 16(SP), R13 - // Check if we have enough space in s.out - LEAQ 16(AX)(R13*1), R14 + LEAQ 16(CX)(AX*1), R14 ADDQ R10, R14 - CMPQ R14, 32(SP) + CMPQ R14, 64(SP) JA error_not_enough_space // Copy literals - TESTQ AX, AX - JZ check_offset - XORQ R14, R14 + MOVUPS (R11), X0 + MOVUPS X0, (R10) + CMPQ CX, $0x10 + JBE copy_1_end + MOVQ $0x00000010, R14 copy_1: MOVUPS (R11)(R14*1), X0 MOVUPS X0, (R10)(R14*1) ADDQ $0x10, R14 - CMPQ R14, AX + CMPQ R14, CX JB copy_1 - ADDQ AX, R11 - ADDQ AX, R10 - ADDQ AX, R12 + +copy_1_end: + ADDQ CX, R11 + ADDQ CX, R10 + ADDQ CX, R12 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: - MOVQ R12, AX - ADDQ 40(SP), AX - CMPQ CX, AX + MOVQ R12, CX + ADDQ 72(SP), CX + CMPQ R13, CX JG error_match_off_too_big - CMPQ CX, 56(SP) + CMPQ R13, 88(SP) JG error_match_off_too_big // Copy match from history - MOVQ CX, AX - SUBQ R12, AX + MOVQ R13, CX + SUBQ R12, CX JLS copy_match - MOVQ 48(SP), R14 - SUBQ AX, R14 - CMPQ R13, AX + MOVQ 80(SP), R14 + SUBQ CX, R14 + CMPQ AX, CX JG copy_all_from_history - MOVQ R13, AX - SUBQ $0x10, AX + MOVQ AX, CX + SUBQ $0x10, CX JB copy_4_small copy_4_loop: @@ -2127,54 +2152,54 @@ copy_4_loop: MOVUPS X0, (R10) ADDQ $0x10, R14 ADDQ $0x10, R10 - SUBQ $0x10, AX + SUBQ $0x10, CX JAE copy_4_loop - LEAQ 16(R14)(AX*1), R14 - LEAQ 16(R10)(AX*1), R10 + LEAQ 16(R14)(CX*1), R14 + LEAQ 16(R10)(CX*1), R10 MOVUPS -16(R14), X0 MOVUPS X0, -16(R10) JMP copy_4_end copy_4_small: - CMPQ R13, $0x03 + CMPQ AX, $0x03 JE copy_4_move_3 - CMPQ R13, $0x08 + CMPQ AX, $0x08 JB copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVWQZX (R14), AX - MOVB 2(R14), CL - MOVW AX, (R10) - MOVB CL, 2(R10) - ADDQ R13, R14 - ADDQ R13, R10 + MOVWQZX (R14), CX + MOVB 2(R14), R13 + MOVW CX, (R10) + MOVB R13, 2(R10) + ADDQ AX, R14 + ADDQ AX, R10 JMP copy_4_end copy_4_move_4through7: - MOVL (R14), AX - MOVL -4(R14)(R13*1), CX - MOVL AX, (R10) - MOVL CX, -4(R10)(R13*1) - ADDQ R13, R14 - ADDQ R13, R10 + MOVL (R14), CX + MOVL -4(R14)(AX*1), R13 + MOVL CX, (R10) + MOVL R13, -4(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 JMP copy_4_end copy_4_move_8through16: - MOVQ (R14), AX - MOVQ -8(R14)(R13*1), CX - MOVQ AX, (R10) - MOVQ CX, -8(R10)(R13*1) - ADDQ R13, R14 - ADDQ R13, R10 + MOVQ (R14), CX + MOVQ -8(R14)(AX*1), R13 + MOVQ CX, (R10) + MOVQ R13, -8(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 copy_4_end: - ADDQ R13, R12 + ADDQ AX, R12 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVQ AX, R15 + MOVQ CX, R15 SUBQ $0x10, R15 JB copy_5_small @@ -2192,20 +2217,20 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMPQ AX, $0x03 + CMPQ CX, $0x03 JE copy_5_move_3 JB copy_5_move_1or2 - CMPQ AX, $0x08 + CMPQ CX, $0x08 JB copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVB (R14), R15 - MOVB -1(R14)(AX*1), BP + MOVB -1(R14)(CX*1), BP MOVB R15, (R10) - MOVB BP, -1(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVB BP, -1(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_3: @@ -2213,69 +2238,78 @@ copy_5_move_3: MOVB 2(R14), BP MOVW R15, (R10) MOVB BP, 2(R10) - ADDQ AX, R14 - ADDQ AX, R10 + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 - MOVL -4(R14)(AX*1), BP + MOVL -4(R14)(CX*1), BP MOVL R15, (R10) - MOVL BP, -4(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVL BP, -4(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_8through16: MOVQ (R14), R15 - MOVQ -8(R14)(AX*1), BP + MOVQ -8(R14)(CX*1), BP MOVQ R15, (R10) - MOVQ BP, -8(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVQ BP, -8(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 copy_5_end: - ADDQ AX, R12 - SUBQ AX, R13 + ADDQ CX, R12 + SUBQ CX, AX // Copy match from the current buffer copy_match: - MOVQ R10, AX - SUBQ CX, AX + MOVQ R10, CX + SUBQ R13, CX // ml <= mo - CMPQ R13, CX + CMPQ AX, R13 JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, R12 - MOVQ R10, CX - ADDQ R13, R10 + ADDQ AX, R12 + MOVUPS (CX), X0 + MOVUPS X0, (R10) + CMPQ AX, $0x10 + JA copy_2_long + ADDQ AX, R10 + JMP handle_loop + +copy_2_long: + LEAQ 16(R10), R13 + ADDQ AX, R10 + ADDQ $0x10, CX + SUBQ $0x10, AX copy_2: - MOVUPS (AX), X0 - MOVUPS X0, (CX) - ADDQ $0x10, AX + MOVUPS (CX), X0 + MOVUPS X0, (R13) ADDQ $0x10, CX - SUBQ $0x10, R13 + ADDQ $0x10, R13 + SUBQ $0x10, AX JHI copy_2 JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADDQ R13, R12 + ADDQ AX, R12 copy_slow_3: - MOVBQZX (AX), CX - MOVB CL, (R10) - INCQ AX + MOVBQZX (CX), R13 + MOVB R13, (R10) + INCQ CX INCQ R10 - DECQ R13 + DECQ AX JNZ copy_slow_3 handle_loop: - MOVQ ctx+16(FP), AX - DECQ 96(AX) + DECQ 32(SP) JNS sequenceDecs_decodeSync_amd64_main_loop loop_finished: @@ -2284,6 +2318,13 @@ loop_finished: MOVB BL, 40(AX) MOVQ SI, 32(AX) + // s.seqSize += outPosition - ctx.outPosition + MOVQ ctx+16(FP), AX + MOVQ s+0(FP), CX + MOVQ R12, DX + SUBQ 136(AX), DX + ADDQ DX, 256(CX) + // Update the context MOVQ ctx+16(FP), AX MOVQ R12, 136(AX) @@ -2297,7 +2338,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: - MOVQ 16(SP), AX + MOVQ 48(SP), AX MOVQ ctx+16(FP), CX MOVQ AX, 216(CX) MOVQ $0x00000001, ret+24(FP) @@ -2306,7 +2347,7 @@ sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_amd64_error_match_len_too_big: MOVQ ctx+16(FP), AX - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ $0x00000002, ret+24(FP) RET @@ -2314,7 +2355,7 @@ sequenceDecs_decodeSync_amd64_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVQ ctx+16(FP), AX - MOVQ 8(SP), CX + MOVQ 40(SP), CX MOVQ CX, 224(AX) MOVQ R12, 136(AX) MOVQ $0x00000003, ret+24(FP) @@ -2323,7 +2364,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) MOVQ $0x00000004, ret+24(FP) RET @@ -2336,9 +2377,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ R12, 136(AX) MOVQ $0x00000005, ret+24(FP) @@ -2346,7 +2387,7 @@ error_not_enough_space: // func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: BMI, BMI2, CMOV, SSE -TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_bmi2(SB), $96-32 MOVQ br+8(FP), BX MOVQ 24(BX), AX MOVBQZX 40(BX), DX @@ -2358,26 +2399,34 @@ TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32 MOVQ 72(CX), SI MOVQ 80(CX), DI MOVQ 88(CX), R8 - XORQ R9, R9 + MOVQ (CX), R9 MOVQ R9, 8(SP) + MOVQ 24(CX), R9 MOVQ R9, 16(SP) + MOVQ 48(CX), R9 MOVQ R9, 24(SP) + MOVQ 96(CX), R9 + MOVQ R9, 32(SP) + XORQ R9, R9 + MOVQ R9, 40(SP) + MOVQ R9, 48(SP) + MOVQ R9, 56(SP) MOVQ 112(CX), R9 MOVQ 128(CX), R10 - MOVQ R10, 32(SP) + MOVQ R10, 64(SP) MOVQ 144(CX), R10 MOVQ 136(CX), R11 MOVQ 200(CX), R12 - MOVQ R12, 56(SP) + MOVQ R12, 88(SP) MOVQ 176(CX), R12 - MOVQ R12, 48(SP) + MOVQ R12, 80(SP) MOVQ 184(CX), CX - MOVQ CX, 40(SP) - MOVQ 40(SP), CX - ADDQ CX, 48(SP) + MOVQ CX, 72(SP) + MOVQ 72(SP), CX + ADDQ CX, 80(SP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - ADDQ R9, 32(SP) + ADDQ R9, 64(SP) // outBase += outPosition ADDQ R11, R9 @@ -2425,7 +2474,7 @@ sequenceDecs_decodeSync_bmi2_fill_end: MOVQ R8, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 8(SP) + MOVQ CX, 40(SP) // Update match length MOVQ $0x00000808, CX @@ -2438,7 +2487,7 @@ sequenceDecs_decodeSync_bmi2_fill_end: MOVQ DI, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 16(SP) + MOVQ CX, 48(SP) // Fill bitreader to have enough for the remaining CMPQ BX, $0x08 @@ -2480,14 +2529,13 @@ sequenceDecs_decodeSync_bmi2_fill_2_end: MOVQ SI, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 24(SP) + MOVQ CX, 56(SP) // Fill bitreader for state updates MOVQ R12, (SP) MOVQ $0x00000808, CX BEXTRQ CX, R8, R12 - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decodeSync_bmi2_skip_update LEAQ (SI)(DI*1), R13 ADDQ R8, R13 @@ -2505,8 +2553,7 @@ sequenceDecs_decodeSync_bmi2_fill_2_end: ADDQ CX, R8 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R8*8), R8 // Update Match Length State @@ -2516,8 +2563,7 @@ sequenceDecs_decodeSync_bmi2_fill_2_end: ADDQ CX, DI // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(DI*8), DI // Update Literal Length State @@ -2526,14 +2572,13 @@ sequenceDecs_decodeSync_bmi2_fill_2_end: ADDQ CX, SI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(SI*8), SI sequenceDecs_decodeSync_bmi2_skip_update: // Adjust offset MOVQ s+0(FP), CX - MOVQ 8(SP), R13 + MOVQ 40(SP), R13 CMPQ R12, $0x01 JBE sequenceDecs_decodeSync_bmi2_adjust_offsetB_1_or_0 MOVUPS 144(CX), X0 @@ -2542,7 +2587,7 @@ sequenceDecs_decodeSync_bmi2_skip_update: JMP sequenceDecs_decodeSync_bmi2_after_adjust sequenceDecs_decodeSync_bmi2_adjust_offsetB_1_or_0: - CMPQ 24(SP), $0x00000000 + CMPQ 56(SP), $0x00000000 JNE sequenceDecs_decodeSync_bmi2_adjust_offset_maybezero INCQ R13 JMP sequenceDecs_decodeSync_bmi2_adjust_offset_nonzero @@ -2577,14 +2622,11 @@ sequenceDecs_decodeSync_bmi2_adjust_skip: MOVQ R14, R13 sequenceDecs_decodeSync_bmi2_after_adjust: - MOVQ R13, 8(SP) + MOVQ R13, 40(SP) // Check values - MOVQ 16(SP), CX - MOVQ 24(SP), R12 - LEAQ (CX)(R12*1), R14 - MOVQ s+0(FP), R15 - ADDQ R14, 256(R15) + MOVQ 48(SP), CX + MOVQ 56(SP), R12 MOVQ ctx+16(FP), R14 SUBQ R12, 104(R14) JS error_not_enough_literals @@ -2596,50 +2638,49 @@ sequenceDecs_decodeSync_bmi2_after_adjust: JNZ sequenceDecs_decodeSync_bmi2_error_match_len_ofs_mismatch sequenceDecs_decodeSync_bmi2_match_len_ofs_ok: - MOVQ 24(SP), CX - MOVQ 8(SP), R12 - MOVQ 16(SP), R13 - // Check if we have enough space in s.out - LEAQ 16(CX)(R13*1), R14 + LEAQ 16(R12)(CX*1), R14 ADDQ R9, R14 - CMPQ R14, 32(SP) + CMPQ R14, 64(SP) JA error_not_enough_space // Copy literals - TESTQ CX, CX - JZ check_offset - XORQ R14, R14 + MOVUPS (R10), X0 + MOVUPS X0, (R9) + CMPQ R12, $0x10 + JBE copy_1_end + MOVQ $0x00000010, R14 copy_1: MOVUPS (R10)(R14*1), X0 MOVUPS X0, (R9)(R14*1) ADDQ $0x10, R14 - CMPQ R14, CX + CMPQ R14, R12 JB copy_1 - ADDQ CX, R10 - ADDQ CX, R9 - ADDQ CX, R11 + +copy_1_end: + ADDQ R12, R10 + ADDQ R12, R9 + ADDQ R12, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: - MOVQ R11, CX - ADDQ 40(SP), CX - CMPQ R12, CX + MOVQ R11, R12 + ADDQ 72(SP), R12 + CMPQ R13, R12 JG error_match_off_too_big - CMPQ R12, 56(SP) + CMPQ R13, 88(SP) JG error_match_off_too_big // Copy match from history - MOVQ R12, CX - SUBQ R11, CX + MOVQ R13, R12 + SUBQ R11, R12 JLS copy_match - MOVQ 48(SP), R14 - SUBQ CX, R14 - CMPQ R13, CX + MOVQ 80(SP), R14 + SUBQ R12, R14 + CMPQ CX, R12 JG copy_all_from_history - MOVQ R13, CX - SUBQ $0x10, CX + MOVQ CX, R12 + SUBQ $0x10, R12 JB copy_4_small copy_4_loop: @@ -2647,54 +2688,54 @@ copy_4_loop: MOVUPS X0, (R9) ADDQ $0x10, R14 ADDQ $0x10, R9 - SUBQ $0x10, CX + SUBQ $0x10, R12 JAE copy_4_loop - LEAQ 16(R14)(CX*1), R14 - LEAQ 16(R9)(CX*1), R9 + LEAQ 16(R14)(R12*1), R14 + LEAQ 16(R9)(R12*1), R9 MOVUPS -16(R14), X0 MOVUPS X0, -16(R9) JMP copy_4_end copy_4_small: - CMPQ R13, $0x03 + CMPQ CX, $0x03 JE copy_4_move_3 - CMPQ R13, $0x08 + CMPQ CX, $0x08 JB copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVWQZX (R14), CX - MOVB 2(R14), R12 - MOVW CX, (R9) - MOVB R12, 2(R9) - ADDQ R13, R14 - ADDQ R13, R9 + MOVWQZX (R14), R12 + MOVB 2(R14), R13 + MOVW R12, (R9) + MOVB R13, 2(R9) + ADDQ CX, R14 + ADDQ CX, R9 JMP copy_4_end copy_4_move_4through7: - MOVL (R14), CX - MOVL -4(R14)(R13*1), R12 - MOVL CX, (R9) - MOVL R12, -4(R9)(R13*1) - ADDQ R13, R14 - ADDQ R13, R9 + MOVL (R14), R12 + MOVL -4(R14)(CX*1), R13 + MOVL R12, (R9) + MOVL R13, -4(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 JMP copy_4_end copy_4_move_8through16: - MOVQ (R14), CX - MOVQ -8(R14)(R13*1), R12 - MOVQ CX, (R9) - MOVQ R12, -8(R9)(R13*1) - ADDQ R13, R14 - ADDQ R13, R9 + MOVQ (R14), R12 + MOVQ -8(R14)(CX*1), R13 + MOVQ R12, (R9) + MOVQ R13, -8(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 copy_4_end: - ADDQ R13, R11 + ADDQ CX, R11 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVQ CX, R15 + MOVQ R12, R15 SUBQ $0x10, R15 JB copy_5_small @@ -2712,20 +2753,20 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMPQ CX, $0x03 + CMPQ R12, $0x03 JE copy_5_move_3 JB copy_5_move_1or2 - CMPQ CX, $0x08 + CMPQ R12, $0x08 JB copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVB (R14), R15 - MOVB -1(R14)(CX*1), BP + MOVB -1(R14)(R12*1), BP MOVB R15, (R9) - MOVB BP, -1(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVB BP, -1(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_3: @@ -2733,69 +2774,78 @@ copy_5_move_3: MOVB 2(R14), BP MOVW R15, (R9) MOVB BP, 2(R9) - ADDQ CX, R14 - ADDQ CX, R9 + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 - MOVL -4(R14)(CX*1), BP + MOVL -4(R14)(R12*1), BP MOVL R15, (R9) - MOVL BP, -4(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVL BP, -4(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_8through16: MOVQ (R14), R15 - MOVQ -8(R14)(CX*1), BP + MOVQ -8(R14)(R12*1), BP MOVQ R15, (R9) - MOVQ BP, -8(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVQ BP, -8(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 copy_5_end: - ADDQ CX, R11 - SUBQ CX, R13 + ADDQ R12, R11 + SUBQ R12, CX // Copy match from the current buffer copy_match: - MOVQ R9, CX - SUBQ R12, CX + MOVQ R9, R12 + SUBQ R13, R12 // ml <= mo - CMPQ R13, R12 + CMPQ CX, R13 JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, R11 - MOVQ R9, R12 - ADDQ R13, R9 + ADDQ CX, R11 + MOVUPS (R12), X0 + MOVUPS X0, (R9) + CMPQ CX, $0x10 + JA copy_2_long + ADDQ CX, R9 + JMP handle_loop + +copy_2_long: + LEAQ 16(R9), R13 + ADDQ CX, R9 + ADDQ $0x10, R12 + SUBQ $0x10, CX copy_2: - MOVUPS (CX), X0 - MOVUPS X0, (R12) - ADDQ $0x10, CX + MOVUPS (R12), X0 + MOVUPS X0, (R13) ADDQ $0x10, R12 - SUBQ $0x10, R13 + ADDQ $0x10, R13 + SUBQ $0x10, CX JHI copy_2 JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADDQ R13, R11 + ADDQ CX, R11 copy_slow_3: - MOVBQZX (CX), R12 - MOVB R12, (R9) - INCQ CX + MOVBQZX (R12), R13 + MOVB R13, (R9) + INCQ R12 INCQ R9 - DECQ R13 + DECQ CX JNZ copy_slow_3 handle_loop: - MOVQ ctx+16(FP), CX - DECQ 96(CX) + DECQ 32(SP) JNS sequenceDecs_decodeSync_bmi2_main_loop loop_finished: @@ -2804,6 +2854,13 @@ loop_finished: MOVB DL, 40(CX) MOVQ BX, 32(CX) + // s.seqSize += outPosition - ctx.outPosition + MOVQ ctx+16(FP), AX + MOVQ s+0(FP), CX + MOVQ R11, DX + SUBQ 136(AX), DX + ADDQ DX, 256(CX) + // Update the context MOVQ ctx+16(FP), AX MOVQ R11, 136(AX) @@ -2817,7 +2874,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_bmi2_error_match_len_ofs_mismatch: - MOVQ 16(SP), AX + MOVQ 48(SP), AX MOVQ ctx+16(FP), CX MOVQ AX, 216(CX) MOVQ $0x00000001, ret+24(FP) @@ -2826,7 +2883,7 @@ sequenceDecs_decodeSync_bmi2_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_bmi2_error_match_len_too_big: MOVQ ctx+16(FP), AX - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ $0x00000002, ret+24(FP) RET @@ -2834,7 +2891,7 @@ sequenceDecs_decodeSync_bmi2_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVQ ctx+16(FP), AX - MOVQ 8(SP), CX + MOVQ 40(SP), CX MOVQ CX, 224(AX) MOVQ R11, 136(AX) MOVQ $0x00000003, ret+24(FP) @@ -2843,7 +2900,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) MOVQ $0x00000004, ret+24(FP) RET @@ -2856,9 +2913,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ R11, 136(AX) MOVQ $0x00000005, ret+24(FP) @@ -2866,7 +2923,7 @@ error_not_enough_space: // func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: CMOV, SSE -TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $96-32 MOVQ br+8(FP), CX MOVQ 24(CX), DX MOVBQZX 40(CX), BX @@ -2878,26 +2935,34 @@ TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32 MOVQ 72(AX), DI MOVQ 80(AX), R8 MOVQ 88(AX), R9 - XORQ CX, CX + MOVQ (AX), CX MOVQ CX, 8(SP) + MOVQ 24(AX), CX MOVQ CX, 16(SP) + MOVQ 48(AX), CX MOVQ CX, 24(SP) + MOVQ 96(AX), CX + MOVQ CX, 32(SP) + XORQ CX, CX + MOVQ CX, 40(SP) + MOVQ CX, 48(SP) + MOVQ CX, 56(SP) MOVQ 112(AX), R10 MOVQ 128(AX), CX - MOVQ CX, 32(SP) + MOVQ CX, 64(SP) MOVQ 144(AX), R11 MOVQ 136(AX), R12 MOVQ 200(AX), CX - MOVQ CX, 56(SP) + MOVQ CX, 88(SP) MOVQ 176(AX), CX - MOVQ CX, 48(SP) + MOVQ CX, 80(SP) MOVQ 184(AX), AX - MOVQ AX, 40(SP) - MOVQ 40(SP), AX - ADDQ AX, 48(SP) + MOVQ AX, 72(SP) + MOVQ 72(SP), AX + ADDQ AX, 80(SP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - ADDQ R10, 32(SP) + ADDQ R10, 64(SP) // outBase += outPosition ADDQ R12, R10 @@ -2939,42 +3004,28 @@ sequenceDecs_decodeSync_safe_amd64_fill_end: MOVQ BX, CX MOVQ DX, R14 SHLQ CL, R14 + SHRQ $0x01, R14 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_of_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_of_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R14 ADDQ R14, AX - -sequenceDecs_decodeSync_safe_amd64_of_update_zero: - MOVQ AX, 8(SP) + MOVQ AX, 40(SP) // Update match length MOVQ R8, AX MOVQ BX, CX MOVQ DX, R14 SHLQ CL, R14 + SHRQ $0x01, R14 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_ml_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_ml_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R14 ADDQ R14, AX - -sequenceDecs_decodeSync_safe_amd64_ml_update_zero: - MOVQ AX, 16(SP) + MOVQ AX, 48(SP) // Fill bitreader to have enough for the remaining CMPQ SI, $0x08 @@ -3010,92 +3061,78 @@ sequenceDecs_decodeSync_safe_amd64_fill_2_end: MOVQ BX, CX MOVQ DX, R14 SHLQ CL, R14 + SHRQ $0x01, R14 MOVBLZX AH, CX SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_ll_update_zero ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_ll_update_zero - NEGQ CX + XORQ $0x3f, CX SHRQ CL, R14 ADDQ R14, AX - -sequenceDecs_decodeSync_safe_amd64_ll_update_zero: - MOVQ AX, 24(SP) + MOVQ AX, 56(SP) // Fill bitreader for state updates MOVQ R13, (SP) MOVQ R9, AX SHRQ $0x08, AX MOVBQZX AL, AX - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decodeSync_safe_amd64_skip_update // Update Literal Length State MOVBQZX DI, R13 SHRL $0x10, DI - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVBLZX R13, CX - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, DI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(DI*8), DI // Update Match Length State MOVBQZX R8, R13 SHRL $0x10, R8 - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVBLZX R13, CX - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, R8 // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(R8*8), R8 // Update Offset State MOVBQZX R9, R13 SHRL $0x10, R9 - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVBLZX R13, CX - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, R9 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R9*8), R9 sequenceDecs_decodeSync_safe_amd64_skip_update: // Adjust offset MOVQ s+0(FP), CX - MOVQ 8(SP), R13 + MOVQ 40(SP), R13 CMPQ AX, $0x01 JBE sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 MOVUPS 144(CX), X0 @@ -3104,7 +3141,7 @@ sequenceDecs_decodeSync_safe_amd64_skip_update: JMP sequenceDecs_decodeSync_safe_amd64_after_adjust sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0: - CMPQ 24(SP), $0x00000000 + CMPQ 56(SP), $0x00000000 JNE sequenceDecs_decodeSync_safe_amd64_adjust_offset_maybezero INCQ R13 JMP sequenceDecs_decodeSync_safe_amd64_adjust_offset_nonzero @@ -3139,14 +3176,11 @@ sequenceDecs_decodeSync_safe_amd64_adjust_skip: MOVQ R14, R13 sequenceDecs_decodeSync_safe_amd64_after_adjust: - MOVQ R13, 8(SP) + MOVQ R13, 40(SP) // Check values - MOVQ 16(SP), AX - MOVQ 24(SP), CX - LEAQ (AX)(CX*1), R14 - MOVQ s+0(FP), R15 - ADDQ R14, 256(R15) + MOVQ 48(SP), AX + MOVQ 56(SP), CX MOVQ ctx+16(FP), R14 SUBQ CX, 104(R14) JS error_not_enough_literals @@ -3158,20 +3192,16 @@ sequenceDecs_decodeSync_safe_amd64_after_adjust: JNZ sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok: - MOVQ 24(SP), AX - MOVQ 8(SP), CX - MOVQ 16(SP), R13 - // Check if we have enough space in s.out - LEAQ (AX)(R13*1), R14 + LEAQ (CX)(AX*1), R14 ADDQ R10, R14 - CMPQ R14, 32(SP) + CMPQ R14, 64(SP) JA error_not_enough_space // Copy literals - TESTQ AX, AX + TESTQ CX, CX JZ check_offset - MOVQ AX, R14 + MOVQ CX, R14 SUBQ $0x10, R14 JB copy_1_small @@ -3189,20 +3219,20 @@ copy_1_loop: JMP copy_1_end copy_1_small: - CMPQ AX, $0x03 + CMPQ CX, $0x03 JE copy_1_move_3 JB copy_1_move_1or2 - CMPQ AX, $0x08 + CMPQ CX, $0x08 JB copy_1_move_4through7 JMP copy_1_move_8through16 copy_1_move_1or2: MOVB (R11), R14 - MOVB -1(R11)(AX*1), R15 + MOVB -1(R11)(CX*1), R15 MOVB R14, (R10) - MOVB R15, -1(R10)(AX*1) - ADDQ AX, R11 - ADDQ AX, R10 + MOVB R15, -1(R10)(CX*1) + ADDQ CX, R11 + ADDQ CX, R10 JMP copy_1_end copy_1_move_3: @@ -3210,49 +3240,49 @@ copy_1_move_3: MOVB 2(R11), R15 MOVW R14, (R10) MOVB R15, 2(R10) - ADDQ AX, R11 - ADDQ AX, R10 + ADDQ CX, R11 + ADDQ CX, R10 JMP copy_1_end copy_1_move_4through7: MOVL (R11), R14 - MOVL -4(R11)(AX*1), R15 + MOVL -4(R11)(CX*1), R15 MOVL R14, (R10) - MOVL R15, -4(R10)(AX*1) - ADDQ AX, R11 - ADDQ AX, R10 + MOVL R15, -4(R10)(CX*1) + ADDQ CX, R11 + ADDQ CX, R10 JMP copy_1_end copy_1_move_8through16: MOVQ (R11), R14 - MOVQ -8(R11)(AX*1), R15 + MOVQ -8(R11)(CX*1), R15 MOVQ R14, (R10) - MOVQ R15, -8(R10)(AX*1) - ADDQ AX, R11 - ADDQ AX, R10 + MOVQ R15, -8(R10)(CX*1) + ADDQ CX, R11 + ADDQ CX, R10 copy_1_end: - ADDQ AX, R12 + ADDQ CX, R12 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) check_offset: - MOVQ R12, AX - ADDQ 40(SP), AX - CMPQ CX, AX + MOVQ R12, CX + ADDQ 72(SP), CX + CMPQ R13, CX JG error_match_off_too_big - CMPQ CX, 56(SP) + CMPQ R13, 88(SP) JG error_match_off_too_big // Copy match from history - MOVQ CX, AX - SUBQ R12, AX + MOVQ R13, CX + SUBQ R12, CX JLS copy_match - MOVQ 48(SP), R14 - SUBQ AX, R14 - CMPQ R13, AX + MOVQ 80(SP), R14 + SUBQ CX, R14 + CMPQ AX, CX JG copy_all_from_history - MOVQ R13, AX - SUBQ $0x10, AX + MOVQ AX, CX + SUBQ $0x10, CX JB copy_4_small copy_4_loop: @@ -3260,54 +3290,54 @@ copy_4_loop: MOVUPS X0, (R10) ADDQ $0x10, R14 ADDQ $0x10, R10 - SUBQ $0x10, AX + SUBQ $0x10, CX JAE copy_4_loop - LEAQ 16(R14)(AX*1), R14 - LEAQ 16(R10)(AX*1), R10 + LEAQ 16(R14)(CX*1), R14 + LEAQ 16(R10)(CX*1), R10 MOVUPS -16(R14), X0 MOVUPS X0, -16(R10) JMP copy_4_end copy_4_small: - CMPQ R13, $0x03 + CMPQ AX, $0x03 JE copy_4_move_3 - CMPQ R13, $0x08 + CMPQ AX, $0x08 JB copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVWQZX (R14), AX - MOVB 2(R14), CL - MOVW AX, (R10) - MOVB CL, 2(R10) - ADDQ R13, R14 - ADDQ R13, R10 + MOVWQZX (R14), CX + MOVB 2(R14), R13 + MOVW CX, (R10) + MOVB R13, 2(R10) + ADDQ AX, R14 + ADDQ AX, R10 JMP copy_4_end copy_4_move_4through7: - MOVL (R14), AX - MOVL -4(R14)(R13*1), CX - MOVL AX, (R10) - MOVL CX, -4(R10)(R13*1) - ADDQ R13, R14 - ADDQ R13, R10 + MOVL (R14), CX + MOVL -4(R14)(AX*1), R13 + MOVL CX, (R10) + MOVL R13, -4(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 JMP copy_4_end copy_4_move_8through16: - MOVQ (R14), AX - MOVQ -8(R14)(R13*1), CX - MOVQ AX, (R10) - MOVQ CX, -8(R10)(R13*1) - ADDQ R13, R14 - ADDQ R13, R10 + MOVQ (R14), CX + MOVQ -8(R14)(AX*1), R13 + MOVQ CX, (R10) + MOVQ R13, -8(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 copy_4_end: - ADDQ R13, R12 + ADDQ AX, R12 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVQ AX, R15 + MOVQ CX, R15 SUBQ $0x10, R15 JB copy_5_small @@ -3325,20 +3355,20 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMPQ AX, $0x03 + CMPQ CX, $0x03 JE copy_5_move_3 JB copy_5_move_1or2 - CMPQ AX, $0x08 + CMPQ CX, $0x08 JB copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVB (R14), R15 - MOVB -1(R14)(AX*1), BP + MOVB -1(R14)(CX*1), BP MOVB R15, (R10) - MOVB BP, -1(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVB BP, -1(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_3: @@ -3346,120 +3376,119 @@ copy_5_move_3: MOVB 2(R14), BP MOVW R15, (R10) MOVB BP, 2(R10) - ADDQ AX, R14 - ADDQ AX, R10 + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 - MOVL -4(R14)(AX*1), BP + MOVL -4(R14)(CX*1), BP MOVL R15, (R10) - MOVL BP, -4(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVL BP, -4(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_8through16: MOVQ (R14), R15 - MOVQ -8(R14)(AX*1), BP + MOVQ -8(R14)(CX*1), BP MOVQ R15, (R10) - MOVQ BP, -8(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVQ BP, -8(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 copy_5_end: - ADDQ AX, R12 - SUBQ AX, R13 + ADDQ CX, R12 + SUBQ CX, AX // Copy match from the current buffer copy_match: - MOVQ R10, AX - SUBQ CX, AX + MOVQ R10, CX + SUBQ R13, CX // ml <= mo - CMPQ R13, CX + CMPQ AX, R13 JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, R12 - MOVQ R13, CX - SUBQ $0x10, CX + ADDQ AX, R12 + MOVQ AX, R13 + SUBQ $0x10, R13 JB copy_2_small copy_2_loop: - MOVUPS (AX), X0 + MOVUPS (CX), X0 MOVUPS X0, (R10) - ADDQ $0x10, AX + ADDQ $0x10, CX ADDQ $0x10, R10 - SUBQ $0x10, CX + SUBQ $0x10, R13 JAE copy_2_loop - LEAQ 16(AX)(CX*1), AX - LEAQ 16(R10)(CX*1), R10 - MOVUPS -16(AX), X0 + LEAQ 16(CX)(R13*1), CX + LEAQ 16(R10)(R13*1), R10 + MOVUPS -16(CX), X0 MOVUPS X0, -16(R10) JMP copy_2_end copy_2_small: - CMPQ R13, $0x03 + CMPQ AX, $0x03 JE copy_2_move_3 JB copy_2_move_1or2 - CMPQ R13, $0x08 + CMPQ AX, $0x08 JB copy_2_move_4through7 JMP copy_2_move_8through16 copy_2_move_1or2: - MOVB (AX), CL - MOVB -1(AX)(R13*1), R14 - MOVB CL, (R10) - MOVB R14, -1(R10)(R13*1) - ADDQ R13, AX - ADDQ R13, R10 + MOVB (CX), R13 + MOVB -1(CX)(AX*1), R14 + MOVB R13, (R10) + MOVB R14, -1(R10)(AX*1) + ADDQ AX, CX + ADDQ AX, R10 JMP copy_2_end copy_2_move_3: - MOVWQZX (AX), CX - MOVB 2(AX), R14 - MOVW CX, (R10) + MOVWQZX (CX), R13 + MOVB 2(CX), R14 + MOVW R13, (R10) MOVB R14, 2(R10) - ADDQ R13, AX - ADDQ R13, R10 + ADDQ AX, CX + ADDQ AX, R10 JMP copy_2_end copy_2_move_4through7: - MOVL (AX), CX - MOVL -4(AX)(R13*1), R14 - MOVL CX, (R10) - MOVL R14, -4(R10)(R13*1) - ADDQ R13, AX - ADDQ R13, R10 + MOVL (CX), R13 + MOVL -4(CX)(AX*1), R14 + MOVL R13, (R10) + MOVL R14, -4(R10)(AX*1) + ADDQ AX, CX + ADDQ AX, R10 JMP copy_2_end copy_2_move_8through16: - MOVQ (AX), CX - MOVQ -8(AX)(R13*1), R14 - MOVQ CX, (R10) - MOVQ R14, -8(R10)(R13*1) - ADDQ R13, AX - ADDQ R13, R10 + MOVQ (CX), R13 + MOVQ -8(CX)(AX*1), R14 + MOVQ R13, (R10) + MOVQ R14, -8(R10)(AX*1) + ADDQ AX, CX + ADDQ AX, R10 copy_2_end: JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADDQ R13, R12 + ADDQ AX, R12 copy_slow_3: - MOVBQZX (AX), CX - MOVB CL, (R10) - INCQ AX + MOVBQZX (CX), R13 + MOVB R13, (R10) + INCQ CX INCQ R10 - DECQ R13 + DECQ AX JNZ copy_slow_3 handle_loop: - MOVQ ctx+16(FP), AX - DECQ 96(AX) + DECQ 32(SP) JNS sequenceDecs_decodeSync_safe_amd64_main_loop loop_finished: @@ -3468,6 +3497,13 @@ loop_finished: MOVB BL, 40(AX) MOVQ SI, 32(AX) + // s.seqSize += outPosition - ctx.outPosition + MOVQ ctx+16(FP), AX + MOVQ s+0(FP), CX + MOVQ R12, DX + SUBQ 136(AX), DX + ADDQ DX, 256(CX) + // Update the context MOVQ ctx+16(FP), AX MOVQ R12, 136(AX) @@ -3481,7 +3517,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: - MOVQ 16(SP), AX + MOVQ 48(SP), AX MOVQ ctx+16(FP), CX MOVQ AX, 216(CX) MOVQ $0x00000001, ret+24(FP) @@ -3490,7 +3526,7 @@ sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: MOVQ ctx+16(FP), AX - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ $0x00000002, ret+24(FP) RET @@ -3498,7 +3534,7 @@ sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVQ ctx+16(FP), AX - MOVQ 8(SP), CX + MOVQ 40(SP), CX MOVQ CX, 224(AX) MOVQ R12, 136(AX) MOVQ $0x00000003, ret+24(FP) @@ -3507,7 +3543,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) MOVQ $0x00000004, ret+24(FP) RET @@ -3520,9 +3556,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ R12, 136(AX) MOVQ $0x00000005, ret+24(FP) @@ -3530,7 +3566,7 @@ error_not_enough_space: // func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: BMI, BMI2, CMOV, SSE -TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $96-32 MOVQ br+8(FP), BX MOVQ 24(BX), AX MOVBQZX 40(BX), DX @@ -3542,26 +3578,34 @@ TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32 MOVQ 72(CX), SI MOVQ 80(CX), DI MOVQ 88(CX), R8 - XORQ R9, R9 + MOVQ (CX), R9 MOVQ R9, 8(SP) + MOVQ 24(CX), R9 MOVQ R9, 16(SP) + MOVQ 48(CX), R9 MOVQ R9, 24(SP) + MOVQ 96(CX), R9 + MOVQ R9, 32(SP) + XORQ R9, R9 + MOVQ R9, 40(SP) + MOVQ R9, 48(SP) + MOVQ R9, 56(SP) MOVQ 112(CX), R9 MOVQ 128(CX), R10 - MOVQ R10, 32(SP) + MOVQ R10, 64(SP) MOVQ 144(CX), R10 MOVQ 136(CX), R11 MOVQ 200(CX), R12 - MOVQ R12, 56(SP) + MOVQ R12, 88(SP) MOVQ 176(CX), R12 - MOVQ R12, 48(SP) + MOVQ R12, 80(SP) MOVQ 184(CX), CX - MOVQ CX, 40(SP) - MOVQ 40(SP), CX - ADDQ CX, 48(SP) + MOVQ CX, 72(SP) + MOVQ 72(SP), CX + ADDQ CX, 80(SP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - ADDQ R9, 32(SP) + ADDQ R9, 64(SP) // outBase += outPosition ADDQ R11, R9 @@ -3609,7 +3653,7 @@ sequenceDecs_decodeSync_safe_bmi2_fill_end: MOVQ R8, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 8(SP) + MOVQ CX, 40(SP) // Update match length MOVQ $0x00000808, CX @@ -3622,7 +3666,7 @@ sequenceDecs_decodeSync_safe_bmi2_fill_end: MOVQ DI, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 16(SP) + MOVQ CX, 48(SP) // Fill bitreader to have enough for the remaining CMPQ BX, $0x08 @@ -3664,14 +3708,13 @@ sequenceDecs_decodeSync_safe_bmi2_fill_2_end: MOVQ SI, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 24(SP) + MOVQ CX, 56(SP) // Fill bitreader for state updates MOVQ R12, (SP) MOVQ $0x00000808, CX BEXTRQ CX, R8, R12 - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decodeSync_safe_bmi2_skip_update LEAQ (SI)(DI*1), R13 ADDQ R8, R13 @@ -3689,8 +3732,7 @@ sequenceDecs_decodeSync_safe_bmi2_fill_2_end: ADDQ CX, R8 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R8*8), R8 // Update Match Length State @@ -3700,8 +3742,7 @@ sequenceDecs_decodeSync_safe_bmi2_fill_2_end: ADDQ CX, DI // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(DI*8), DI // Update Literal Length State @@ -3710,14 +3751,13 @@ sequenceDecs_decodeSync_safe_bmi2_fill_2_end: ADDQ CX, SI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(SI*8), SI sequenceDecs_decodeSync_safe_bmi2_skip_update: // Adjust offset MOVQ s+0(FP), CX - MOVQ 8(SP), R13 + MOVQ 40(SP), R13 CMPQ R12, $0x01 JBE sequenceDecs_decodeSync_safe_bmi2_adjust_offsetB_1_or_0 MOVUPS 144(CX), X0 @@ -3726,7 +3766,7 @@ sequenceDecs_decodeSync_safe_bmi2_skip_update: JMP sequenceDecs_decodeSync_safe_bmi2_after_adjust sequenceDecs_decodeSync_safe_bmi2_adjust_offsetB_1_or_0: - CMPQ 24(SP), $0x00000000 + CMPQ 56(SP), $0x00000000 JNE sequenceDecs_decodeSync_safe_bmi2_adjust_offset_maybezero INCQ R13 JMP sequenceDecs_decodeSync_safe_bmi2_adjust_offset_nonzero @@ -3761,14 +3801,11 @@ sequenceDecs_decodeSync_safe_bmi2_adjust_skip: MOVQ R14, R13 sequenceDecs_decodeSync_safe_bmi2_after_adjust: - MOVQ R13, 8(SP) + MOVQ R13, 40(SP) // Check values - MOVQ 16(SP), CX - MOVQ 24(SP), R12 - LEAQ (CX)(R12*1), R14 - MOVQ s+0(FP), R15 - ADDQ R14, 256(R15) + MOVQ 48(SP), CX + MOVQ 56(SP), R12 MOVQ ctx+16(FP), R14 SUBQ R12, 104(R14) JS error_not_enough_literals @@ -3780,20 +3817,16 @@ sequenceDecs_decodeSync_safe_bmi2_after_adjust: JNZ sequenceDecs_decodeSync_safe_bmi2_error_match_len_ofs_mismatch sequenceDecs_decodeSync_safe_bmi2_match_len_ofs_ok: - MOVQ 24(SP), CX - MOVQ 8(SP), R12 - MOVQ 16(SP), R13 - // Check if we have enough space in s.out - LEAQ (CX)(R13*1), R14 + LEAQ (R12)(CX*1), R14 ADDQ R9, R14 - CMPQ R14, 32(SP) + CMPQ R14, 64(SP) JA error_not_enough_space // Copy literals - TESTQ CX, CX + TESTQ R12, R12 JZ check_offset - MOVQ CX, R14 + MOVQ R12, R14 SUBQ $0x10, R14 JB copy_1_small @@ -3811,20 +3844,20 @@ copy_1_loop: JMP copy_1_end copy_1_small: - CMPQ CX, $0x03 + CMPQ R12, $0x03 JE copy_1_move_3 JB copy_1_move_1or2 - CMPQ CX, $0x08 + CMPQ R12, $0x08 JB copy_1_move_4through7 JMP copy_1_move_8through16 copy_1_move_1or2: MOVB (R10), R14 - MOVB -1(R10)(CX*1), R15 + MOVB -1(R10)(R12*1), R15 MOVB R14, (R9) - MOVB R15, -1(R9)(CX*1) - ADDQ CX, R10 - ADDQ CX, R9 + MOVB R15, -1(R9)(R12*1) + ADDQ R12, R10 + ADDQ R12, R9 JMP copy_1_end copy_1_move_3: @@ -3832,49 +3865,49 @@ copy_1_move_3: MOVB 2(R10), R15 MOVW R14, (R9) MOVB R15, 2(R9) - ADDQ CX, R10 - ADDQ CX, R9 + ADDQ R12, R10 + ADDQ R12, R9 JMP copy_1_end copy_1_move_4through7: MOVL (R10), R14 - MOVL -4(R10)(CX*1), R15 + MOVL -4(R10)(R12*1), R15 MOVL R14, (R9) - MOVL R15, -4(R9)(CX*1) - ADDQ CX, R10 - ADDQ CX, R9 + MOVL R15, -4(R9)(R12*1) + ADDQ R12, R10 + ADDQ R12, R9 JMP copy_1_end copy_1_move_8through16: MOVQ (R10), R14 - MOVQ -8(R10)(CX*1), R15 + MOVQ -8(R10)(R12*1), R15 MOVQ R14, (R9) - MOVQ R15, -8(R9)(CX*1) - ADDQ CX, R10 - ADDQ CX, R9 + MOVQ R15, -8(R9)(R12*1) + ADDQ R12, R10 + ADDQ R12, R9 copy_1_end: - ADDQ CX, R11 + ADDQ R12, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) check_offset: - MOVQ R11, CX - ADDQ 40(SP), CX - CMPQ R12, CX + MOVQ R11, R12 + ADDQ 72(SP), R12 + CMPQ R13, R12 JG error_match_off_too_big - CMPQ R12, 56(SP) + CMPQ R13, 88(SP) JG error_match_off_too_big // Copy match from history - MOVQ R12, CX - SUBQ R11, CX + MOVQ R13, R12 + SUBQ R11, R12 JLS copy_match - MOVQ 48(SP), R14 - SUBQ CX, R14 - CMPQ R13, CX + MOVQ 80(SP), R14 + SUBQ R12, R14 + CMPQ CX, R12 JG copy_all_from_history - MOVQ R13, CX - SUBQ $0x10, CX + MOVQ CX, R12 + SUBQ $0x10, R12 JB copy_4_small copy_4_loop: @@ -3882,54 +3915,54 @@ copy_4_loop: MOVUPS X0, (R9) ADDQ $0x10, R14 ADDQ $0x10, R9 - SUBQ $0x10, CX + SUBQ $0x10, R12 JAE copy_4_loop - LEAQ 16(R14)(CX*1), R14 - LEAQ 16(R9)(CX*1), R9 + LEAQ 16(R14)(R12*1), R14 + LEAQ 16(R9)(R12*1), R9 MOVUPS -16(R14), X0 MOVUPS X0, -16(R9) JMP copy_4_end copy_4_small: - CMPQ R13, $0x03 + CMPQ CX, $0x03 JE copy_4_move_3 - CMPQ R13, $0x08 + CMPQ CX, $0x08 JB copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVWQZX (R14), CX - MOVB 2(R14), R12 - MOVW CX, (R9) - MOVB R12, 2(R9) - ADDQ R13, R14 - ADDQ R13, R9 + MOVWQZX (R14), R12 + MOVB 2(R14), R13 + MOVW R12, (R9) + MOVB R13, 2(R9) + ADDQ CX, R14 + ADDQ CX, R9 JMP copy_4_end copy_4_move_4through7: - MOVL (R14), CX - MOVL -4(R14)(R13*1), R12 - MOVL CX, (R9) - MOVL R12, -4(R9)(R13*1) - ADDQ R13, R14 - ADDQ R13, R9 + MOVL (R14), R12 + MOVL -4(R14)(CX*1), R13 + MOVL R12, (R9) + MOVL R13, -4(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 JMP copy_4_end copy_4_move_8through16: - MOVQ (R14), CX - MOVQ -8(R14)(R13*1), R12 - MOVQ CX, (R9) - MOVQ R12, -8(R9)(R13*1) - ADDQ R13, R14 - ADDQ R13, R9 + MOVQ (R14), R12 + MOVQ -8(R14)(CX*1), R13 + MOVQ R12, (R9) + MOVQ R13, -8(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 copy_4_end: - ADDQ R13, R11 + ADDQ CX, R11 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVQ CX, R15 + MOVQ R12, R15 SUBQ $0x10, R15 JB copy_5_small @@ -3947,20 +3980,20 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMPQ CX, $0x03 + CMPQ R12, $0x03 JE copy_5_move_3 JB copy_5_move_1or2 - CMPQ CX, $0x08 + CMPQ R12, $0x08 JB copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVB (R14), R15 - MOVB -1(R14)(CX*1), BP + MOVB -1(R14)(R12*1), BP MOVB R15, (R9) - MOVB BP, -1(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVB BP, -1(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_3: @@ -3968,120 +4001,119 @@ copy_5_move_3: MOVB 2(R14), BP MOVW R15, (R9) MOVB BP, 2(R9) - ADDQ CX, R14 - ADDQ CX, R9 + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 - MOVL -4(R14)(CX*1), BP + MOVL -4(R14)(R12*1), BP MOVL R15, (R9) - MOVL BP, -4(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVL BP, -4(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_8through16: MOVQ (R14), R15 - MOVQ -8(R14)(CX*1), BP + MOVQ -8(R14)(R12*1), BP MOVQ R15, (R9) - MOVQ BP, -8(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVQ BP, -8(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 copy_5_end: - ADDQ CX, R11 - SUBQ CX, R13 + ADDQ R12, R11 + SUBQ R12, CX // Copy match from the current buffer copy_match: - MOVQ R9, CX - SUBQ R12, CX + MOVQ R9, R12 + SUBQ R13, R12 // ml <= mo - CMPQ R13, R12 + CMPQ CX, R13 JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, R11 - MOVQ R13, R12 - SUBQ $0x10, R12 + ADDQ CX, R11 + MOVQ CX, R13 + SUBQ $0x10, R13 JB copy_2_small copy_2_loop: - MOVUPS (CX), X0 + MOVUPS (R12), X0 MOVUPS X0, (R9) - ADDQ $0x10, CX + ADDQ $0x10, R12 ADDQ $0x10, R9 - SUBQ $0x10, R12 + SUBQ $0x10, R13 JAE copy_2_loop - LEAQ 16(CX)(R12*1), CX - LEAQ 16(R9)(R12*1), R9 - MOVUPS -16(CX), X0 + LEAQ 16(R12)(R13*1), R12 + LEAQ 16(R9)(R13*1), R9 + MOVUPS -16(R12), X0 MOVUPS X0, -16(R9) JMP copy_2_end copy_2_small: - CMPQ R13, $0x03 + CMPQ CX, $0x03 JE copy_2_move_3 JB copy_2_move_1or2 - CMPQ R13, $0x08 + CMPQ CX, $0x08 JB copy_2_move_4through7 JMP copy_2_move_8through16 copy_2_move_1or2: - MOVB (CX), R12 - MOVB -1(CX)(R13*1), R14 - MOVB R12, (R9) - MOVB R14, -1(R9)(R13*1) - ADDQ R13, CX - ADDQ R13, R9 + MOVB (R12), R13 + MOVB -1(R12)(CX*1), R14 + MOVB R13, (R9) + MOVB R14, -1(R9)(CX*1) + ADDQ CX, R12 + ADDQ CX, R9 JMP copy_2_end copy_2_move_3: - MOVWQZX (CX), R12 - MOVB 2(CX), R14 - MOVW R12, (R9) + MOVWQZX (R12), R13 + MOVB 2(R12), R14 + MOVW R13, (R9) MOVB R14, 2(R9) - ADDQ R13, CX - ADDQ R13, R9 + ADDQ CX, R12 + ADDQ CX, R9 JMP copy_2_end copy_2_move_4through7: - MOVL (CX), R12 - MOVL -4(CX)(R13*1), R14 - MOVL R12, (R9) - MOVL R14, -4(R9)(R13*1) - ADDQ R13, CX - ADDQ R13, R9 + MOVL (R12), R13 + MOVL -4(R12)(CX*1), R14 + MOVL R13, (R9) + MOVL R14, -4(R9)(CX*1) + ADDQ CX, R12 + ADDQ CX, R9 JMP copy_2_end copy_2_move_8through16: - MOVQ (CX), R12 - MOVQ -8(CX)(R13*1), R14 - MOVQ R12, (R9) - MOVQ R14, -8(R9)(R13*1) - ADDQ R13, CX - ADDQ R13, R9 + MOVQ (R12), R13 + MOVQ -8(R12)(CX*1), R14 + MOVQ R13, (R9) + MOVQ R14, -8(R9)(CX*1) + ADDQ CX, R12 + ADDQ CX, R9 copy_2_end: JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADDQ R13, R11 + ADDQ CX, R11 copy_slow_3: - MOVBQZX (CX), R12 - MOVB R12, (R9) - INCQ CX + MOVBQZX (R12), R13 + MOVB R13, (R9) + INCQ R12 INCQ R9 - DECQ R13 + DECQ CX JNZ copy_slow_3 handle_loop: - MOVQ ctx+16(FP), CX - DECQ 96(CX) + DECQ 32(SP) JNS sequenceDecs_decodeSync_safe_bmi2_main_loop loop_finished: @@ -4090,6 +4122,13 @@ loop_finished: MOVB DL, 40(CX) MOVQ BX, 32(CX) + // s.seqSize += outPosition - ctx.outPosition + MOVQ ctx+16(FP), AX + MOVQ s+0(FP), CX + MOVQ R11, DX + SUBQ 136(AX), DX + ADDQ DX, 256(CX) + // Update the context MOVQ ctx+16(FP), AX MOVQ R11, 136(AX) @@ -4103,7 +4142,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_safe_bmi2_error_match_len_ofs_mismatch: - MOVQ 16(SP), AX + MOVQ 48(SP), AX MOVQ ctx+16(FP), CX MOVQ AX, 216(CX) MOVQ $0x00000001, ret+24(FP) @@ -4112,7 +4151,7 @@ sequenceDecs_decodeSync_safe_bmi2_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_safe_bmi2_error_match_len_too_big: MOVQ ctx+16(FP), AX - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ $0x00000002, ret+24(FP) RET @@ -4120,7 +4159,7 @@ sequenceDecs_decodeSync_safe_bmi2_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVQ ctx+16(FP), AX - MOVQ 8(SP), CX + MOVQ 40(SP), CX MOVQ CX, 224(AX) MOVQ R11, 136(AX) MOVQ $0x00000003, ret+24(FP) @@ -4129,7 +4168,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) MOVQ $0x00000004, ret+24(FP) RET @@ -4142,9 +4181,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ R11, 136(AX) MOVQ $0x00000005, ret+24(FP) diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s index fa48be19e4..56391bfc18 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s @@ -5,7 +5,7 @@ // func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV -TEXT ·sequenceDecs_decode_arm64(SB), $8-32 +TEXT ·sequenceDecs_decode_arm64(SB), $40-32 MOVD br+8(FP), R1 MOVD 24(R1), R2 MOVBU 40(R1), R3 @@ -17,6 +17,14 @@ TEXT ·sequenceDecs_decode_arm64(SB), $8-32 MOVD 72(R0), R6 MOVD 80(R0), R7 MOVD 88(R0), R8 + MOVD (R0), R1 + MOVD R1, 16(RSP) + MOVD 24(R0), R1 + MOVD R1, 24(RSP) + MOVD 48(R0), R1 + MOVD R1, 32(RSP) + MOVD 96(R0), R1 + MOVD R1, 40(RSP) MOVD 104(R0), R9 MOVD s+0(FP), R0 MOVD 144(R0), R10 @@ -29,8 +37,7 @@ sequenceDecs_decode_amd64_main_loop: // Fill bitreader to have enough for the offset and match length. CMP $0x08, R5 BLT sequenceDecs_decode_amd64_fill_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R13, R13 MOVD (R13), R2 SUB R0, R5, R5 @@ -57,51 +64,32 @@ sequenceDecs_decode_amd64_fill_check_overread: sequenceDecs_decode_amd64_fill_end: // Update offset MOVD R8, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_amd64_of_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_amd64_of_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_amd64_of_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_amd64_of_update_zero: MOVD R0, 16(R9) // Update match length MOVD R7, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_amd64_ml_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_amd64_ml_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_amd64_ml_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_amd64_ml_update_zero: MOVD R0, 8(R9) // Fill bitreader to have enough for the remaining CMP $0x08, R5 BLT sequenceDecs_decode_amd64_fill_2_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R13, R13 MOVD (R13), R2 SUB R0, R5, R5 @@ -128,91 +116,63 @@ sequenceDecs_decode_amd64_fill_2_check_overread: sequenceDecs_decode_amd64_fill_2_end: // Update literal length MOVD R6, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_amd64_ll_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_amd64_ll_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_amd64_ll_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_amd64_ll_update_zero: MOVD R0, (R9) // Fill bitreader for state updates MOVD R13, 8(RSP) UBFX $8, R8, $8, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 + MOVD 40(RSP), R16 CMP $0x00, R16 BEQ sequenceDecs_decode_amd64_skip_update // Update Literal Length State MOVBU R6, R13 LSRW $0x10, R6, R6 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVBU R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R6, R6 // Load ctx.llTable - MOVD ctx+16(FP), R1 - MOVD (R1), R1 + MOVD 16(RSP), R1 MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R13 LSRW $0x10, R7, R7 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVBU R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R7, R7 // Load ctx.mlTable - MOVD ctx+16(FP), R1 - MOVD 24(R1), R1 + MOVD 24(RSP), R1 MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R13 LSRW $0x10, R8, R8 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVBU R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R8, R8 // Load ctx.ofTable - MOVD ctx+16(FP), R1 - MOVD 48(R1), R1 + MOVD 32(RSP), R1 MOVD (R1)(R8<<3), R8 sequenceDecs_decode_amd64_skip_update: @@ -298,10 +258,9 @@ sequenceDecs_decode_amd64_after_adjust: sequenceDecs_decode_amd64_match_len_ofs_ok: ADD $0x18, R9, R9 - MOVD ctx+16(FP), R0 - MOVD 96(R0), R16 + MOVD 40(RSP), R16 SUBS $1, R16, R16 - MOVD R16, 96(R0) + MOVD R16, 40(RSP) BPL sequenceDecs_decode_amd64_main_loop MOVD s+0(FP), R0 MOVD R10, 144(R0) @@ -313,42 +272,60 @@ sequenceDecs_decode_amd64_match_len_ofs_ok: MOVD R5, 32(R0) // Return success + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000000, R16 MOVD R16, ret+24(FP) RET // Return with match length error sequenceDecs_decode_amd64_error_match_len_ofs_mismatch: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000001, R16 MOVD R16, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_amd64_error_match_len_too_big: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000002, R16 MOVD R16, ret+24(FP) RET // Return with match offset too long error + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000003, R16 MOVD R16, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000004, R16 MOVD R16, ret+24(FP) RET // Return with overread error error_overread: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000006, R16 MOVD R16, ret+24(FP) RET // func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV -TEXT ·sequenceDecs_decode_56_arm64(SB), $8-32 +TEXT ·sequenceDecs_decode_56_arm64(SB), $40-32 MOVD br+8(FP), R1 MOVD 24(R1), R2 MOVBU 40(R1), R3 @@ -360,6 +337,14 @@ TEXT ·sequenceDecs_decode_56_arm64(SB), $8-32 MOVD 72(R0), R6 MOVD 80(R0), R7 MOVD 88(R0), R8 + MOVD (R0), R1 + MOVD R1, 16(RSP) + MOVD 24(R0), R1 + MOVD R1, 24(RSP) + MOVD 48(R0), R1 + MOVD R1, 32(RSP) + MOVD 96(R0), R1 + MOVD R1, 40(RSP) MOVD 104(R0), R9 MOVD s+0(FP), R0 MOVD 144(R0), R10 @@ -372,8 +357,7 @@ sequenceDecs_decode_56_amd64_main_loop: // Fill bitreader to have enough for the offset and match length. CMP $0x08, R5 BLT sequenceDecs_decode_56_amd64_fill_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R13, R13 MOVD (R13), R2 SUB R0, R5, R5 @@ -400,133 +384,87 @@ sequenceDecs_decode_56_amd64_fill_check_overread: sequenceDecs_decode_56_amd64_fill_end: // Update offset MOVD R8, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_56_amd64_of_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_56_amd64_of_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_56_amd64_of_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_56_amd64_of_update_zero: MOVD R0, 16(R9) // Update match length MOVD R7, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_56_amd64_ml_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_56_amd64_ml_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_56_amd64_ml_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_56_amd64_ml_update_zero: MOVD R0, 8(R9) // Update literal length MOVD R6, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_56_amd64_ll_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_56_amd64_ll_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_56_amd64_ll_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_56_amd64_ll_update_zero: MOVD R0, (R9) // Fill bitreader for state updates MOVD R13, 8(RSP) UBFX $8, R8, $8, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 + MOVD 40(RSP), R16 CMP $0x00, R16 BEQ sequenceDecs_decode_56_amd64_skip_update // Update Literal Length State MOVBU R6, R13 LSRW $0x10, R6, R6 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVBU R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R6, R6 // Load ctx.llTable - MOVD ctx+16(FP), R1 - MOVD (R1), R1 + MOVD 16(RSP), R1 MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R13 LSRW $0x10, R7, R7 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVBU R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R7, R7 // Load ctx.mlTable - MOVD ctx+16(FP), R1 - MOVD 24(R1), R1 + MOVD 24(RSP), R1 MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R13 LSRW $0x10, R8, R8 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVBU R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R8, R8 // Load ctx.ofTable - MOVD ctx+16(FP), R1 - MOVD 48(R1), R1 + MOVD 32(RSP), R1 MOVD (R1)(R8<<3), R8 sequenceDecs_decode_56_amd64_skip_update: @@ -612,10 +550,9 @@ sequenceDecs_decode_56_amd64_after_adjust: sequenceDecs_decode_56_amd64_match_len_ofs_ok: ADD $0x18, R9, R9 - MOVD ctx+16(FP), R0 - MOVD 96(R0), R16 + MOVD 40(RSP), R16 SUBS $1, R16, R16 - MOVD R16, 96(R0) + MOVD R16, 40(RSP) BPL sequenceDecs_decode_56_amd64_main_loop MOVD s+0(FP), R0 MOVD R10, 144(R0) @@ -627,35 +564,53 @@ sequenceDecs_decode_56_amd64_match_len_ofs_ok: MOVD R5, 32(R0) // Return success + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000000, R16 MOVD R16, ret+24(FP) RET // Return with match length error sequenceDecs_decode_56_amd64_error_match_len_ofs_mismatch: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000001, R16 MOVD R16, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_56_amd64_error_match_len_too_big: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000002, R16 MOVD R16, ret+24(FP) RET // Return with match offset too long error + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000003, R16 MOVD R16, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000004, R16 MOVD R16, ret+24(FP) RET // Return with overread error error_overread: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000006, R16 MOVD R16, ret+24(FP) RET @@ -695,9 +650,11 @@ main_loop: MOVD 8(R0), R12 // Copy literals - TST R10, R10 - BEQ check_offset - MOVD $0, R13 + FMOVQ (R5), F0 + FMOVQ F0, (R3) + CMP $0x10, R10 + BLS copy_1_end + MOVD $0x00000010, R13 copy_1: ADD R13, R5, R15 @@ -707,12 +664,13 @@ copy_1: ADD $0x10, R13, R13 CMP R10, R13 BLO copy_1 - ADD R10, R5, R5 - ADD R10, R3, R3 - ADD R10, R6, R6 + +copy_1_end: + ADD R10, R5, R5 + ADD R10, R3, R3 + ADD R10, R6, R6 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: ADD R9, R6, R10 CMP R10, R11 BGT error_match_off_too_big @@ -878,9 +836,19 @@ copy_match: BHI copy_overlapping_match // Copy non-overlapping match - ADD R12, R6, R6 - MOVD R3, R11 - ADD R12, R3, R3 + ADD R12, R6, R6 + FMOVQ (R10), F0 + FMOVQ F0, (R3) + CMP $0x10, R12 + BHI copy_2_long + ADD R12, R3, R3 + JMP handle_loop + +copy_2_long: + ADD $16, R3, R11 + ADD R12, R3, R3 + ADD $0x10, R10, R10 + SUB $0x10, R12, R12 copy_2: FMOVQ (R10), F0 @@ -1346,7 +1314,7 @@ empty_seqs: // func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: CMOV, SSE -TEXT ·sequenceDecs_decodeSync_arm64(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_arm64(SB), $96-32 MOVD br+8(FP), R1 MOVD 24(R1), R2 MOVBU 40(R1), R3 @@ -1358,30 +1326,38 @@ TEXT ·sequenceDecs_decodeSync_arm64(SB), $64-32 MOVD 72(R0), R6 MOVD 80(R0), R7 MOVD 88(R0), R8 - MOVD $0, R1 + MOVD (R0), R1 MOVD R1, 16(RSP) + MOVD 24(R0), R1 MOVD R1, 24(RSP) + MOVD 48(R0), R1 MOVD R1, 32(RSP) + MOVD 96(R0), R1 + MOVD R1, 40(RSP) + MOVD $0, R1 + MOVD R1, 48(RSP) + MOVD R1, 56(RSP) + MOVD R1, 64(RSP) MOVD 112(R0), R9 MOVD 128(R0), R1 - MOVD R1, 40(RSP) + MOVD R1, 72(RSP) MOVD 144(R0), R10 MOVD 136(R0), R11 MOVD 200(R0), R1 - MOVD R1, 64(RSP) + MOVD R1, 96(RSP) MOVD 176(R0), R1 - MOVD R1, 56(RSP) + MOVD R1, 88(RSP) MOVD 184(R0), R0 - MOVD R0, 48(RSP) - MOVD 48(RSP), R0 - MOVD 56(RSP), R16 + MOVD R0, 80(RSP) + MOVD 80(RSP), R0 + MOVD 88(RSP), R16 ADD R0, R16, R16 - MOVD R16, 56(RSP) + MOVD R16, 88(RSP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - MOVD 40(RSP), R16 + MOVD 72(RSP), R16 ADD R9, R16, R16 - MOVD R16, 40(RSP) + MOVD R16, 72(RSP) // outBase += outPosition ADD R11, R9, R9 @@ -1392,8 +1368,7 @@ sequenceDecs_decodeSync_amd64_main_loop: // Fill bitreader to have enough for the offset and match length. CMP $0x08, R5 BLT sequenceDecs_decodeSync_amd64_fill_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R12, R12 MOVD (R12), R2 SUB R0, R5, R5 @@ -1420,51 +1395,32 @@ sequenceDecs_decodeSync_amd64_fill_check_overread: sequenceDecs_decodeSync_amd64_fill_end: // Update offset MOVD R8, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_amd64_of_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_amd64_of_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_amd64_of_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_amd64_of_update_zero: - MOVD R0, 16(RSP) + MOVD R0, 48(RSP) // Update match length MOVD R7, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_amd64_ml_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_amd64_ml_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_amd64_ml_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_amd64_ml_update_zero: - MOVD R0, 24(RSP) + MOVD R0, 56(RSP) // Fill bitreader to have enough for the remaining CMP $0x08, R5 BLT sequenceDecs_decodeSync_amd64_fill_2_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R12, R12 MOVD (R12), R2 SUB R0, R5, R5 @@ -1491,97 +1447,69 @@ sequenceDecs_decodeSync_amd64_fill_2_check_overread: sequenceDecs_decodeSync_amd64_fill_2_end: // Update literal length MOVD R6, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_amd64_ll_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_amd64_ll_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_amd64_ll_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_amd64_ll_update_zero: - MOVD R0, 32(RSP) + MOVD R0, 64(RSP) // Fill bitreader for state updates MOVD R12, 8(RSP) UBFX $8, R8, $8, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 + MOVD 40(RSP), R16 CMP $0x00, R16 BEQ sequenceDecs_decodeSync_amd64_skip_update // Update Literal Length State MOVBU R6, R12 LSRW $0x10, R6, R6 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVBU R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R6, R6 // Load ctx.llTable - MOVD ctx+16(FP), R1 - MOVD (R1), R1 + MOVD 16(RSP), R1 MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R12 LSRW $0x10, R7, R7 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVBU R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R7, R7 // Load ctx.mlTable - MOVD ctx+16(FP), R1 - MOVD 24(R1), R1 + MOVD 24(RSP), R1 MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R12 LSRW $0x10, R8, R8 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVBU R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R8, R8 // Load ctx.ofTable - MOVD ctx+16(FP), R1 - MOVD 48(R1), R1 + MOVD 32(RSP), R1 MOVD (R1)(R8<<3), R8 sequenceDecs_decodeSync_amd64_skip_update: // Adjust offset MOVD s+0(FP), R1 - MOVD 16(RSP), R12 + MOVD 48(RSP), R12 CMP $0x01, R0 BLS sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 FMOVQ 144(R1), F0 @@ -1590,7 +1518,7 @@ sequenceDecs_decodeSync_amd64_skip_update: JMP sequenceDecs_decodeSync_amd64_after_adjust sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0: - MOVD 32(RSP), R16 + MOVD 64(RSP), R16 CMP $0x00000000, R16 BNE sequenceDecs_decodeSync_amd64_adjust_offset_maybezero ADD $1, R12, R12 @@ -1628,16 +1556,11 @@ sequenceDecs_decodeSync_amd64_adjust_skip: MOVD R13, R12 sequenceDecs_decodeSync_amd64_after_adjust: - MOVD R12, 16(RSP) + MOVD R12, 48(RSP) // Check values - MOVD 24(RSP), R0 - MOVD 32(RSP), R1 - ADD R1, R0, R13 - MOVD s+0(FP), R14 - MOVD 256(R14), R16 - ADD R13, R16, R16 - MOVD R16, 256(R14) + MOVD 56(RSP), R0 + MOVD 64(RSP), R1 MOVD ctx+16(FP), R13 MOVD 104(R13), R16 SUBS R1, R16, R16 @@ -1651,22 +1574,20 @@ sequenceDecs_decodeSync_amd64_after_adjust: BNE sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch sequenceDecs_decodeSync_amd64_match_len_ofs_ok: - MOVD 32(RSP), R0 - MOVD 16(RSP), R1 - MOVD 24(RSP), R12 - // Check if we have enough space in s.out - ADD R12, R0, R13 + ADD R0, R1, R13 ADD $16, R13, R13 ADD R9, R13, R13 - MOVD 40(RSP), R16 + MOVD 72(RSP), R16 CMP R16, R13 BHI error_not_enough_space // Copy literals - TST R0, R0 - BEQ check_offset - MOVD $0, R13 + FMOVQ (R10), F0 + FMOVQ F0, (R9) + CMP $0x10, R1 + BLS copy_1_end + MOVD $0x00000010, R13 copy_1: ADD R13, R10, R15 @@ -1674,33 +1595,34 @@ copy_1: ADD R13, R9, R15 FMOVQ F0, (R15) ADD $0x10, R13, R13 - CMP R0, R13 + CMP R1, R13 BLO copy_1 - ADD R0, R10, R10 - ADD R0, R9, R9 - ADD R0, R11, R11 + +copy_1_end: + ADD R1, R10, R10 + ADD R1, R9, R9 + ADD R1, R11, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: - MOVD R11, R0 - MOVD 48(RSP), R16 - ADD R16, R0, R0 - CMP R0, R1 + MOVD R11, R1 + MOVD 80(RSP), R16 + ADD R16, R1, R1 + CMP R1, R12 BGT error_match_off_too_big - MOVD 64(RSP), R16 - CMP R16, R1 + MOVD 96(RSP), R16 + CMP R16, R12 BGT error_match_off_too_big // Copy match from history - MOVD R1, R0 - SUBS R11, R0, R0 + MOVD R12, R1 + SUBS R11, R1, R1 BLS copy_match - MOVD 56(RSP), R13 - SUB R0, R13, R13 - CMP R0, R12 + MOVD 88(RSP), R13 + SUB R1, R13, R13 + CMP R1, R0 BGT copy_all_from_history - MOVD R12, R0 - SUBS $0x10, R0, R0 + MOVD R0, R1 + SUBS $0x10, R1, R1 BLO copy_4_small copy_4_loop: @@ -1708,61 +1630,61 @@ copy_4_loop: FMOVQ F0, (R9) ADD $0x10, R13, R13 ADD $0x10, R9, R9 - SUBS $0x10, R0, R0 + SUBS $0x10, R1, R1 BHS copy_4_loop - ADD R0, R13, R13 + ADD R1, R13, R13 ADD $16, R13, R13 - ADD R0, R9, R9 + ADD R1, R9, R9 ADD $16, R9, R9 FMOVQ -16(R13), F0 FMOVQ F0, -16(R9) JMP copy_4_end copy_4_small: - CMP $0x03, R12 + CMP $0x03, R0 BEQ copy_4_move_3 - CMP $0x08, R12 + CMP $0x08, R0 BLO copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVHU (R13), R0 + MOVHU (R13), R1 MOVBU 2(R13), R16 - BFI $0, R16, $8, R1 - MOVH R0, (R9) - MOVB R1, 2(R9) - ADD R12, R13, R13 - ADD R12, R9, R9 + BFI $0, R16, $8, R12 + MOVH R1, (R9) + MOVB R12, 2(R9) + ADD R0, R13, R13 + ADD R0, R9, R9 JMP copy_4_end copy_4_move_4through7: - MOVWU (R13), R0 - ADD R12, R13, R15 - MOVWU -4(R15), R1 - MOVW R0, (R9) - ADD R12, R9, R15 - MOVW R1, -4(R15) - ADD R12, R13, R13 - ADD R12, R9, R9 + MOVWU (R13), R1 + ADD R0, R13, R15 + MOVWU -4(R15), R12 + MOVW R1, (R9) + ADD R0, R9, R15 + MOVW R12, -4(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 JMP copy_4_end copy_4_move_8through16: - MOVD (R13), R0 - ADD R12, R13, R15 - MOVD -8(R15), R1 - MOVD R0, (R9) - ADD R12, R9, R15 - MOVD R1, -8(R15) - ADD R12, R13, R13 - ADD R12, R9, R9 + MOVD (R13), R1 + ADD R0, R13, R15 + MOVD -8(R15), R12 + MOVD R1, (R9) + ADD R0, R9, R15 + MOVD R12, -8(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 copy_4_end: - ADD R12, R11, R11 + ADD R0, R11, R11 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVD R0, R14 + MOVD R1, R14 SUBS $0x10, R14, R14 BLO copy_5_small @@ -1782,24 +1704,24 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMP $0x03, R0 + CMP $0x03, R1 BEQ copy_5_move_3 BLO copy_5_move_1or2 - CMP $0x08, R0 + CMP $0x08, R1 BLO copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVBU (R13), R16 BFI $0, R16, $8, R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVBU -1(R15), R16 BFI $0, R16, $8, R4 MOVB R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVB R4, -1(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 JMP copy_5_end copy_5_move_3: @@ -1808,75 +1730,84 @@ copy_5_move_3: BFI $0, R16, $8, R4 MOVH R14, (R9) MOVB R4, 2(R9) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 JMP copy_5_end copy_5_move_4through7: MOVWU (R13), R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVWU -4(R15), R4 MOVW R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVW R4, -4(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 JMP copy_5_end copy_5_move_8through16: MOVD (R13), R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVD -8(R15), R4 MOVD R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVD R4, -8(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 copy_5_end: - ADD R0, R11, R11 - SUB R0, R12, R12 + ADD R1, R11, R11 + SUB R1, R0, R0 // Copy match from the current buffer copy_match: - MOVD R9, R0 - SUB R1, R0, R0 + MOVD R9, R1 + SUB R12, R1, R1 // ml <= mo - CMP R1, R12 + CMP R12, R0 BHI copy_overlapping_match // Copy non-overlapping match - ADD R12, R11, R11 - MOVD R9, R1 - ADD R12, R9, R9 + ADD R0, R11, R11 + FMOVQ (R1), F0 + FMOVQ F0, (R9) + CMP $0x10, R0 + BHI copy_2_long + ADD R0, R9, R9 + JMP handle_loop + +copy_2_long: + ADD $16, R9, R12 + ADD R0, R9, R9 + ADD $0x10, R1, R1 + SUB $0x10, R0, R0 copy_2: - FMOVQ (R0), F0 - FMOVQ F0, (R1) - ADD $0x10, R0, R0 + FMOVQ (R1), F0 + FMOVQ F0, (R12) ADD $0x10, R1, R1 - SUBS $0x10, R12, R12 + ADD $0x10, R12, R12 + SUBS $0x10, R0, R0 BHI copy_2 JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADD R12, R11, R11 + ADD R0, R11, R11 copy_slow_3: - MOVBU (R0), R1 - MOVB R1, (R9) - ADD $1, R0, R0 + MOVBU (R1), R12 + MOVB R12, (R9) + ADD $1, R1, R1 ADD $1, R9, R9 - SUBS $1, R12, R12 + SUBS $1, R0, R0 BNE copy_slow_3 handle_loop: - MOVD ctx+16(FP), R0 - MOVD 96(R0), R16 + MOVD 40(RSP), R16 SUBS $1, R16, R16 - MOVD R16, 96(R0) + MOVD R16, 40(RSP) BPL sequenceDecs_decodeSync_amd64_main_loop loop_finished: @@ -1885,6 +1816,16 @@ loop_finished: MOVB R3, 40(R0) MOVD R5, 32(R0) + // s.seqSize += outPosition - ctx.outPosition + MOVD ctx+16(FP), R0 + MOVD s+0(FP), R1 + MOVD R11, R2 + MOVD 136(R0), R16 + SUB R16, R2, R2 + MOVD 256(R1), R16 + ADD R2, R16, R16 + MOVD R16, 256(R1) + // Update the context MOVD ctx+16(FP), R0 MOVD R11, 136(R0) @@ -1899,7 +1840,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: - MOVD 24(RSP), R0 + MOVD 56(RSP), R0 MOVD ctx+16(FP), R1 MOVD R0, 216(R1) MOVD $0x00000001, R16 @@ -1909,7 +1850,7 @@ sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_amd64_error_match_len_too_big: MOVD ctx+16(FP), R0 - MOVD 24(RSP), R1 + MOVD 56(RSP), R1 MOVD R1, 216(R0) MOVD $0x00000002, R16 MOVD R16, ret+24(FP) @@ -1918,7 +1859,7 @@ sequenceDecs_decodeSync_amd64_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVD ctx+16(FP), R0 - MOVD 16(RSP), R1 + MOVD 48(RSP), R1 MOVD R1, 224(R0) MOVD R11, 136(R0) MOVD $0x00000003, R16 @@ -1928,7 +1869,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVD ctx+16(FP), R0 - MOVD 32(RSP), R1 + MOVD 64(RSP), R1 MOVD R1, 208(R0) MOVD $0x00000004, R16 MOVD R16, ret+24(FP) @@ -1943,9 +1884,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVD ctx+16(FP), R0 - MOVD 32(RSP), R1 + MOVD 64(RSP), R1 MOVD R1, 208(R0) - MOVD 24(RSP), R1 + MOVD 56(RSP), R1 MOVD R1, 216(R0) MOVD R11, 136(R0) MOVD $0x00000005, R16 @@ -1956,7 +1897,7 @@ error_not_enough_space: // func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: CMOV, SSE -TEXT ·sequenceDecs_decodeSync_safe_arm64(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_safe_arm64(SB), $96-32 MOVD br+8(FP), R1 MOVD 24(R1), R2 MOVBU 40(R1), R3 @@ -1968,30 +1909,38 @@ TEXT ·sequenceDecs_decodeSync_safe_arm64(SB), $64-32 MOVD 72(R0), R6 MOVD 80(R0), R7 MOVD 88(R0), R8 - MOVD $0, R1 + MOVD (R0), R1 MOVD R1, 16(RSP) + MOVD 24(R0), R1 MOVD R1, 24(RSP) + MOVD 48(R0), R1 MOVD R1, 32(RSP) + MOVD 96(R0), R1 + MOVD R1, 40(RSP) + MOVD $0, R1 + MOVD R1, 48(RSP) + MOVD R1, 56(RSP) + MOVD R1, 64(RSP) MOVD 112(R0), R9 MOVD 128(R0), R1 - MOVD R1, 40(RSP) + MOVD R1, 72(RSP) MOVD 144(R0), R10 MOVD 136(R0), R11 MOVD 200(R0), R1 - MOVD R1, 64(RSP) + MOVD R1, 96(RSP) MOVD 176(R0), R1 - MOVD R1, 56(RSP) + MOVD R1, 88(RSP) MOVD 184(R0), R0 - MOVD R0, 48(RSP) - MOVD 48(RSP), R0 - MOVD 56(RSP), R16 + MOVD R0, 80(RSP) + MOVD 80(RSP), R0 + MOVD 88(RSP), R16 ADD R0, R16, R16 - MOVD R16, 56(RSP) + MOVD R16, 88(RSP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - MOVD 40(RSP), R16 + MOVD 72(RSP), R16 ADD R9, R16, R16 - MOVD R16, 40(RSP) + MOVD R16, 72(RSP) // outBase += outPosition ADD R11, R9, R9 @@ -2002,8 +1951,7 @@ sequenceDecs_decodeSync_safe_amd64_main_loop: // Fill bitreader to have enough for the offset and match length. CMP $0x08, R5 BLT sequenceDecs_decodeSync_safe_amd64_fill_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R12, R12 MOVD (R12), R2 SUB R0, R5, R5 @@ -2030,51 +1978,32 @@ sequenceDecs_decodeSync_safe_amd64_fill_check_overread: sequenceDecs_decodeSync_safe_amd64_fill_end: // Update offset MOVD R8, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_safe_amd64_of_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_safe_amd64_of_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_safe_amd64_of_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_safe_amd64_of_update_zero: - MOVD R0, 16(RSP) + MOVD R0, 48(RSP) // Update match length MOVD R7, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_safe_amd64_ml_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_safe_amd64_ml_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_safe_amd64_ml_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_safe_amd64_ml_update_zero: - MOVD R0, 24(RSP) + MOVD R0, 56(RSP) // Fill bitreader to have enough for the remaining CMP $0x08, R5 BLT sequenceDecs_decodeSync_safe_amd64_fill_2_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R12, R12 MOVD (R12), R2 SUB R0, R5, R5 @@ -2101,97 +2030,69 @@ sequenceDecs_decodeSync_safe_amd64_fill_2_check_overread: sequenceDecs_decodeSync_safe_amd64_fill_2_end: // Update literal length MOVD R6, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_safe_amd64_ll_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_safe_amd64_ll_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_safe_amd64_ll_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_safe_amd64_ll_update_zero: - MOVD R0, 32(RSP) + MOVD R0, 64(RSP) // Fill bitreader for state updates MOVD R12, 8(RSP) UBFX $8, R8, $8, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 + MOVD 40(RSP), R16 CMP $0x00, R16 BEQ sequenceDecs_decodeSync_safe_amd64_skip_update // Update Literal Length State MOVBU R6, R12 LSRW $0x10, R6, R6 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVBU R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R6, R6 // Load ctx.llTable - MOVD ctx+16(FP), R1 - MOVD (R1), R1 + MOVD 16(RSP), R1 MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R12 LSRW $0x10, R7, R7 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVBU R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R7, R7 // Load ctx.mlTable - MOVD ctx+16(FP), R1 - MOVD 24(R1), R1 + MOVD 24(RSP), R1 MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R12 LSRW $0x10, R8, R8 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVBU R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R8, R8 // Load ctx.ofTable - MOVD ctx+16(FP), R1 - MOVD 48(R1), R1 + MOVD 32(RSP), R1 MOVD (R1)(R8<<3), R8 sequenceDecs_decodeSync_safe_amd64_skip_update: // Adjust offset MOVD s+0(FP), R1 - MOVD 16(RSP), R12 + MOVD 48(RSP), R12 CMP $0x01, R0 BLS sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 FMOVQ 144(R1), F0 @@ -2200,7 +2101,7 @@ sequenceDecs_decodeSync_safe_amd64_skip_update: JMP sequenceDecs_decodeSync_safe_amd64_after_adjust sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0: - MOVD 32(RSP), R16 + MOVD 64(RSP), R16 CMP $0x00000000, R16 BNE sequenceDecs_decodeSync_safe_amd64_adjust_offset_maybezero ADD $1, R12, R12 @@ -2238,16 +2139,11 @@ sequenceDecs_decodeSync_safe_amd64_adjust_skip: MOVD R13, R12 sequenceDecs_decodeSync_safe_amd64_after_adjust: - MOVD R12, 16(RSP) + MOVD R12, 48(RSP) // Check values - MOVD 24(RSP), R0 - MOVD 32(RSP), R1 - ADD R1, R0, R13 - MOVD s+0(FP), R14 - MOVD 256(R14), R16 - ADD R13, R16, R16 - MOVD R16, 256(R14) + MOVD 56(RSP), R0 + MOVD 64(RSP), R1 MOVD ctx+16(FP), R13 MOVD 104(R13), R16 SUBS R1, R16, R16 @@ -2261,21 +2157,17 @@ sequenceDecs_decodeSync_safe_amd64_after_adjust: BNE sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok: - MOVD 32(RSP), R0 - MOVD 16(RSP), R1 - MOVD 24(RSP), R12 - // Check if we have enough space in s.out - ADD R12, R0, R13 + ADD R0, R1, R13 ADD R9, R13, R13 - MOVD 40(RSP), R16 + MOVD 72(RSP), R16 CMP R16, R13 BHI error_not_enough_space // Copy literals - TST R0, R0 + TST R1, R1 BEQ check_offset - MOVD R0, R13 + MOVD R1, R13 SUBS $0x10, R13, R13 BLO copy_1_small @@ -2295,24 +2187,24 @@ copy_1_loop: JMP copy_1_end copy_1_small: - CMP $0x03, R0 + CMP $0x03, R1 BEQ copy_1_move_3 BLO copy_1_move_1or2 - CMP $0x08, R0 + CMP $0x08, R1 BLO copy_1_move_4through7 JMP copy_1_move_8through16 copy_1_move_1or2: MOVBU (R10), R16 BFI $0, R16, $8, R13 - ADD R0, R10, R15 + ADD R1, R10, R15 MOVBU -1(R15), R16 BFI $0, R16, $8, R14 MOVB R13, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVB R14, -1(R15) - ADD R0, R10, R10 - ADD R0, R9, R9 + ADD R1, R10, R10 + ADD R1, R9, R9 JMP copy_1_end copy_1_move_3: @@ -2321,55 +2213,55 @@ copy_1_move_3: BFI $0, R16, $8, R14 MOVH R13, (R9) MOVB R14, 2(R9) - ADD R0, R10, R10 - ADD R0, R9, R9 + ADD R1, R10, R10 + ADD R1, R9, R9 JMP copy_1_end copy_1_move_4through7: MOVWU (R10), R13 - ADD R0, R10, R15 + ADD R1, R10, R15 MOVWU -4(R15), R14 MOVW R13, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVW R14, -4(R15) - ADD R0, R10, R10 - ADD R0, R9, R9 + ADD R1, R10, R10 + ADD R1, R9, R9 JMP copy_1_end copy_1_move_8through16: MOVD (R10), R13 - ADD R0, R10, R15 + ADD R1, R10, R15 MOVD -8(R15), R14 MOVD R13, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVD R14, -8(R15) - ADD R0, R10, R10 - ADD R0, R9, R9 + ADD R1, R10, R10 + ADD R1, R9, R9 copy_1_end: - ADD R0, R11, R11 + ADD R1, R11, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) check_offset: - MOVD R11, R0 - MOVD 48(RSP), R16 - ADD R16, R0, R0 - CMP R0, R1 + MOVD R11, R1 + MOVD 80(RSP), R16 + ADD R16, R1, R1 + CMP R1, R12 BGT error_match_off_too_big - MOVD 64(RSP), R16 - CMP R16, R1 + MOVD 96(RSP), R16 + CMP R16, R12 BGT error_match_off_too_big // Copy match from history - MOVD R1, R0 - SUBS R11, R0, R0 + MOVD R12, R1 + SUBS R11, R1, R1 BLS copy_match - MOVD 56(RSP), R13 - SUB R0, R13, R13 - CMP R0, R12 + MOVD 88(RSP), R13 + SUB R1, R13, R13 + CMP R1, R0 BGT copy_all_from_history - MOVD R12, R0 - SUBS $0x10, R0, R0 + MOVD R0, R1 + SUBS $0x10, R1, R1 BLO copy_4_small copy_4_loop: @@ -2377,61 +2269,61 @@ copy_4_loop: FMOVQ F0, (R9) ADD $0x10, R13, R13 ADD $0x10, R9, R9 - SUBS $0x10, R0, R0 + SUBS $0x10, R1, R1 BHS copy_4_loop - ADD R0, R13, R13 + ADD R1, R13, R13 ADD $16, R13, R13 - ADD R0, R9, R9 + ADD R1, R9, R9 ADD $16, R9, R9 FMOVQ -16(R13), F0 FMOVQ F0, -16(R9) JMP copy_4_end copy_4_small: - CMP $0x03, R12 + CMP $0x03, R0 BEQ copy_4_move_3 - CMP $0x08, R12 + CMP $0x08, R0 BLO copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVHU (R13), R0 + MOVHU (R13), R1 MOVBU 2(R13), R16 - BFI $0, R16, $8, R1 - MOVH R0, (R9) - MOVB R1, 2(R9) - ADD R12, R13, R13 - ADD R12, R9, R9 + BFI $0, R16, $8, R12 + MOVH R1, (R9) + MOVB R12, 2(R9) + ADD R0, R13, R13 + ADD R0, R9, R9 JMP copy_4_end copy_4_move_4through7: - MOVWU (R13), R0 - ADD R12, R13, R15 - MOVWU -4(R15), R1 - MOVW R0, (R9) - ADD R12, R9, R15 - MOVW R1, -4(R15) - ADD R12, R13, R13 - ADD R12, R9, R9 + MOVWU (R13), R1 + ADD R0, R13, R15 + MOVWU -4(R15), R12 + MOVW R1, (R9) + ADD R0, R9, R15 + MOVW R12, -4(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 JMP copy_4_end copy_4_move_8through16: - MOVD (R13), R0 - ADD R12, R13, R15 - MOVD -8(R15), R1 - MOVD R0, (R9) - ADD R12, R9, R15 - MOVD R1, -8(R15) - ADD R12, R13, R13 - ADD R12, R9, R9 + MOVD (R13), R1 + ADD R0, R13, R15 + MOVD -8(R15), R12 + MOVD R1, (R9) + ADD R0, R9, R15 + MOVD R12, -8(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 copy_4_end: - ADD R12, R11, R11 + ADD R0, R11, R11 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVD R0, R14 + MOVD R1, R14 SUBS $0x10, R14, R14 BLO copy_5_small @@ -2451,24 +2343,24 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMP $0x03, R0 + CMP $0x03, R1 BEQ copy_5_move_3 BLO copy_5_move_1or2 - CMP $0x08, R0 + CMP $0x08, R1 BLO copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVBU (R13), R16 BFI $0, R16, $8, R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVBU -1(R15), R16 BFI $0, R16, $8, R4 MOVB R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVB R4, -1(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 JMP copy_5_end copy_5_move_3: @@ -2477,137 +2369,136 @@ copy_5_move_3: BFI $0, R16, $8, R4 MOVH R14, (R9) MOVB R4, 2(R9) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 JMP copy_5_end copy_5_move_4through7: MOVWU (R13), R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVWU -4(R15), R4 MOVW R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVW R4, -4(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 JMP copy_5_end copy_5_move_8through16: MOVD (R13), R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVD -8(R15), R4 MOVD R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVD R4, -8(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 copy_5_end: - ADD R0, R11, R11 - SUB R0, R12, R12 + ADD R1, R11, R11 + SUB R1, R0, R0 // Copy match from the current buffer copy_match: - MOVD R9, R0 - SUB R1, R0, R0 + MOVD R9, R1 + SUB R12, R1, R1 // ml <= mo - CMP R1, R12 + CMP R12, R0 BHI copy_overlapping_match // Copy non-overlapping match - ADD R12, R11, R11 - MOVD R12, R1 - SUBS $0x10, R1, R1 + ADD R0, R11, R11 + MOVD R0, R12 + SUBS $0x10, R12, R12 BLO copy_2_small copy_2_loop: - FMOVQ (R0), F0 + FMOVQ (R1), F0 FMOVQ F0, (R9) - ADD $0x10, R0, R0 + ADD $0x10, R1, R1 ADD $0x10, R9, R9 - SUBS $0x10, R1, R1 + SUBS $0x10, R12, R12 BHS copy_2_loop - ADD R1, R0, R0 - ADD $16, R0, R0 - ADD R1, R9, R9 + ADD R12, R1, R1 + ADD $16, R1, R1 + ADD R12, R9, R9 ADD $16, R9, R9 - FMOVQ -16(R0), F0 + FMOVQ -16(R1), F0 FMOVQ F0, -16(R9) JMP copy_2_end copy_2_small: - CMP $0x03, R12 + CMP $0x03, R0 BEQ copy_2_move_3 BLO copy_2_move_1or2 - CMP $0x08, R12 + CMP $0x08, R0 BLO copy_2_move_4through7 JMP copy_2_move_8through16 copy_2_move_1or2: - MOVBU (R0), R16 - BFI $0, R16, $8, R1 - ADD R12, R0, R15 + MOVBU (R1), R16 + BFI $0, R16, $8, R12 + ADD R0, R1, R15 MOVBU -1(R15), R16 BFI $0, R16, $8, R13 - MOVB R1, (R9) - ADD R12, R9, R15 + MOVB R12, (R9) + ADD R0, R9, R15 MOVB R13, -1(R15) - ADD R12, R0, R0 - ADD R12, R9, R9 + ADD R0, R1, R1 + ADD R0, R9, R9 JMP copy_2_end copy_2_move_3: - MOVHU (R0), R1 - MOVBU 2(R0), R16 + MOVHU (R1), R12 + MOVBU 2(R1), R16 BFI $0, R16, $8, R13 - MOVH R1, (R9) + MOVH R12, (R9) MOVB R13, 2(R9) - ADD R12, R0, R0 - ADD R12, R9, R9 + ADD R0, R1, R1 + ADD R0, R9, R9 JMP copy_2_end copy_2_move_4through7: - MOVWU (R0), R1 - ADD R12, R0, R15 + MOVWU (R1), R12 + ADD R0, R1, R15 MOVWU -4(R15), R13 - MOVW R1, (R9) - ADD R12, R9, R15 + MOVW R12, (R9) + ADD R0, R9, R15 MOVW R13, -4(R15) - ADD R12, R0, R0 - ADD R12, R9, R9 + ADD R0, R1, R1 + ADD R0, R9, R9 JMP copy_2_end copy_2_move_8through16: - MOVD (R0), R1 - ADD R12, R0, R15 + MOVD (R1), R12 + ADD R0, R1, R15 MOVD -8(R15), R13 - MOVD R1, (R9) - ADD R12, R9, R15 + MOVD R12, (R9) + ADD R0, R9, R15 MOVD R13, -8(R15) - ADD R12, R0, R0 - ADD R12, R9, R9 + ADD R0, R1, R1 + ADD R0, R9, R9 copy_2_end: JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADD R12, R11, R11 + ADD R0, R11, R11 copy_slow_3: - MOVBU (R0), R1 - MOVB R1, (R9) - ADD $1, R0, R0 + MOVBU (R1), R12 + MOVB R12, (R9) + ADD $1, R1, R1 ADD $1, R9, R9 - SUBS $1, R12, R12 + SUBS $1, R0, R0 BNE copy_slow_3 handle_loop: - MOVD ctx+16(FP), R0 - MOVD 96(R0), R16 + MOVD 40(RSP), R16 SUBS $1, R16, R16 - MOVD R16, 96(R0) + MOVD R16, 40(RSP) BPL sequenceDecs_decodeSync_safe_amd64_main_loop loop_finished: @@ -2616,6 +2507,16 @@ loop_finished: MOVB R3, 40(R0) MOVD R5, 32(R0) + // s.seqSize += outPosition - ctx.outPosition + MOVD ctx+16(FP), R0 + MOVD s+0(FP), R1 + MOVD R11, R2 + MOVD 136(R0), R16 + SUB R16, R2, R2 + MOVD 256(R1), R16 + ADD R2, R16, R16 + MOVD R16, 256(R1) + // Update the context MOVD ctx+16(FP), R0 MOVD R11, 136(R0) @@ -2630,7 +2531,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: - MOVD 24(RSP), R0 + MOVD 56(RSP), R0 MOVD ctx+16(FP), R1 MOVD R0, 216(R1) MOVD $0x00000001, R16 @@ -2640,7 +2541,7 @@ sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: MOVD ctx+16(FP), R0 - MOVD 24(RSP), R1 + MOVD 56(RSP), R1 MOVD R1, 216(R0) MOVD $0x00000002, R16 MOVD R16, ret+24(FP) @@ -2649,7 +2550,7 @@ sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVD ctx+16(FP), R0 - MOVD 16(RSP), R1 + MOVD 48(RSP), R1 MOVD R1, 224(R0) MOVD R11, 136(R0) MOVD $0x00000003, R16 @@ -2659,7 +2560,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVD ctx+16(FP), R0 - MOVD 32(RSP), R1 + MOVD 64(RSP), R1 MOVD R1, 208(R0) MOVD $0x00000004, R16 MOVD R16, ret+24(FP) @@ -2674,9 +2575,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVD ctx+16(FP), R0 - MOVD 32(RSP), R1 + MOVD 64(RSP), R1 MOVD R1, 208(R0) - MOVD 24(RSP), R1 + MOVD 56(RSP), R1 MOVD R1, 216(R0) MOVD R11, 136(R0) MOVD $0x00000005, R16 diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go b/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go index 42ce5de716..94559c459a 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go @@ -83,9 +83,10 @@ const errorOverread = 6 // When the output and literal buffers have compressedBlockOverAlloc (16) // bytes of slack past their logical use, the assembly may use extended // memory copies that read and write in 16-byte blocks, overrunning the end -// of a literal run or match by up to 15 bytes. Otherwise it must use the -// bounds-exact ("safe") copies. This mirrors the analogous, always-dynamic -// selection in executeSimple below. +// of a literal run or match by up to 15 bytes; an empty literal run still +// copies one block, reading and writing the full 16 bytes of slack past +// its position. Otherwise it must use the bounds-exact ("safe") copies. +// This mirrors the analogous, always-dynamic selection in executeSimple below. // // The unsafe copies were disabled in #644 (2022) as a mitigation for a // crash, but that crash's root cause — an unguarded bitReader overread that diff --git a/vendor/modules.txt b/vendor/modules.txt index d1e1f791be..77d89fad8e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -145,7 +145,7 @@ github.com/grpc-ecosystem/grpc-gateway/v2/utilities # github.com/inconshreveable/mousetrap v1.1.0 ## explicit; go 1.18 github.com/inconshreveable/mousetrap -# github.com/klauspost/compress v1.20.0 +# github.com/klauspost/compress v1.20.1 ## explicit; go 1.25 github.com/klauspost/compress github.com/klauspost/compress/fse From 3caafba34fc32299bf9cf2fa372d62c12879983a Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 1 Oct 2026 19:44:52 +0200 Subject: [PATCH 09/26] vendor: github.com/containerd/log v0.2.0 full diff: https://github.com/containerd/log/compare/v0.1.0...v0.2.0 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 4 +- .../github.com/containerd/log/.gitattributes | 1 + .../github.com/containerd/log/.golangci.yml | 50 +++-- vendor/github.com/containerd/log/context.go | 70 +++++- vendor/github.com/containerd/log/slog.go | 66 ++++++ .../sirupsen/logrus/hooks/slog/handler.go | 201 ++++++++++++++++++ .../sirupsen/logrus/hooks/slog/level.go | 119 +++++++++++ .../sirupsen/logrus/hooks/slog/slog.go | 126 +++++++++++ vendor/modules.txt | 5 +- 10 files changed, 615 insertions(+), 29 deletions(-) create mode 100644 vendor/github.com/containerd/log/.gitattributes create mode 100644 vendor/github.com/containerd/log/slog.go create mode 100644 vendor/github.com/sirupsen/logrus/hooks/slog/handler.go create mode 100644 vendor/github.com/sirupsen/logrus/hooks/slog/level.go create mode 100644 vendor/github.com/sirupsen/logrus/hooks/slog/slog.go diff --git a/vendor.mod b/vendor.mod index b1bfb7897a..07dab079af 100644 --- a/vendor.mod +++ b/vendor.mod @@ -15,7 +15,7 @@ require ( dario.cat/mergo v1.0.2 github.com/containerd/errdefs v1.0.0 github.com/containerd/errdefs/pkg v0.3.0 - github.com/containerd/log v0.1.0 + github.com/containerd/log v0.2.0 github.com/containerd/platforms v1.0.0-rc.5 github.com/creack/pty v1.1.24 github.com/distribution/reference v0.6.0 diff --git a/vendor.sum b/vendor.sum index 36d2533377..718a336653 100644 --- a/vendor.sum +++ b/vendor.sum @@ -18,8 +18,8 @@ github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/log v0.2.0 h1:BewD/umNgVnoczglOpX8eRMyEy5t5iPlu5AIpnWDONc= +github.com/containerd/log v0.2.0/go.mod h1:/M7L7CXKcPTfNC74XzaK+5H5KbO5+4lJVpuVI6vRLoM= github.com/containerd/platforms v1.0.0-rc.5 h1:vXd569rDrz8LeMXzAnBsy6LADV5YtsD8oyaRarxdmSU= github.com/containerd/platforms v1.0.0-rc.5/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= diff --git a/vendor/github.com/containerd/log/.gitattributes b/vendor/github.com/containerd/log/.gitattributes new file mode 100644 index 0000000000..6313b56c57 --- /dev/null +++ b/vendor/github.com/containerd/log/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/vendor/github.com/containerd/log/.golangci.yml b/vendor/github.com/containerd/log/.golangci.yml index a695775df4..5c3bdd766c 100644 --- a/vendor/github.com/containerd/log/.golangci.yml +++ b/vendor/github.com/containerd/log/.golangci.yml @@ -1,30 +1,50 @@ +version: "2" linters: enable: - - exportloopref # Checks for pointers to enclosing loop variables - - gofmt - - goimports + - copyloopvar + - dupword - gosec + - govet - ineffassign - misspell - nolintlint - revive - staticcheck - - tenv # Detects using os.Setenv instead of t.Setenv since Go 1.17 - unconvert - unused - - vet - - dupword # Checks for duplicate words in the source code disable: - errcheck + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - api + - cluster + - design + - docs + - docs/man + - releases + - reports + - test +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - api + - cluster + - design + - docs + - docs/man + - releases + - reports + - test run: timeout: 5m - skip-dirs: - - api - - cluster - - design - - docs - - docs/man - - releases - - reports - - test # e2e scripts diff --git a/vendor/github.com/containerd/log/context.go b/vendor/github.com/containerd/log/context.go index 20153066f3..e43ca0b100 100644 --- a/vendor/github.com/containerd/log/context.go +++ b/vendor/github.com/containerd/log/context.go @@ -40,8 +40,11 @@ package log import ( "context" "fmt" + "io" + "log/slog" "github.com/sirupsen/logrus" + lslog "github.com/sirupsen/logrus/hooks/slog" ) // G is a shorthand for [GetLogger]. @@ -108,10 +111,17 @@ const ( PanicLevel Level = logrus.PanicLevel ) -// SetLevel sets log level globally. It returns an error if the given -// level is not supported. +// levelValue is a log level accepted by [SetLevel]. +type levelValue interface { + string | Level | slog.Level | lslog.Level | lslog.SlogLevel +} + +// SetLevel sets the global log level. // -// level can be one of: +// The level may be specified as a string, a [Level], a [slog.Level], an +// [lslog.Level], or an [lslog.SlogLevel]. +// +// String levels are parsed using [logrus.ParseLevel] and may be one of: // // - "trace" ([TraceLevel]) // - "debug" ([DebugLevel]) @@ -120,10 +130,34 @@ const ( // - "error" ([ErrorLevel]) // - "fatal" ([FatalLevel]) // - "panic" ([PanicLevel]) -func SetLevel(level string) error { - lvl, err := logrus.ParseLevel(level) - if err != nil { - return err +// +// slog levels are mapped to Logrus levels using the mapping defined by +// [lslog.SlogLevel]. [lslog.Level] values are accepted directly as their +// underlying Logrus level. +// +// SetLevel returns an error if a string level is not supported. +func SetLevel[T levelValue](level T) error { + var lvl Level + + switch l := any(level).(type) { + case string: + var err error + lvl, err = logrus.ParseLevel(l) + if err != nil { + return err + } + + case Level: + lvl = l + + case slog.Level: + lvl = lslog.SlogLevel(l).Level() + + case lslog.Level: + lvl = Level(l) + + case lslog.SlogLevel: + lvl = l.Level() } L.Logger.SetLevel(lvl) @@ -149,21 +183,39 @@ const ( // SetFormat sets the log output format ([TextFormat] or [JSONFormat]). func SetFormat(format OutputFormat) error { + if slogOut != nil { + var handler slog.Handler + switch format { + case TextFormat: + handler = slog.NewTextHandler(slogOut, &slog.HandlerOptions{Level: loggerLevel{}}) + case JSONFormat: + handler = slog.NewJSONHandler(slogOut, &slog.HandlerOptions{Level: loggerLevel{}}) + default: + return fmt.Errorf("unknown log format: %s", format) + } + slog.SetDefault(slog.New(handler)) + + // Keep logrus formatting and output disabled, as both are handled by slog. + L.Logger.SetFormatter(discardFormatter{}) + L.Logger.SetOutput(io.Discard) + return nil + } + switch format { case TextFormat: L.Logger.SetFormatter(&logrus.TextFormatter{ TimestampFormat: RFC3339NanoFixed, FullTimestamp: true, }) - return nil case JSONFormat: L.Logger.SetFormatter(&logrus.JSONFormatter{ TimestampFormat: RFC3339NanoFixed, }) - return nil default: return fmt.Errorf("unknown log format: %s", format) } + + return nil } // WithLogger returns a new context with the provided logger. Use in diff --git a/vendor/github.com/containerd/log/slog.go b/vendor/github.com/containerd/log/slog.go new file mode 100644 index 0000000000..6e230ca8ef --- /dev/null +++ b/vendor/github.com/containerd/log/slog.go @@ -0,0 +1,66 @@ +/* + Copyright The containerd Authors. + + 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 log + +import ( + "io" + "log/slog" + "sync" + + "github.com/sirupsen/logrus" + lslog "github.com/sirupsen/logrus/hooks/slog" +) + +// slogOut is used to set the slog logger when setting output format. +var slogOut io.Writer + +// slogOnce guards UseSlog so repeated calls do not stack up hooks or +// reset slogOut to the discard writer installed on the first call. +var slogOnce sync.Once + +func UseSlog() { + slogOnce.Do(func() { + L.Logger.SetNoLock() + L.Logger.AddHook(slogHook{}) + slogOut = L.Logger.Out + + // Disable logrus formatting and output, as both are handled by slog. + L.Logger.SetFormatter(discardFormatter{}) + L.Logger.SetOutput(io.Discard) + }) +} + +type slogHook struct{} + +func (slogHook) Levels() []logrus.Level { + return logrus.AllLevels +} + +func (slogHook) Fire(entry *logrus.Entry) error { + return lslog.NewHook(slog.Default(), nil).Fire(entry) +} + +// loggerLevel exposes the current Logrus logger level as a slog.Leveler. +type loggerLevel struct{} + +func (loggerLevel) Level() slog.Level { + return lslog.Level(L.Logger.GetLevel()).Level() +} + +type discardFormatter struct{} + +func (discardFormatter) Format(*logrus.Entry) ([]byte, error) { return nil, nil } diff --git a/vendor/github.com/sirupsen/logrus/hooks/slog/handler.go b/vendor/github.com/sirupsen/logrus/hooks/slog/handler.go new file mode 100644 index 0000000000..1b846c3c04 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/hooks/slog/handler.go @@ -0,0 +1,201 @@ +package slog + +import ( + "context" + "log/slog" + "maps" + "runtime" + "slices" + "strings" + + "github.com/sirupsen/logrus" +) + +// HandlerOptions are options for a [Handler]. +// A zero HandlerOptions consists entirely of default values. +type HandlerOptions struct { + // AddSource causes the handler to include the source code position + // of the log statement in the Logrus entry. + AddSource bool + + // LevelMapper maps slog levels to Logrus levels. If nil, the default + // mapping is used. Set it to customize level mapping, for example to map + // custom slog levels to specific Logrus levels. + LevelMapper func(slog.Level) logrus.Level +} + +// Handler is a [slog.Handler] that writes records to a [logrus.Logger]. +// +// It is intended for bridging libraries or application code that log via slog +// into an existing Logrus logger, for example during a gradual migration. +// +// By default, slog levels are mapped using [SlogLevel]. +// Set [HandlerOptions.LevelMapper] to customize the mapping. +// +// Mapping to [logrus.FatalLevel] or [logrus.PanicLevel] preserves the level +// only; handling a record does not exit or panic. +type Handler struct { + logger *logrus.Logger + opts HandlerOptions + + // fields holds attributes from prior WithAttrs calls, already resolved + // under the group prefix that applied when they were added. + fields logrus.Fields + + // groups is the current group name stack for attributes added later. + groups []string +} + +var _ slog.Handler = (*Handler)(nil) + +// NewHandler creates a [slog.Handler] that writes to the provided +// [logrus.Logger]. +// +// The provided logger must not be nil. NewHandler panics if logger is nil. +// If opts is nil, the default options are used. +func NewHandler(logger *logrus.Logger, opts *HandlerOptions) *Handler { + if logger == nil { + panic("cannot create handler from nil logger") + } + if opts == nil { + opts = &HandlerOptions{} + } + return &Handler{ + logger: logger, + opts: *opts, + } +} + +// toLogrusLevel maps a slog level using LevelMapper or the default mapping. +func (h *Handler) toLogrusLevel(level slog.Level) logrus.Level { + if h.opts.LevelMapper != nil { + return h.opts.LevelMapper(level) + } + return SlogLevel(level).Level() +} + +// Enabled reports whether the handler handles records at the given level. +// It maps the slog level to a logrus level and consults the underlying logger. +func (h *Handler) Enabled(_ context.Context, level slog.Level) bool { + return h.logger.IsLevelEnabled(h.toLogrusLevel(level)) +} + +// Handle converts the slog record into a logrus entry and logs it. +// Record time, context, message, and attributes (including those from +// [Handler.WithAttrs]/[Handler.WithGroup]) are preserved. Attributes are +// attached as logrus fields; group names are joined with "." as a key prefix +// (similar to [slog.TextHandler]). +func (h *Handler) Handle(ctx context.Context, record slog.Record) error { + // Stop recursive forwarding before it can cycle back through this logger. + if hasLogrusLogger(ctx, h.logger) { + return nil + } + level := h.toLogrusLevel(record.Level) + if !h.logger.IsLevelEnabled(level) { + return nil + } + + entry := &logrus.Entry{ + Logger: h.logger, + Data: h.fields, + Time: record.Time, + Context: ctx, + } + + if h.opts.AddSource && record.PC != 0 { + // Preserve the caller selected by slog instead of rediscovering it + // through Logrus's caller stack filtering. + // + // Record.PC is a return PC; resolve it with CallersFrames. + frame, _ := runtime.CallersFrames([]uintptr{record.PC}).Next() + entry.Caller = &frame + } + + if n := record.NumAttrs(); n > 0 { + // Clone before mutating the handler's fields. + entry.Data = maps.Clone(h.fields) + if entry.Data == nil { + entry.Data = make(logrus.Fields, n) + } + record.Attrs(func(a slog.Attr) bool { + appendAttr(entry.Data, h.groups, a) + return true + }) + } + + entry.Log(level, record.Message) + return nil +} + +// WithAttrs returns a new Handler whose attributes consist of h's attributes +// followed by attrs. +func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler { + if len(attrs) == 0 { + return h + } + h2 := h.clone() + h2.fields = maps.Clone(h.fields) + if h2.fields == nil { + h2.fields = make(logrus.Fields, len(attrs)) + } + for _, a := range attrs { + appendAttr(h2.fields, h.groups, a) + } + return h2 +} + +// WithGroup returns a new Handler with a group appended to the receiver's +// existing groups. All attributes added to the returned handler (via WithAttrs +// or Handle) are nested under the combined group names. +// If name is empty, WithGroup returns h unchanged. +func (h *Handler) WithGroup(name string) slog.Handler { + if name == "" { + return h + } + h2 := h.clone() + h2.groups = append(slices.Clip(h.groups), name) + return h2 +} + +// clone returns a shallow copy of h. Callers must clone fields or groups +// before modifying them. +func (h *Handler) clone() *Handler { + return &Handler{ + logger: h.logger, + opts: h.opts, + fields: h.fields, + groups: h.groups, + } +} + +// appendAttr adds attr to fields, resolving it and applying group prefixes. +// Group attributes are flattened with "."-separated keys. +func appendAttr(fields logrus.Fields, groups []string, attr slog.Attr) { + attr.Value = attr.Value.Resolve() + if attr.Equal(slog.Attr{}) { + return + } + if attr.Value.Kind() == slog.KindGroup { + gs := attr.Value.Group() + if len(gs) == 0 { + return + } + g := groups + if attr.Key != "" { + g = append(slices.Clip(groups), attr.Key) + } + for _, a := range gs { + appendAttr(fields, g, a) + } + return + } + + key := attr.Key + if len(groups) > 0 { + key = strings.Join(groups, ".") + if attr.Key != "" { + key += "." + attr.Key + } + } + fields[key] = attr.Value.Any() +} diff --git a/vendor/github.com/sirupsen/logrus/hooks/slog/level.go b/vendor/github.com/sirupsen/logrus/hooks/slog/level.go new file mode 100644 index 0000000000..737f5e065f --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/hooks/slog/level.go @@ -0,0 +1,119 @@ +package slog + +import ( + "log/slog" + + "github.com/sirupsen/logrus" +) + +// slog levels corresponding to Logrus levels. +const ( + slogLevelTrace = slog.LevelDebug - 4 + slogLevelDebug = slog.LevelDebug + slogLevelInfo = slog.LevelInfo + slogLevelWarn = slog.LevelWarn + slogLevelError = slog.LevelError + slogLevelFatal = slog.LevelError + 2 + slogLevelPanic = slog.LevelError + 4 +) + +// A Leveler provides a [logrus.Level] value. +// +// It is the Logrus counterpart of [slog.Leveler]. +// +// As [SlogLevel] itself implements Leveler, clients typically supply +// a SlogLevel value wherever a Leveler is needed. +// Clients who need to vary the level dynamically can provide a more complex +// Leveler implementation. +type Leveler interface { + Level() logrus.Level +} + +// Level adapts a [logrus.Level] to a [slog.Leveler] using the default +// Logrus-to-slog level mapping: +// +// - [logrus.TraceLevel] -> [slog.LevelDebug] - 4 +// - [logrus.DebugLevel] -> [slog.LevelDebug] +// - [logrus.InfoLevel] -> [slog.LevelInfo] +// - [logrus.WarnLevel] -> [slog.LevelWarn] +// - [logrus.ErrorLevel] -> [slog.LevelError] +// - [logrus.FatalLevel] -> [slog.LevelError] + 2 +// - [logrus.PanicLevel] -> [slog.LevelError] + 4 +// +// Unknown Logrus levels map to [slog.LevelError]. +type Level logrus.Level + +// Level returns l mapped to the corresponding slog level. +func (l Level) Level() slog.Level { + return toSlogLevel(logrus.Level(l)) +} + +var _ slog.Leveler = Level(0) + +// SlogLevel adapts a [slog.Level] to a [Leveler] using the default +// slog-to-Logrus level mapping: +// +// - [slog.LevelDebug] - 4 -> [logrus.TraceLevel] +// - [slog.LevelDebug] -> [logrus.DebugLevel] +// - [slog.LevelInfo] -> [logrus.InfoLevel] +// - [slog.LevelWarn] -> [logrus.WarnLevel] +// - [slog.LevelError] -> [logrus.ErrorLevel] +// - [slog.LevelError] + 2 -> [logrus.FatalLevel] +// - [slog.LevelError] + 4 -> [logrus.PanicLevel] +// +// Levels between these boundaries map to the next lower Logrus severity. +// Levels below [slog.LevelDebug] map to [logrus.TraceLevel], and levels at or +// above the Panic boundary map to [logrus.PanicLevel]. +type SlogLevel slog.Level + +// Level returns l mapped to the corresponding Logrus level. +func (l SlogLevel) Level() logrus.Level { + return toLogrusLevel(slog.Level(l)) +} + +var _ Leveler = SlogLevel(0) + +// toLogrusLevel maps a slog level using the default mapping. +func toLogrusLevel(level slog.Level) logrus.Level { + switch { + case level >= slogLevelPanic: + return logrus.PanicLevel + case level >= slogLevelFatal: + return logrus.FatalLevel + case level >= slogLevelError: + return logrus.ErrorLevel + case level >= slogLevelWarn: + return logrus.WarnLevel + case level >= slogLevelInfo: + return logrus.InfoLevel + case level >= slogLevelDebug: + return logrus.DebugLevel + case level >= slogLevelTrace: + return logrus.TraceLevel + default: + return logrus.TraceLevel + } +} + +// toSlogLevel maps a Logrus level using the default mapping. +func toSlogLevel(level logrus.Level) slog.Level { + switch level { + case logrus.PanicLevel: + return slogLevelPanic + case logrus.FatalLevel: + return slogLevelFatal + case logrus.ErrorLevel: + return slogLevelError + case logrus.WarnLevel: + return slogLevelWarn + case logrus.InfoLevel: + return slogLevelInfo + case logrus.DebugLevel: + return slogLevelDebug + case logrus.TraceLevel: + return slogLevelTrace + default: + // Treat all unknown levels as errors + return slogLevelError + } +} diff --git a/vendor/github.com/sirupsen/logrus/hooks/slog/slog.go b/vendor/github.com/sirupsen/logrus/hooks/slog/slog.go new file mode 100644 index 0000000000..d5609ee5f6 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/hooks/slog/slog.go @@ -0,0 +1,126 @@ +// Package slog provides adapters between Logrus and log/slog. +// +// [Handler] forwards slog records to a Logrus logger, while [Hook] forwards +// Logrus entries to a slog logger. They can be used independently to support +// incremental migration between the two logging APIs. +package slog + +import ( + "context" + "log/slog" + "maps" + + "github.com/sirupsen/logrus" +) + +// logrusLoggerContextKey is the context key used to track Logrus loggers a +// record has already traversed while being forwarded through slog adapters. +type logrusLoggerContextKey struct{} + +// withLogrusLogger returns a context that records logger as having already +// handled the current log record. +func withLogrusLogger(ctx context.Context, logger *logrus.Logger) context.Context { + seen, _ := ctx.Value(logrusLoggerContextKey{}).(map[*logrus.Logger]struct{}) + seen = maps.Clone(seen) + if seen == nil { + seen = make(map[*logrus.Logger]struct{}, 1) + } + seen[logger] = struct{}{} + return context.WithValue(ctx, logrusLoggerContextKey{}, seen) +} + +// hasLogrusLogger reports whether logger has already handled the current log +// record while it was forwarded through slog adapters. +func hasLogrusLogger(ctx context.Context, logger *logrus.Logger) bool { + seen, _ := ctx.Value(logrusLoggerContextKey{}).(map[*logrus.Logger]struct{}) + _, ok := seen[logger] + return ok +} + +// HookOptions are options for a [Hook]. +// A zero HookOptions consists entirely of default values. +type HookOptions struct { + // LevelMapper maps Logrus levels to slog levels. If nil, the default + // mapping is used. Set it to customize level mapping, for example to map + // custom Logrus levels to specific slog levels. + LevelMapper func(logrus.Level) slog.Level +} + +// Hook sends Logrus entries to slog. +// +// It is intended for bridging libraries or application code that log via +// Logrus into an existing slog logger, for example during a gradual migration. +// +// By default, Logrus levels are mapped using [Level]. Set +// [HookOptions.LevelMapper] to customize the mapping. +type Hook struct { + logger *slog.Logger + opts HookOptions +} + +var _ logrus.Hook = (*Hook)(nil) + +// NewHook creates a [logrus.Hook] that sends logs to the provided [slog.Logger]. +// +// This hook is intended to be used during transition from Logrus to slog, +// or as a shim between different parts of your application or different +// libraries that depend on different loggers. +// +// The provided logger must not be nil. NewHook panics if logger is nil. +// If opts is nil, the default options are used. +func NewHook(logger *slog.Logger, opts *HookOptions) *Hook { + if logger == nil { + panic("cannot create hook from nil logger") + } + if opts == nil { + opts = &HookOptions{} + } + return &Hook{ + logger: logger, + opts: *opts, + } +} + +// toSlogLevel maps a Logrus level using LevelMapper or the default mapping. +func (h *Hook) toSlogLevel(level logrus.Level) slog.Level { + if h.opts.LevelMapper != nil { + return h.opts.LevelMapper(level) + } + return Level(level).Level() +} + +// Levels always returns all levels, since slog allows controlling level +// enabling based on context. +func (h *Hook) Levels() []logrus.Level { + return logrus.AllLevels +} + +// Fire forwards the provided logrus Entry to the underlying slog.Logger's +// Handler, mapping it to a slog.Record. Time and caller information are +// preserved when available, and Entry.Data is converted to attributes. +// If Entry.Context is nil, context.Background() is used. +func (h *Hook) Fire(entry *logrus.Entry) error { + ctx := entry.Context + if ctx == nil { + ctx = context.Background() + } + // Track this logger to guard against recursive forwarding. + ctx = withLogrusLogger(ctx, entry.Logger) + + level := h.toSlogLevel(entry.Level) + handler := h.logger.Handler() + if !handler.Enabled(ctx, level) { + return nil + } + attrs := make([]slog.Attr, 0, len(entry.Data)) + for k, v := range entry.Data { + attrs = append(attrs, slog.Any(k, v)) + } + var pc uintptr + if entry.Caller != nil { + pc = entry.Caller.PC + } + r := slog.NewRecord(entry.Time, level, entry.Message, pc) + r.AddAttrs(attrs...) + return handler.Handle(ctx, r) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 501237c5a1..5c001e2ba7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -31,8 +31,8 @@ github.com/containerd/errdefs ## explicit; go 1.22 github.com/containerd/errdefs/pkg/errhttp github.com/containerd/errdefs/pkg/internal/cause -# github.com/containerd/log v0.1.0 -## explicit; go 1.20 +# github.com/containerd/log v0.2.0 +## explicit; go 1.23 github.com/containerd/log # github.com/containerd/platforms v1.0.0-rc.5 ## explicit; go 1.24 @@ -283,6 +283,7 @@ github.com/santhosh-tekuri/jsonschema/v6/kind # github.com/sirupsen/logrus v1.10.2 ## explicit; go 1.23 github.com/sirupsen/logrus +github.com/sirupsen/logrus/hooks/slog # github.com/spf13/cobra v1.10.2 ## explicit; go 1.15 github.com/spf13/cobra From fb1cc07c08300cf77fec2652072a907ad0f653c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 1 Oct 2026 19:01:46 +0200 Subject: [PATCH 10/26] cmd/docker: Add --cloud with configurable context resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve it through the offload plugin by default, with a provider override in features.cloud in the Docker config. Require the selected plugin to declare the cloud-context-resolver feature in its metadata before showing the flag in help and completion or invoking its __resolve-context operation. Resolve through WithContextResolver, after the config file and context store are loaded but before client initialization, without wrapping or re-executing Docker. Forward --context to downstream plugins so they need not support --cloud or repeat provisioning. Skip provisioning for help, version, and completion requests. Report unknown flags and missing flag values before provisioning, so a mistyped invocation fails without creating cloud resources or contacting the engine selected before resolution. Signed-off-by: Paweł Gronowski --- cmd/docker/cloud.go | 256 ++++++++++++++++++ cmd/docker/cloud_test.go | 542 +++++++++++++++++++++++++++++++++++++++ cmd/docker/docker.go | 18 +- 3 files changed, 815 insertions(+), 1 deletion(-) create mode 100644 cmd/docker/cloud.go create mode 100644 cmd/docker/cloud_test.go diff --git a/cmd/docker/cloud.go b/cmd/docker/cloud.go new file mode 100644 index 0000000000..f2a127bb42 --- /dev/null +++ b/cmd/docker/cloud.go @@ -0,0 +1,256 @@ +package main + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "os" + "os/exec" + "strconv" + "strings" + + "github.com/docker/cli/cli" + pluginmanager "github.com/docker/cli/cli-plugins/manager" + "github.com/docker/cli/cli-plugins/metadata" + "github.com/docker/cli/cli/command" + "github.com/docker/cli/cli/config" + contextdocker "github.com/docker/cli/cli/context/docker" + "github.com/spf13/cobra" + "github.com/spf13/pflag" +) + +// processCloud resolves the global --cloud[=NAME] option after configuration is +// loaded, but before telemetry and endpoint initialization. +// The option appears in help and completion only when the selected provider is +// installed, valid, and declares support for the resolver contract. +// The provider defaults to the offload plugin; features.cloud in the effective +// Docker config.json can override the plugin name, not its executable path. +// Explicit use also requires the provider's capability declaration. +// Discovery for visibility does not provision a context or connect to a daemon. +// +// # Provider contract +// +// The provider must include "Features": {"cloud-context-resolver": true} in its +// docker-cli-plugin-metadata response to declare support for this contract. +// Older plugins without this declaration leave the flag hidden and cannot be +// used for resolution. +// The CLI uses normal plugin discovery and invokes: +// +// docker- --config= __resolve-context -- +// +// Bare --cloud and --cloud= pass default as the target name. +// The effective config directory is also passed as DOCKER_CONFIG. +// The provider must provision into that context store without changing the saved +// current context or recursively forwarding --cloud. +// It inherits the environment, receives no interactive stdin, and sends progress +// to stderr. +// Stdout must contain exactly one JSON object: +// +// {"DOCKER_CONTEXT":"provisioned-context"} +// +// The returned context must exist, must not be the virtual default context, and +// must have a Docker endpoint with a nonempty host. +// Resolver failures abort command execution without falling back to another +// context. +// Cancellation terminates the resolver process; provisioning subprocesses and +// resource cleanup remain the provider's responsibility. +// Downstream plugins receive --context= instead of the global +// --cloud option. +// The provider implementation ships separately and must support this operation +// before enabling the integration. +func processCloud(ctx context.Context, dockerCli *command.DockerCli, cmd *cobra.Command, args, osArgs []string) ([]string, error) { + if !cmd.Flags().Changed("cloud") { + return osArgs, nil + } + if cmd.Flags().Changed("context") || cmd.Flags().Changed("host") { + return osArgs, errors.New("conflicting options: cannot specify --cloud together with --context or --host") + } + + help, err := cloudHelpRequest(cmd, args) + if err != nil { + return osArgs, err + } + + var contextName string + if !help { + name, _ := cmd.Flags().GetString("cloud") + if name == "" { + name = "default" + } + + contextName, err = resolveCloudContext(ctx, dockerCli, cmd, name) + if err != nil { + return osArgs, fmt.Errorf("--cloud: %w", err) + } + if err := cmd.Flags().Set("context", contextName); err != nil { + return osArgs, err + } + } + + return cloudPluginArgs(cmd, osArgs, contextName) +} + +// cloudResolverFeature is the plugin metadata feature that declares support for +// the __resolve-context contract. +const cloudResolverFeature = "cloud-context-resolver" + +func cloudProvider(dockerCli config.Provider, rootCmd *cobra.Command) (*pluginmanager.Plugin, error) { + provider := dockerCli.ConfigFile().Features["cloud"] + if provider == "" { + provider = "offload" + } + + plugin, err := pluginmanager.GetPlugin(provider, dockerCli, rootCmd) + if err != nil { + return nil, fmt.Errorf("cloud resolver plugin %q unavailable: %w", provider, err) + } + if plugin.Err != nil { + return nil, fmt.Errorf("invalid cloud resolver plugin %q: %w", provider, plugin.Err) + } + + if supported, _ := plugin.Features[cloudResolverFeature].(bool); !supported { + return nil, fmt.Errorf("plugin %q does not support cloud context resolution", provider) + } + + return plugin, nil +} + +// updateCloudFlagVisibility runs only for help and completion, avoiding plugin +// discovery on ordinary invocations that do not use --cloud. +func updateCloudFlagVisibility(dockerCli config.Provider, rootCmd *cobra.Command) { + flag := rootCmd.Flags().Lookup("cloud") + if flag == nil { + return + } + _, err := cloudProvider(dockerCli, rootCmd) + flag.Hidden = err != nil +} + +func resolveCloudContext(ctx context.Context, dockerCli *command.DockerCli, rootCmd *cobra.Command, name string) (string, error) { + if err := ctx.Err(); err != nil { + return "", err + } + + plugin, err := cloudProvider(dockerCli, rootCmd) + if err != nil { + return "", err + } + + cmd := exec.CommandContext(ctx, plugin.Path, "--config="+config.Dir(), plugin.Name, "__resolve-context", "--", name) // #nosec G204 -- executable validated through CLI plugin discovery + cmd.Env = append(os.Environ(), config.EnvOverrideConfigDir+"="+config.Dir(), metadata.ReexecEnvvar+"="+os.Args[0]) + cmd.Stderr = dockerCli.Err() + + out, err := cmd.Output() + if err != nil { + if ctx.Err() != nil { + return "", ctx.Err() + } + return "", fmt.Errorf("cloud resolver failed: %w", err) + } + + var response struct { + DockerContext string `json:"DOCKER_CONTEXT"` + } + if err := json.Unmarshal(out, &response); err != nil { + return "", fmt.Errorf("invalid cloud resolver response: %w", err) + } + response.DockerContext = strings.TrimSpace(response.DockerContext) + if response.DockerContext == "" || response.DockerContext == command.DefaultContextName { + return "", errors.New("cloud resolver must return a non-default DOCKER_CONTEXT") + } + + // Do not allow a missing context or endpoint to fall back to the local engine. + meta, err := dockerCli.ContextStore().GetMetadata(response.DockerContext) + if err != nil { + return "", fmt.Errorf("loading resolved context %q: %w", response.DockerContext, err) + } + + endpoint, err := contextdocker.EndpointFromContext(meta) + if err != nil { + return "", fmt.Errorf("invalid resolved context %q: %w", response.DockerContext, err) + } + if endpoint.Host == "" { + return "", fmt.Errorf("resolved context %q has no Docker endpoint host", response.DockerContext) + } + + return response.DockerContext, nil +} + +// cloudHelpRequest avoids provisioning for help and shell completion. +// Parse known command flags rather than scanning argv: --help may be an option +// value or an argument to a container, not a request for Docker help. +// Unknown flags and missing flag values return a usage error, so a mistyped +// invocation fails without provisioning or falling back to the local engine. +// Flag values are validated only by the command's own parse, after resolution. +func cloudHelpRequest(rootCmd *cobra.Command, args []string) (bool, error) { + help, _ := rootCmd.PersistentFlags().GetBool("help") + version, _ := rootCmd.Flags().GetBool("version") + if help || version || len(args) == 0 { + return true, nil + } + + switch args[0] { + case "help", "completion", cobra.ShellCompRequestCmd, cobra.ShellCompNoDescRequestCmd: + return true, nil + } + + cmd, remaining, err := rootCmd.Find(args) + if err != nil || cmd == rootCmd || pluginmanager.IsPluginCommand(cmd) { + // Plugin flags are opaque. Only recognize help immediately after the + // plugin name; deeper help is available through "docker help PLUGIN". + return len(args) > 1 && (args[1] == "--help" || args[1] == "-h" || args[1] == "--help=true"), nil + } + + cmd.InitDefaultHelpFlag() + flags := cmd.Flags() + flags.AddFlagSet(cmd.PersistentFlags()) + flags.AddFlagSet(cmd.InheritedFlags()) + + err = flags.ParseAll(remaining, func(flag *pflag.Flag, value string) error { + if flag.Name == "help" { + var err error + if help, err = strconv.ParseBool(value); err != nil { + return fmt.Errorf("invalid argument %q for \"--help\" flag: %w", value, err) + } + } + return nil + }) + if err != nil { + // Format the usage error directly. The root command's FlagErrorFunc + // first checks whether the daemon supports the command, which would + // connect to the engine selected before --cloud is resolved. + return false, cli.FlagErrorFunc(cmd, err) + } + + return help, nil +} + +// cloudPluginArgs only rewrites the global prefix, leaving subcommand arguments +// untouched. Parsing also distinguishes --cloud from another flag's value. +func cloudPluginArgs(cmd *cobra.Command, osArgs []string, contextName string) ([]string, error) { + flags := pflag.NewFlagSet(cmd.Name(), pflag.ContinueOnError) + flags.SetInterspersed(false) + flags.AddFlagSet(cmd.Flags()) + flags.AddFlagSet(cmd.PersistentFlags()) + + result := []string{osArgs[0]} + if contextName != "" { + result = append(result, "--context="+contextName) + } + + if err := flags.ParseAll(osArgs[1:], func(flag *pflag.Flag, value string) error { + if flag.Name != "cloud" { + result = append(result, "--"+flag.Name+"="+value) + } + return nil + }); err != nil { + return osArgs, err + } + + if flags.ArgsLenAtDash() >= 0 { + result = append(result, "--") + } + + return append(result, flags.Args()...), nil +} diff --git a/cmd/docker/cloud_test.go b/cmd/docker/cloud_test.go new file mode 100644 index 0000000000..f1ce8a60a8 --- /dev/null +++ b/cmd/docker/cloud_test.go @@ -0,0 +1,542 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/docker/cli/cli-plugins/metadata" + "github.com/docker/cli/cli/command" + "github.com/docker/cli/cli/config" + "github.com/docker/cli/cli/config/configfile" + contextdocker "github.com/docker/cli/cli/context/docker" + "github.com/docker/cli/cli/context/store" + "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" +) + +func TestCloudFlagHidden(t *testing.T) { + dockerCli, err := command.NewDockerCli() + assert.NilError(t, err) + + tcmd := newDockerCommand(dockerCli) + tcmd.SetArgs([]string{"--cloud=team", "--help"}) + cmd, _, err := tcmd.HandleGlobalFlags() + assert.NilError(t, err) + + name, err := cmd.Flags().GetString("cloud") + assert.NilError(t, err) + assert.Equal(t, name, "team") + assert.Assert(t, cmd.Flags().Lookup("cloud").Hidden) + assert.Assert(t, !strings.Contains(cmd.UsageString(), "--cloud")) +} + +func TestCloudHelpRequest(t *testing.T) { + for _, tc := range []struct { + name string + args []string + help bool + }{ + {name: "no command", help: true}, + {name: "global help", args: []string{"--help"}, help: true}, + {name: "global version", args: []string{"--version"}, help: true}, + {name: "help command", args: []string{"help", "run"}, help: true}, + {name: "completion request", args: []string{"__complete", "run", ""}, help: true}, + {name: "completion script", args: []string{"completion", "fish"}, help: true}, + {name: "builtin help", args: []string{"run", "--help"}, help: true}, + {name: "boolean help value", args: []string{"run", "--help=1"}, help: true}, + {name: "nested help", args: []string{"container", "run", "--help"}, help: true}, + {name: "plugin help", args: []string{"compose", "--help"}, help: true}, + {name: "command execution", args: []string{"ps"}}, + {name: "container help", args: []string{"run", "alpine", "--help"}}, + {name: "flag value", args: []string{"run", "--name", "--help", "alpine"}}, + {name: "help disabled", args: []string{"run", "--help=false", "alpine"}}, + } { + t.Run(tc.name, func(t *testing.T) { + dockerCli, err := command.NewDockerCli() + assert.NilError(t, err) + tcmd := newDockerCommand(dockerCli) + tcmd.SetArgs(append([]string{"--cloud"}, tc.args...)) + cmd, args, err := tcmd.HandleGlobalFlags() + assert.NilError(t, err) + + help, err := cloudHelpRequest(cmd, args) + assert.NilError(t, err) + assert.Equal(t, help, tc.help) + }) + } +} + +// Flag errors are reported before cloud resolution, so they must not run the +// command's daemon feature checks against the engine selected before it. +func TestCloudFlagErrorSkipsDaemon(t *testing.T) { + originalConfig := config.Dir() + t.Cleanup(func() { config.SetDir(originalConfig) }) + config.SetDir(t.TempDir()) + + var pings atomic.Int32 + daemon := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + pings.Add(1) + w.Header().Set("Docker-Experimental", "false") + })) + defer daemon.Close() + t.Setenv("DOCKER_HOST", "tcp://"+daemon.Listener.Addr().String()) + + dockerCli, err := command.NewDockerCli() + assert.NilError(t, err) + tcmd := newDockerCommand(dockerCli) + tcmd.SetArgs([]string{"--cloud", "checkpoint", "ls", "--unknown"}) + cmd, args, err := tcmd.HandleGlobalFlags() + assert.NilError(t, err) + assert.NilError(t, tcmd.Initialize()) + + _, err = cloudHelpRequest(cmd, args) + assert.Check(t, is.ErrorContains(err, "unknown flag: --unknown")) + assert.Check(t, is.Equal(pings.Load(), int32(0))) +} + +func TestCloudPluginArgs(t *testing.T) { + for _, tc := range []struct { + name string + args []string + context string + want []string + }{ + { + name: "global flag only", + args: []string{"docker", "--cloud=foo", "compose", "up", "--cloud=child"}, + context: "cloud-foo", + want: []string{"docker", "--context=cloud-foo", "compose", "up", "--cloud=child"}, + }, + { + name: "flag value is not cloud flag", + args: []string{"docker", "--config", "--cloud", "--cloud", "-D", "compose", "up"}, + context: "cloud-default", + want: []string{"docker", "--context=cloud-default", "--config=--cloud", "--debug=true", "compose", "up"}, + }, + { + name: "delimiter preserved", + args: []string{"docker", "--cloud=foo", "--", "compose", "--", "--cloud"}, + context: "cloud-foo", + want: []string{"docker", "--context=cloud-foo", "--", "compose", "--", "--cloud"}, + }, + { + name: "repeated cloud flags", + args: []string{"docker", "--cloud=foo", "--cloud=bar", "compose", "up"}, + context: "cloud-bar", + want: []string{"docker", "--context=cloud-bar", "compose", "up"}, + }, + { + name: "help without resolution", + args: []string{"docker", "--cloud", "compose", "--help"}, + want: []string{"docker", "compose", "--help"}, + }, + } { + t.Run(tc.name, func(t *testing.T) { + dockerCli, err := command.NewDockerCli() + assert.NilError(t, err) + tcmd := newDockerCommand(dockerCli) + tcmd.SetArgs(tc.args[1:]) + cmd, _, err := tcmd.HandleGlobalFlags() + assert.NilError(t, err) + + got, err := cloudPluginArgs(cmd, tc.args, tc.context) + assert.NilError(t, err) + assert.DeepEqual(t, got, tc.want) + }) + } +} + +// Exercise the real startup and subprocess boundary without a daemon or cloud +// service, including failures that must never dispatch the requested command. +func TestCloudResolution(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("fixture plugins use shell scripts") + } + + executable, err := os.Executable() + assert.NilError(t, err) + + for _, tc := range []struct { + name string + args []string + response string + exit int + wantName string + wantErr string + plugin bool + skip bool + provider string + noProvider bool + legacyProvider bool + command []string + visible bool + }{ + { + name: "default target", + args: []string{"--cloud"}, + wantName: "default", + }, + { + name: "empty target", + args: []string{"--cloud="}, + wantName: "default", + }, + { + name: "named target", + args: []string{"--cloud=team"}, + wantName: "team", + }, + { + name: "plugin dispatch", + args: []string{"--cloud=team"}, + wantName: "team", + plugin: true, + }, + { + name: "nonzero exit", + args: []string{"--cloud"}, + exit: 1, + wantErr: "cloud resolver failed", + }, + { + name: "malformed JSON", + args: []string{"--cloud"}, + response: "not JSON", + wantErr: "invalid cloud resolver response", + }, + { + name: "multiple responses", + args: []string{"--cloud"}, + response: `{} {}`, + wantErr: "invalid cloud resolver response", + }, + { + name: "missing field", + args: []string{"--cloud"}, + response: `{}`, + wantErr: "must return a non-default DOCKER_CONTEXT", + }, + { + name: "local context", + args: []string{"--cloud"}, + response: `{"DOCKER_CONTEXT":"default"}`, + wantErr: "must return a non-default DOCKER_CONTEXT", + }, + { + name: "missing context", + args: []string{"--cloud"}, + response: `{"DOCKER_CONTEXT":"missing"}`, + wantErr: `loading resolved context "missing"`, + }, + { + name: "missing endpoint host", + args: []string{"--cloud"}, + response: `{"DOCKER_CONTEXT":"empty-host"}`, + wantErr: "has no Docker endpoint host", + }, + { + name: "explicit context conflict", + args: []string{"--cloud", "--context=other"}, + wantErr: "conflicting options", + skip: true, + }, + { + name: "explicit host conflict", + args: []string{"--cloud", "--host=tcp://localhost:2375"}, + wantErr: "conflicting options", + skip: true, + }, + { + name: "invalid flag before help", + args: []string{"--cloud"}, + command: []string{"run", "--unknown", "--help"}, + wantErr: "unknown flag: --unknown", + skip: true, + }, + { + name: "default provider", + args: []string{"--cloud"}, + noProvider: true, + wantName: "default", + }, + { + name: "legacy default provider", + args: []string{"--cloud"}, + noProvider: true, + legacyProvider: true, + wantErr: `plugin "offload" does not support cloud context resolution`, + skip: true, + }, + { + name: "legacy configured provider", + args: []string{"--cloud"}, + legacyProvider: true, + wantErr: `plugin "foobar" does not support cloud context resolution`, + skip: true, + }, + { + name: "configured provider unavailable", + args: []string{"--cloud"}, + provider: "missing", + wantErr: `cloud resolver plugin "missing" unavailable`, + skip: true, + }, + { + name: "provider cannot be a path", + args: []string{"--cloud"}, + provider: "../foobar", + wantErr: `cloud resolver plugin "../foobar" unavailable`, + skip: true, + }, + { + name: "no cloud option", + noProvider: true, + skip: true, + }, + { + name: "help", + args: []string{"--cloud", "--help"}, + noProvider: true, + skip: true, + }, + { + name: "version", + args: []string{"--cloud", "--version"}, + noProvider: true, + skip: true, + }, + { + name: "help exposes supported provider", + command: []string{"--help"}, + noProvider: true, + visible: true, + skip: true, + }, + { + name: "help hides legacy provider", + command: []string{"--help"}, + noProvider: true, + legacyProvider: true, + skip: true, + }, + { + name: "help hides missing provider", + command: []string{"--help"}, + provider: "missing", + skip: true, + }, + { + name: "completion exposes supported provider", + command: []string{"__complete", "--cl"}, + noProvider: true, + visible: true, + skip: true, + }, + { + name: "completion hides legacy provider", + command: []string{"__complete", "--cl"}, + noProvider: true, + legacyProvider: true, + skip: true, + }, + { + name: "completion hides missing provider", + command: []string{"__complete", "--cl"}, + provider: "missing", + skip: true, + }, + } { + t.Run(tc.name, func(t *testing.T) { + // Explicit --cloud must override inherited endpoint selection. + t.Setenv("DOCKER_CONTEXT", "inherited") + t.Setenv("DOCKER_HOST", "tcp://127.0.0.1:1") + t.Setenv("DOCKER_CLI_HOOKS", "false") + t.Setenv("DOCKER_CONFIG", t.TempDir()) + + configDir := t.TempDir() + installedProvider := "offload" + if !tc.noProvider { + installedProvider = "foobar" + cfg := configfile.New(filepath.Join(configDir, config.ConfigFileName)) + provider := tc.provider + if provider == "" { + provider = "foobar" + } + cfg.Features = map[string]string{"cloud": provider} + assert.NilError(t, cfg.Save()) + } + + pluginDir := filepath.Join(configDir, "cli-plugins") + assert.NilError(t, os.MkdirAll(pluginDir, 0o755)) + + response := tc.response + if response == "" { + response = `{"DOCKER_CONTEXT":"resolved"}` + } + + providerMetadata := metadata.Metadata{SchemaVersion: "0.1.0", Vendor: "test"} + if !tc.legacyProvider { + providerMetadata.Features = map[string]any{cloudResolverFeature: true} + } + pluginMetadata, err := json.Marshal(providerMetadata) + assert.NilError(t, err) + + script := fmt.Sprintf(`#!/bin/sh +if [ "$1" = docker-cli-plugin-metadata ]; then + echo '%s' + exit 0 +fi +printf '%%s\n' "$@" >> "$DOCKER_CONFIG/resolver-args" +echo provisioning >&2 +printf '%%s\n' '%s' +exit %d +`, pluginMetadata, response, tc.exit) + assert.NilError(t, os.WriteFile(filepath.Join(pluginDir, "docker-"+installedProvider), []byte(script), 0o755)) + assert.NilError(t, os.WriteFile(filepath.Join(pluginDir, "docker-cloudtest"), []byte(`#!/bin/sh +if [ "$1" = docker-cli-plugin-metadata ]; then + echo '{"SchemaVersion":"0.1.0","Vendor":"test"}' + exit 0 +fi +printf '%s\n' "$@" > "$CLOUD_TEST_ARGS" +`), 0o755)) + + dispatchFile := filepath.Join(configDir, "dispatch-args") + t.Setenv("CLOUD_TEST_ARGS", dispatchFile) + + contextStore := store.New(filepath.Join(configDir, "contexts"), command.DefaultContextStoreConfig()) + assert.NilError(t, contextStore.CreateOrUpdate(store.Metadata{ + Name: "resolved", + Endpoints: map[string]any{contextdocker.DockerEndpoint: contextdocker.EndpointMeta{Host: "tcp://127.0.0.1:1"}}, + })) + assert.NilError(t, contextStore.CreateOrUpdate(store.Metadata{ + Name: "empty-host", + Endpoints: map[string]any{contextdocker.DockerEndpoint: contextdocker.EndpointMeta{}}, + })) + + args := append([]string{"docker", "--config=" + configDir}, tc.args...) + switch { + case tc.command != nil: + args = append(args, tc.command...) + case tc.plugin || tc.wantErr != "": + args = append(args, "cloudtest", "up", "--cloud=child") + default: + args = append(args, "context", "show") + } + + payload, err := json.Marshal(args) + assert.NilError(t, err) + + var stdout, stderr bytes.Buffer + cmd := exec.CommandContext(t.Context(), executable, "-test.run=^TestCloudCommandProcess$") + cmd.Env = append(os.Environ(), "CLOUD_TEST_COMMAND="+string(payload)) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + err = cmd.Run() + if tc.wantErr != "" { + assert.Assert(t, err != nil) + assert.Check(t, is.Contains(stderr.String(), tc.wantErr)) + _, statErr := os.Stat(dispatchFile) + assert.Assert(t, os.IsNotExist(statErr)) + assert.Equal(t, stdout.String(), "") + } else { + assert.NilError(t, err, stderr.String()) + if tc.command != nil { + assert.Equal(t, strings.Contains(stdout.String(), "--cloud"), tc.visible, stdout.String()) + } + if !tc.skip { + if tc.plugin { + args, err := os.ReadFile(dispatchFile) + assert.NilError(t, err) + assert.Equal(t, string(args), "--context=resolved\n--config="+configDir+"\ncloudtest\nup\n--cloud=child\n") + } else { + assert.Equal(t, stdout.String(), "resolved\n") + } + } + } + + invocation, err := os.ReadFile(filepath.Join(configDir, "resolver-args")) + if tc.skip { + assert.Assert(t, os.IsNotExist(err)) + } else { + assert.NilError(t, err) + assert.Check(t, is.Contains(stderr.String(), "provisioning")) + name := tc.wantName + if name == "" { + name = "default" + } + assert.Equal(t, string(invocation), "--config="+configDir+"\n"+installedProvider+"\n__resolve-context\n--\n"+name+"\n") + } + }) + } +} + +// Run startup in a separate process because it installs process-wide signal +// handlers that intentionally outlive an individual command. +func TestCloudCommandProcess(t *testing.T) { + payload := os.Getenv("CLOUD_TEST_COMMAND") + if payload == "" { + return + } + + assert.NilError(t, json.Unmarshal([]byte(payload), &os.Args)) + + err := dockerMain(context.Background()) + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + } + if err == nil { + os.Exit(0) + } + + os.Exit(getExitCode(err)) +} + +func TestCloudResolutionCancellation(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("fixture plugin uses a shell script") + } + + originalConfig := config.Dir() + t.Cleanup(func() { config.SetDir(originalConfig) }) + config.SetDir(t.TempDir()) + + cfg := configfile.New(filepath.Join(config.Dir(), config.ConfigFileName)) + cfg.Features = map[string]string{"cloud": "foobar"} + assert.NilError(t, cfg.Save()) + + pluginDir := filepath.Join(config.Dir(), "cli-plugins") + assert.NilError(t, os.MkdirAll(pluginDir, 0o755)) + assert.NilError(t, os.WriteFile(filepath.Join(pluginDir, "docker-foobar"), []byte(`#!/bin/sh +if [ "$1" = docker-cli-plugin-metadata ]; then + echo '{"SchemaVersion":"0.1.0","Vendor":"test","Features":{"cloud-context-resolver":true}}' + exit 0 +fi +exec sleep 30 +`), 0o755)) + + dockerCli, err := command.NewDockerCli() + assert.NilError(t, err) + tcmd := newDockerCommand(dockerCli) + tcmd.SetArgs(strings.Fields("--cloud context show")) + cmd, _, err := tcmd.HandleGlobalFlags() + assert.NilError(t, err) + + ctx, cancel := context.WithTimeout(t.Context(), time.Second) + defer cancel() + + _, err = resolveCloudContext(ctx, dockerCli, cmd, "default") + assert.ErrorIs(t, err, context.DeadlineExceeded) +} diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 2341570b91..47c720e941 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -178,6 +178,9 @@ func newDockerCommand(dockerCli *command.DockerCli) *cli.TopLevelCommand { _ = cmd.RegisterFlagCompletionFunc("log-level", completeLogLevels) cmd.Flags().BoolP("version", "v", false, "Print version information and quit") + cmd.Flags().String("cloud", "", "Use a cloud context, provisioning it if necessary (optionally --cloud=NAME)") + cmd.Flags().Lookup("cloud").NoOptDefVal = "default" + cmd.Flags().Lookup("cloud").Hidden = true setFlagErrorFunc(dockerCli, cmd) setupHelpCommand(dockerCli, cmd, helpCmd) @@ -250,6 +253,7 @@ func setHelpFunc(dockerCli command.Cli, cmd *cobra.Command) { ccmd.Println(err) return } + updateCloudFlagVisibility(dockerCli, ccmd.Root()) if len(args) >= 1 { err := tryRunPluginHelp(dockerCli, ccmd, args) @@ -508,7 +512,18 @@ func runDocker(ctx context.Context, dockerCli *command.DockerCli) error { return err } - if err := tcmd.Initialize(command.WithEnableGlobalMeterProvider(), command.WithEnableGlobalTracerProvider()); err != nil { + if err := tcmd.Initialize( + command.WithEnableGlobalMeterProvider(), + command.WithEnableGlobalTracerProvider(), + command.WithContextResolver(func(cli *command.DockerCli) (string, error) { + var err error + os.Args, err = processCloud(ctx, cli, cmd, args, os.Args) + if err != nil { + return "", err + } + return cmd.Flags().GetString("context") + }), + ); err != nil { return err } @@ -538,6 +553,7 @@ func runDocker(ctx context.Context, dockerCli *command.DockerCli) error { if err := pluginmanager.AddPluginCommandStubs(dockerCli, cmd); err != nil { return err } + updateCloudFlagVisibility(dockerCli, cmd) } var subCommand *cobra.Command From 58eea0606474d89f6b6f469def6293e0f62091c3 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 1 Oct 2026 19:42:34 +0200 Subject: [PATCH 11/26] vendor: github.com/Azure/go-ansiterm e937bb47801a full diff: https://github.com/Azure/go-ansiterm/compare/faa5f7b0171c...e937bb47801ae0fd8fb8ff02743f6a93e2b51982 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 6 +- .../Azure/go-ansiterm/csi_entry_state.go | 6 +- .../Azure/go-ansiterm/csi_param_state.go | 5 +- .../go-ansiterm/escape_intermediate_state.go | 2 +- .../Azure/go-ansiterm/escape_state.go | 2 +- vendor/github.com/Azure/go-ansiterm/parser.go | 13 +-- .../go-ansiterm/parser_action_helpers.go | 14 +-- .../Azure/go-ansiterm/parser_actions.go | 16 ++- vendor/github.com/Azure/go-ansiterm/states.go | 2 - .../github.com/Azure/go-ansiterm/utilities.go | 10 -- .../Azure/go-ansiterm/winterm/ansi.go | 99 +------------------ vendor/modules.txt | 2 +- 13 files changed, 30 insertions(+), 149 deletions(-) diff --git a/vendor.mod b/vendor.mod index b154d33338..70f61dfb40 100644 --- a/vendor.mod +++ b/vendor.mod @@ -70,7 +70,7 @@ require ( ) require ( - github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/Azure/go-ansiterm v0.0.0-20260917205352-e937bb47801a // indirect github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0 // indirect; see https://github.com/microsoft/hcsshim/pull/2545 github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect diff --git a/vendor.sum b/vendor.sum index b39e868e64..50fb8e2340 100644 --- a/vendor.sum +++ b/vendor.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20260917205352-e937bb47801a h1:4hxax9ktNjSDoFn1tZSeL6gXMTRMpO0FzjdKfT01jgY= +github.com/Azure/go-ansiterm v0.0.0-20260917205352-e937bb47801a/go.mod h1:3EWSSOZ50kb+arhww0qIaEXHToib/3FjBj9Jj5lcP5g= github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0 h1:71VU8kW/LCxJkx41+YYys1EgQO+AUnPa1TrxTSyYUCU= github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0/go.mod h1:ma0QpxizD4fyyzJ1C7MIblymTD2Nxz5Mho/3CepwIZg= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -203,7 +203,7 @@ golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= diff --git a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go index bcbe00d0c5..01c9519c3d 100644 --- a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go +++ b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go @@ -26,7 +26,7 @@ func (csiState csiEntryState) Handle(b byte) (s state, e error) { func (csiState csiEntryState) Transition(s state) error { csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name()) - csiState.baseState.Transition(s) + _ = csiState.baseState.Transition(s) switch s { case csiState.parser.ground: @@ -34,9 +34,9 @@ func (csiState csiEntryState) Transition(s state) error { case csiState.parser.csiParam: switch { case sliceContains(csiParams, csiState.parser.context.currentChar): - csiState.parser.collectParam() + _ = csiState.parser.collectParam() case sliceContains(intermeds, csiState.parser.context.currentChar): - csiState.parser.collectInter() + _ = csiState.parser.collectInter() } } diff --git a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go index 7ed5e01c34..88146e6fe5 100644 --- a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go +++ b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go @@ -16,8 +16,7 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) { case sliceContains(alphabetics, b): return csiState.parser.ground, nil case sliceContains(csiCollectables, b): - csiState.parser.collectParam() - return csiState, nil + return csiState, csiState.parser.collectParam() case sliceContains(executors, b): return csiState, csiState.parser.execute() } @@ -27,7 +26,7 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) { func (csiState csiParamState) Transition(s state) error { csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name()) - csiState.baseState.Transition(s) + _ = csiState.baseState.Transition(s) switch s { case csiState.parser.ground: diff --git a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go index 1c719db9e4..88429690f9 100644 --- a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go +++ b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go @@ -25,7 +25,7 @@ func (escState escapeIntermediateState) Handle(b byte) (s state, e error) { func (escState escapeIntermediateState) Transition(s state) error { escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name()) - escState.baseState.Transition(s) + _ = escState.baseState.Transition(s) switch s { case escState.parser.ground: diff --git a/vendor/github.com/Azure/go-ansiterm/escape_state.go b/vendor/github.com/Azure/go-ansiterm/escape_state.go index 6390abd231..854e3812a9 100644 --- a/vendor/github.com/Azure/go-ansiterm/escape_state.go +++ b/vendor/github.com/Azure/go-ansiterm/escape_state.go @@ -29,7 +29,7 @@ func (escState escapeState) Handle(b byte) (s state, e error) { func (escState escapeState) Transition(s state) error { escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name()) - escState.baseState.Transition(s) + _ = escState.baseState.Transition(s) switch s { case escState.parser.ground: diff --git a/vendor/github.com/Azure/go-ansiterm/parser.go b/vendor/github.com/Azure/go-ansiterm/parser.go index 03cec7ada6..2e8ef80fb7 100644 --- a/vendor/github.com/Azure/go-ansiterm/parser.go +++ b/vendor/github.com/Azure/go-ansiterm/parser.go @@ -113,16 +113,13 @@ func (ap *AnsiParser) handle(b byte) error { if newState == nil { ap.logf("WARNING: newState is nil") - return errors.New("New state of 'nil' is invalid.") + return errors.New("new state of 'nil' is invalid") } - if newState != ap.currState { - if err := ap.changeState(newState); err != nil { - return err - } + if newState == ap.currState { + return nil } - - return nil + return ap.changeState(newState) } func (ap *AnsiParser) changeState(newState state) error { @@ -136,7 +133,7 @@ func (ap *AnsiParser) changeState(newState state) error { // Perform transition action if err := ap.currState.Transition(newState); err != nil { - ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err) + ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name(), err) return err } diff --git a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go index de0a1f9cde..dc001532a6 100644 --- a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go +++ b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go @@ -4,9 +4,9 @@ import ( "strconv" ) -func parseParams(bytes []byte) ([]string, error) { - paramBuff := make([]byte, 0, 0) - params := []string{} +func parseParams(bytes []byte) []string { + var paramBuff []byte + var params []string for _, v := range bytes { if v == ';' { @@ -14,7 +14,7 @@ func parseParams(bytes []byte) ([]string, error) { // Completed parameter, append it to the list s := string(paramBuff) params = append(params, s) - paramBuff = make([]byte, 0, 0) + paramBuff = paramBuff[:0] } } else { paramBuff = append(paramBuff, v) @@ -27,11 +27,7 @@ func parseParams(bytes []byte) ([]string, error) { params = append(params, s) } - return params, nil -} - -func parseCmd(context ansiContext) (string, error) { - return string(context.currentChar), nil + return params } func getInt(params []string, dflt int) int { diff --git a/vendor/github.com/Azure/go-ansiterm/parser_actions.go b/vendor/github.com/Azure/go-ansiterm/parser_actions.go index 0bb5e51e9a..2aee10159a 100644 --- a/vendor/github.com/Azure/go-ansiterm/parser_actions.go +++ b/vendor/github.com/Azure/go-ansiterm/parser_actions.go @@ -15,10 +15,9 @@ func (ap *AnsiParser) collectInter() error { } func (ap *AnsiParser) escDispatch() error { - cmd, _ := parseCmd(*ap.context) - intermeds := ap.context.interBuffer + cmd := string(ap.context.currentChar) ap.logf("escDispatch currentChar: %#x", ap.context.currentChar) - ap.logf("escDispatch: %v(%v)", cmd, intermeds) + ap.logf("escDispatch: %s(%q)", cmd, string(ap.context.interBuffer)) switch cmd { case "D": // IND @@ -31,14 +30,14 @@ func (ap *AnsiParser) escDispatch() error { return err case "M": // RI return ap.eventHandler.RI() + default: + return nil } - - return nil } func (ap *AnsiParser) csiDispatch() error { - cmd, _ := parseCmd(*ap.context) - params, _ := parseParams(ap.context.paramBuffer) + cmd := string(ap.context.currentChar) + params := parseParams(ap.context.paramBuffer) ap.logf("Parsed params: %v with length: %d", params, len(params)) ap.logf("csiDispatch: %v(%v)", cmd, params) @@ -109,9 +108,8 @@ func (ap *AnsiParser) print() error { return ap.eventHandler.Print(ap.context.currentChar) } -func (ap *AnsiParser) clear() error { +func (ap *AnsiParser) clear() { ap.context = &ansiContext{} - return nil } func (ap *AnsiParser) execute() error { diff --git a/vendor/github.com/Azure/go-ansiterm/states.go b/vendor/github.com/Azure/go-ansiterm/states.go index f2ea1fcd12..cf72692261 100644 --- a/vendor/github.com/Azure/go-ansiterm/states.go +++ b/vendor/github.com/Azure/go-ansiterm/states.go @@ -1,7 +1,5 @@ package ansiterm -type stateID int - type state interface { Enter() error Exit() error diff --git a/vendor/github.com/Azure/go-ansiterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/utilities.go index 392114493a..d94dd3a347 100644 --- a/vendor/github.com/Azure/go-ansiterm/utilities.go +++ b/vendor/github.com/Azure/go-ansiterm/utilities.go @@ -1,9 +1,5 @@ package ansiterm -import ( - "strconv" -) - func sliceContains(bytes []byte, b byte) bool { for _, v := range bytes { if v == b { @@ -13,9 +9,3 @@ func sliceContains(bytes []byte, b byte) bool { return false } - -func convertBytesToInteger(bytes []byte) int { - s := string(bytes) - i, _ := strconv.Atoi(s) - return i -} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go index 5599082ae9..c6cc027a78 100644 --- a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go +++ b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go @@ -5,12 +5,9 @@ package winterm import ( "fmt" "os" - "strconv" - "strings" "syscall" - "github.com/Azure/go-ansiterm" - windows "golang.org/x/sys/windows" + "golang.org/x/sys/windows" ) // Windows keyboard constants @@ -55,100 +52,6 @@ const ( ENHANCED_KEY = 0x0100 ) -type ansiCommand struct { - CommandBytes []byte - Command string - Parameters []string - IsSpecial bool -} - -func newAnsiCommand(command []byte) *ansiCommand { - - if isCharacterSelectionCmdChar(command[1]) { - // Is Character Set Selection commands - return &ansiCommand{ - CommandBytes: command, - Command: string(command), - IsSpecial: true, - } - } - - // last char is command character - lastCharIndex := len(command) - 1 - - ac := &ansiCommand{ - CommandBytes: command, - Command: string(command[lastCharIndex]), - IsSpecial: false, - } - - // more than a single escape - if lastCharIndex != 0 { - start := 1 - // skip if double char escape sequence - if command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_ESCAPE_SECONDARY { - start++ - } - // convert this to GetNextParam method - ac.Parameters = strings.Split(string(command[start:lastCharIndex]), ansiterm.ANSI_PARAMETER_SEP) - } - - return ac -} - -func (ac *ansiCommand) paramAsSHORT(index int, defaultValue int16) int16 { - if index < 0 || index >= len(ac.Parameters) { - return defaultValue - } - - param, err := strconv.ParseInt(ac.Parameters[index], 10, 16) - if err != nil { - return defaultValue - } - - return int16(param) -} - -func (ac *ansiCommand) String() string { - return fmt.Sprintf("0x%v \"%v\" (\"%v\")", - bytesToHex(ac.CommandBytes), - ac.Command, - strings.Join(ac.Parameters, "\",\"")) -} - -// isAnsiCommandChar returns true if the passed byte falls within the range of ANSI commands. -// See http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html. -func isAnsiCommandChar(b byte) bool { - switch { - case ansiterm.ANSI_COMMAND_FIRST <= b && b <= ansiterm.ANSI_COMMAND_LAST && b != ansiterm.ANSI_ESCAPE_SECONDARY: - return true - case b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_OSC || b == ansiterm.ANSI_CMD_DECPAM || b == ansiterm.ANSI_CMD_DECPNM: - // non-CSI escape sequence terminator - return true - case b == ansiterm.ANSI_CMD_STR_TERM || b == ansiterm.ANSI_BEL: - // String escape sequence terminator - return true - } - return false -} - -func isXtermOscSequence(command []byte, current byte) bool { - return (len(command) >= 2 && command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_CMD_OSC && current != ansiterm.ANSI_BEL) -} - -func isCharacterSelectionCmdChar(b byte) bool { - return (b == ansiterm.ANSI_CMD_G0 || b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_G2 || b == ansiterm.ANSI_CMD_G3) -} - -// bytesToHex converts a slice of bytes to a human-readable string. -func bytesToHex(b []byte) string { - hex := make([]string, len(b)) - for i, ch := range b { - hex[i] = fmt.Sprintf("%X", ch) - } - return strings.Join(hex, "") -} - // ensureInRange adjusts the passed value, if necessary, to ensure it is within // the passed min / max range. func ensureInRange(n int16, min int16, max int16) int16 { diff --git a/vendor/modules.txt b/vendor/modules.txt index 982b0e9e78..b22301649e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,7 +1,7 @@ # dario.cat/mergo v1.0.2 ## explicit; go 1.13 dario.cat/mergo -# github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c +# github.com/Azure/go-ansiterm v0.0.0-20260917205352-e937bb47801a ## explicit; go 1.16 github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm From 886ab250f033477ba101771df6110dcee71c2d22 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 1 Oct 2026 22:23:55 +0200 Subject: [PATCH 12/26] vendor: github.com/moby/moby/client v0.6.1, moby/api v1.56.1 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 4 +- vendor.sum | 8 +-- .../moby/api/pkg/authconfig/authconfig.go | 2 +- .../moby/moby/api/types/build/disk_usage.go | 3 - .../moby/api/types/common/error_response.go | 3 - .../moby/moby/api/types/common/id_response.go | 3 - .../moby/api/types/container/change_type.go | 3 - .../api/types/container/create_response.go | 3 - .../moby/api/types/container/disk_usage.go | 3 - .../api/types/container/filesystem_change.go | 3 - .../moby/api/types/container/port_summary.go | 3 - .../moby/api/types/container/top_response.go | 3 - .../api/types/container/update_response.go | 3 - .../api/types/container/wait_exit_error.go | 3 - .../moby/api/types/container/wait_response.go | 3 - .../moby/api/types/image/delete_response.go | 3 - .../moby/moby/api/types/image/disk_usage.go | 3 - .../api/types/image/history_response_item.go | 3 - .../api/types/network/config_reference.go | 3 - .../moby/api/types/network/connect_request.go | 3 - .../moby/api/types/network/create_response.go | 3 - .../api/types/network/disconnect_request.go | 3 - .../api/types/network/endpoint_resource.go | 3 - .../moby/moby/api/types/network/inspect.go | 3 - .../moby/api/types/network/ipam_status.go | 3 - .../moby/moby/api/types/network/network.go | 3 - .../moby/moby/api/types/network/peer_info.go | 3 - .../moby/api/types/network/service_info.go | 3 - .../moby/moby/api/types/network/status.go | 3 - .../moby/api/types/network/subnet_status.go | 3 - .../moby/moby/api/types/network/summary.go | 3 - .../moby/moby/api/types/network/task.go | 3 - .../moby/moby/api/types/plugin/device.go | 3 - .../moby/moby/api/types/plugin/env.go | 3 - .../moby/moby/api/types/plugin/mount.go | 3 - .../moby/moby/api/types/plugin/plugin.go | 3 - .../moby/api/types/registry/auth_response.go | 3 - .../moby/api/types/storage/driver_data.go | 3 - .../api/types/storage/root_f_s_storage.go | 3 - .../storage/root_f_s_storage_snapshot.go | 3 - .../moby/moby/api/types/storage/storage.go | 3 - .../types/swarm/service_create_response.go | 3 - .../types/swarm/service_update_response.go | 3 - .../moby/api/types/volume/create_request.go | 3 - .../moby/moby/api/types/volume/disk_usage.go | 3 - .../moby/api/types/volume/list_response.go | 3 - .../moby/moby/api/types/volume/volume.go | 3 - vendor/github.com/moby/moby/client/client.go | 10 +-- .../moby/moby/client/client_hook.go | 70 +++++++++++++++++++ .../moby/moby/client/client_options.go | 38 +++++++++- .../moby/moby/client/client_responsehook.go | 23 ------ .../moby/moby/client/container_attach.go | 5 +- .../moby/moby/client/container_exec.go | 6 +- vendor/github.com/moby/moby/client/hijack.go | 24 +++++-- .../moby/moby/client/plugin_create.go | 4 +- vendor/modules.txt | 4 +- 56 files changed, 142 insertions(+), 188 deletions(-) create mode 100644 vendor/github.com/moby/moby/client/client_hook.go delete mode 100644 vendor/github.com/moby/moby/client/client_responsehook.go diff --git a/vendor.mod b/vendor.mod index b154d33338..166423b46c 100644 --- a/vendor.mod +++ b/vendor.mod @@ -33,8 +33,8 @@ require ( github.com/google/uuid v1.6.0 github.com/mattn/go-runewidth v0.0.29 github.com/moby/go-archive v0.3.3 - github.com/moby/moby/api v1.56.0 - github.com/moby/moby/client v0.6.0 + github.com/moby/moby/api v1.56.1 + github.com/moby/moby/client v0.6.1 github.com/moby/patternmatcher v0.6.1 github.com/moby/swarmkit/v2 v2.1.2 github.com/moby/sys/atomicwriter v0.1.0 diff --git a/vendor.sum b/vendor.sum index b39e868e64..0a584f4479 100644 --- a/vendor.sum +++ b/vendor.sum @@ -88,10 +88,10 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.3.3 h1:OxxR9paxsluYi+zDUEXTTaIxtkK3viymW+Ka7vRhhME= github.com/moby/go-archive v0.3.3/go.mod h1:Npdv43fFqlhZW7Xo8fbm3ZMYFvAGNviUPqX21VERbcE= -github.com/moby/moby/api v1.56.0 h1:GQzua3NA599ASSIICx0iFgiJeO9YkdDARvQsm23ZZuQ= -github.com/moby/moby/api v1.56.0/go.mod h1:sZ+THbVWkjOmBPPfbnzdD/G1LuIexWhqlSHHPTDQ1Uk= -github.com/moby/moby/client v0.6.0 h1:AJjEB21QPbXSXjDsZorFBoDZPhMrfbpaPLgSMAW9Bgs= -github.com/moby/moby/client v0.6.0/go.mod h1:OCo00wNRyA3m4lmJ228W3JbyCN4ZNNYjpOXiJydBdcQ= +github.com/moby/moby/api v1.56.1 h1:PpWkvVPB7Fr/No8w+TfyJ/I6rWZ2YPZhT3JorIg+06c= +github.com/moby/moby/api v1.56.1/go.mod h1:sZ+THbVWkjOmBPPfbnzdD/G1LuIexWhqlSHHPTDQ1Uk= +github.com/moby/moby/client v0.6.1 h1:gvfKmdcWw+9MzXYP0vAUKQtBTGu1L8475K2nsmL7O98= +github.com/moby/moby/client v0.6.1/go.mod h1:XHgTFqz9NCgS/VuoxXMmEDVmVgXQ4vFEc15wsCIwb24= github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U= github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/swarmkit/v2 v2.1.2 h1:1WDZAI6HVYNKdCG4zlXnTAPyLsLwuhRGWlHoOUf5Z6I= diff --git a/vendor/github.com/moby/moby/api/pkg/authconfig/authconfig.go b/vendor/github.com/moby/moby/api/pkg/authconfig/authconfig.go index d1b0105a68..9e9686878c 100644 --- a/vendor/github.com/moby/moby/api/pkg/authconfig/authconfig.go +++ b/vendor/github.com/moby/moby/api/pkg/authconfig/authconfig.go @@ -21,7 +21,7 @@ func Encode(authConfig registry.AuthConfig) (string, error) { // // FIXME(thaJeztah): find exactly what code-paths are impacted by this. // if authConfig == (AuthConfig{}) { return "", nil } - buf, err := json.Marshal(authConfig) + buf, err := json.Marshal(authConfig) // #nosec G117 -- intentionally marshaling auth. if err != nil { return "", errInvalidParameter{err} } diff --git a/vendor/github.com/moby/moby/api/types/build/disk_usage.go b/vendor/github.com/moby/moby/api/types/build/disk_usage.go index 3613797dba..bf178f81e6 100644 --- a/vendor/github.com/moby/moby/api/types/build/disk_usage.go +++ b/vendor/github.com/moby/moby/api/types/build/disk_usage.go @@ -2,9 +2,6 @@ package build -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // DiskUsage represents system data usage for build cache resources. // // swagger:model DiskUsage diff --git a/vendor/github.com/moby/moby/api/types/common/error_response.go b/vendor/github.com/moby/moby/api/types/common/error_response.go index b49d3eea0a..9c7f2fdc2d 100644 --- a/vendor/github.com/moby/moby/api/types/common/error_response.go +++ b/vendor/github.com/moby/moby/api/types/common/error_response.go @@ -2,9 +2,6 @@ package common -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // ErrorResponse Represents an error. // Example: {"message":"Something went wrong."} // diff --git a/vendor/github.com/moby/moby/api/types/common/id_response.go b/vendor/github.com/moby/moby/api/types/common/id_response.go index 7dfe4bf12b..546f5e8d1f 100644 --- a/vendor/github.com/moby/moby/api/types/common/id_response.go +++ b/vendor/github.com/moby/moby/api/types/common/id_response.go @@ -2,9 +2,6 @@ package common -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // IDResponse Response to an API call that returns just an Id // // swagger:model IDResponse diff --git a/vendor/github.com/moby/moby/api/types/container/change_type.go b/vendor/github.com/moby/moby/api/types/container/change_type.go index 52fc99235b..1f2ac105f7 100644 --- a/vendor/github.com/moby/moby/api/types/container/change_type.go +++ b/vendor/github.com/moby/moby/api/types/container/change_type.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // ChangeType Kind of change // // Can be one of: diff --git a/vendor/github.com/moby/moby/api/types/container/create_response.go b/vendor/github.com/moby/moby/api/types/container/create_response.go index 39d761aa96..9fc92fb6fe 100644 --- a/vendor/github.com/moby/moby/api/types/container/create_response.go +++ b/vendor/github.com/moby/moby/api/types/container/create_response.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // CreateResponse ContainerCreateResponse // // # OK response to ContainerCreate operation diff --git a/vendor/github.com/moby/moby/api/types/container/disk_usage.go b/vendor/github.com/moby/moby/api/types/container/disk_usage.go index c36721d3b0..0c0a772d62 100644 --- a/vendor/github.com/moby/moby/api/types/container/disk_usage.go +++ b/vendor/github.com/moby/moby/api/types/container/disk_usage.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // DiskUsage represents system data usage information for container resources. // // swagger:model DiskUsage diff --git a/vendor/github.com/moby/moby/api/types/container/filesystem_change.go b/vendor/github.com/moby/moby/api/types/container/filesystem_change.go index b9ec83e521..d895095259 100644 --- a/vendor/github.com/moby/moby/api/types/container/filesystem_change.go +++ b/vendor/github.com/moby/moby/api/types/container/filesystem_change.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // FilesystemChange Change in the container's filesystem. // // swagger:model FilesystemChange diff --git a/vendor/github.com/moby/moby/api/types/container/port_summary.go b/vendor/github.com/moby/moby/api/types/container/port_summary.go index 68148eece4..0cb7455f36 100644 --- a/vendor/github.com/moby/moby/api/types/container/port_summary.go +++ b/vendor/github.com/moby/moby/api/types/container/port_summary.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - import ( "net/netip" ) diff --git a/vendor/github.com/moby/moby/api/types/container/top_response.go b/vendor/github.com/moby/moby/api/types/container/top_response.go index 966603617f..50124e8a76 100644 --- a/vendor/github.com/moby/moby/api/types/container/top_response.go +++ b/vendor/github.com/moby/moby/api/types/container/top_response.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // TopResponse ContainerTopResponse // // Container "top" response. diff --git a/vendor/github.com/moby/moby/api/types/container/update_response.go b/vendor/github.com/moby/moby/api/types/container/update_response.go index 2f7263b141..94e5eccb20 100644 --- a/vendor/github.com/moby/moby/api/types/container/update_response.go +++ b/vendor/github.com/moby/moby/api/types/container/update_response.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // UpdateResponse ContainerUpdateResponse // // Response for a successful container-update. diff --git a/vendor/github.com/moby/moby/api/types/container/wait_exit_error.go b/vendor/github.com/moby/moby/api/types/container/wait_exit_error.go index 96a7770c34..50f353f95e 100644 --- a/vendor/github.com/moby/moby/api/types/container/wait_exit_error.go +++ b/vendor/github.com/moby/moby/api/types/container/wait_exit_error.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // WaitExitError container waiting error, if any // // swagger:model WaitExitError diff --git a/vendor/github.com/moby/moby/api/types/container/wait_response.go b/vendor/github.com/moby/moby/api/types/container/wait_response.go index 68d3c38724..ff9281dd91 100644 --- a/vendor/github.com/moby/moby/api/types/container/wait_response.go +++ b/vendor/github.com/moby/moby/api/types/container/wait_response.go @@ -2,9 +2,6 @@ package container -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // WaitResponse ContainerWaitResponse // // # OK response to ContainerWait operation diff --git a/vendor/github.com/moby/moby/api/types/image/delete_response.go b/vendor/github.com/moby/moby/api/types/image/delete_response.go index b19119a381..c0a0a5af3d 100644 --- a/vendor/github.com/moby/moby/api/types/image/delete_response.go +++ b/vendor/github.com/moby/moby/api/types/image/delete_response.go @@ -2,9 +2,6 @@ package image -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // DeleteResponse delete response // // swagger:model DeleteResponse diff --git a/vendor/github.com/moby/moby/api/types/image/disk_usage.go b/vendor/github.com/moby/moby/api/types/image/disk_usage.go index 7297813c1d..bbe2d57672 100644 --- a/vendor/github.com/moby/moby/api/types/image/disk_usage.go +++ b/vendor/github.com/moby/moby/api/types/image/disk_usage.go @@ -2,9 +2,6 @@ package image -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // DiskUsage represents system data usage for image resources. // // swagger:model DiskUsage diff --git a/vendor/github.com/moby/moby/api/types/image/history_response_item.go b/vendor/github.com/moby/moby/api/types/image/history_response_item.go index 3de3181ab9..c7b1eddcd9 100644 --- a/vendor/github.com/moby/moby/api/types/image/history_response_item.go +++ b/vendor/github.com/moby/moby/api/types/image/history_response_item.go @@ -2,9 +2,6 @@ package image -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // HistoryResponseItem HistoryResponseItem // // individual image layer information in response to ImageHistory operation diff --git a/vendor/github.com/moby/moby/api/types/network/config_reference.go b/vendor/github.com/moby/moby/api/types/network/config_reference.go index 1158afe655..0c940a9e74 100644 --- a/vendor/github.com/moby/moby/api/types/network/config_reference.go +++ b/vendor/github.com/moby/moby/api/types/network/config_reference.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // ConfigReference The config-only network source to provide the configuration for // this network. // diff --git a/vendor/github.com/moby/moby/api/types/network/connect_request.go b/vendor/github.com/moby/moby/api/types/network/connect_request.go index 2ff14d3603..68fbf16844 100644 --- a/vendor/github.com/moby/moby/api/types/network/connect_request.go +++ b/vendor/github.com/moby/moby/api/types/network/connect_request.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // ConnectRequest NetworkConnectRequest represents the data to be used to connect a container to a network. // // swagger:model ConnectRequest diff --git a/vendor/github.com/moby/moby/api/types/network/create_response.go b/vendor/github.com/moby/moby/api/types/network/create_response.go index 1997059912..429b278e48 100644 --- a/vendor/github.com/moby/moby/api/types/network/create_response.go +++ b/vendor/github.com/moby/moby/api/types/network/create_response.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // CreateResponse NetworkCreateResponse // // # OK response to NetworkCreate operation diff --git a/vendor/github.com/moby/moby/api/types/network/disconnect_request.go b/vendor/github.com/moby/moby/api/types/network/disconnect_request.go index 7b1f521e77..aeebee70a9 100644 --- a/vendor/github.com/moby/moby/api/types/network/disconnect_request.go +++ b/vendor/github.com/moby/moby/api/types/network/disconnect_request.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // DisconnectRequest NetworkDisconnectRequest represents the data to be used to disconnect a container from a network. // // swagger:model DisconnectRequest diff --git a/vendor/github.com/moby/moby/api/types/network/endpoint_resource.go b/vendor/github.com/moby/moby/api/types/network/endpoint_resource.go index bf493ad5dd..a9ab27ae3c 100644 --- a/vendor/github.com/moby/moby/api/types/network/endpoint_resource.go +++ b/vendor/github.com/moby/moby/api/types/network/endpoint_resource.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - import ( "net/netip" ) diff --git a/vendor/github.com/moby/moby/api/types/network/inspect.go b/vendor/github.com/moby/moby/api/types/network/inspect.go index cded5e6081..c07026ac40 100644 --- a/vendor/github.com/moby/moby/api/types/network/inspect.go +++ b/vendor/github.com/moby/moby/api/types/network/inspect.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Inspect The body of the "get network" http response message. // // swagger:model Inspect diff --git a/vendor/github.com/moby/moby/api/types/network/ipam_status.go b/vendor/github.com/moby/moby/api/types/network/ipam_status.go index 7eb4e8487e..50e410ff8f 100644 --- a/vendor/github.com/moby/moby/api/types/network/ipam_status.go +++ b/vendor/github.com/moby/moby/api/types/network/ipam_status.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // IPAMStatus IPAM status // // swagger:model IPAMStatus diff --git a/vendor/github.com/moby/moby/api/types/network/network.go b/vendor/github.com/moby/moby/api/types/network/network.go index a7d9c0f6ad..b2d4d43cd2 100644 --- a/vendor/github.com/moby/moby/api/types/network/network.go +++ b/vendor/github.com/moby/moby/api/types/network/network.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - import ( timeext "time" ) diff --git a/vendor/github.com/moby/moby/api/types/network/peer_info.go b/vendor/github.com/moby/moby/api/types/network/peer_info.go index dc88ec16fa..8638e61623 100644 --- a/vendor/github.com/moby/moby/api/types/network/peer_info.go +++ b/vendor/github.com/moby/moby/api/types/network/peer_info.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - import ( "net/netip" ) diff --git a/vendor/github.com/moby/moby/api/types/network/service_info.go b/vendor/github.com/moby/moby/api/types/network/service_info.go index fdd92f1611..abb3619533 100644 --- a/vendor/github.com/moby/moby/api/types/network/service_info.go +++ b/vendor/github.com/moby/moby/api/types/network/service_info.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - import ( "net/netip" ) diff --git a/vendor/github.com/moby/moby/api/types/network/status.go b/vendor/github.com/moby/moby/api/types/network/status.go index 94f4b4b2ec..b90f1bf1e8 100644 --- a/vendor/github.com/moby/moby/api/types/network/status.go +++ b/vendor/github.com/moby/moby/api/types/network/status.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Status provides runtime information about the network such as the number of allocated IPs. // // swagger:model Status diff --git a/vendor/github.com/moby/moby/api/types/network/subnet_status.go b/vendor/github.com/moby/moby/api/types/network/subnet_status.go index dd62429f5f..de74c7a2e6 100644 --- a/vendor/github.com/moby/moby/api/types/network/subnet_status.go +++ b/vendor/github.com/moby/moby/api/types/network/subnet_status.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // SubnetStatus subnet status // // swagger:model SubnetStatus diff --git a/vendor/github.com/moby/moby/api/types/network/summary.go b/vendor/github.com/moby/moby/api/types/network/summary.go index 3f50ce2278..50c346ffa5 100644 --- a/vendor/github.com/moby/moby/api/types/network/summary.go +++ b/vendor/github.com/moby/moby/api/types/network/summary.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Summary Network list response item // // swagger:model Summary diff --git a/vendor/github.com/moby/moby/api/types/network/task.go b/vendor/github.com/moby/moby/api/types/network/task.go index a547523a44..c0eac2322e 100644 --- a/vendor/github.com/moby/moby/api/types/network/task.go +++ b/vendor/github.com/moby/moby/api/types/network/task.go @@ -2,9 +2,6 @@ package network -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - import ( "net/netip" ) diff --git a/vendor/github.com/moby/moby/api/types/plugin/device.go b/vendor/github.com/moby/moby/api/types/plugin/device.go index ae96177047..2044e4b99a 100644 --- a/vendor/github.com/moby/moby/api/types/plugin/device.go +++ b/vendor/github.com/moby/moby/api/types/plugin/device.go @@ -2,9 +2,6 @@ package plugin -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Device device // // swagger:model Device diff --git a/vendor/github.com/moby/moby/api/types/plugin/env.go b/vendor/github.com/moby/moby/api/types/plugin/env.go index dcbe0b762d..99ee46dabf 100644 --- a/vendor/github.com/moby/moby/api/types/plugin/env.go +++ b/vendor/github.com/moby/moby/api/types/plugin/env.go @@ -2,9 +2,6 @@ package plugin -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Env env // // swagger:model Env diff --git a/vendor/github.com/moby/moby/api/types/plugin/mount.go b/vendor/github.com/moby/moby/api/types/plugin/mount.go index 7970306cc8..9426a94c57 100644 --- a/vendor/github.com/moby/moby/api/types/plugin/mount.go +++ b/vendor/github.com/moby/moby/api/types/plugin/mount.go @@ -2,9 +2,6 @@ package plugin -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Mount mount // // swagger:model Mount diff --git a/vendor/github.com/moby/moby/api/types/plugin/plugin.go b/vendor/github.com/moby/moby/api/types/plugin/plugin.go index 3305170d5e..2dcf83be25 100644 --- a/vendor/github.com/moby/moby/api/types/plugin/plugin.go +++ b/vendor/github.com/moby/moby/api/types/plugin/plugin.go @@ -2,9 +2,6 @@ package plugin -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Plugin A plugin for the Engine API // // swagger:model Plugin diff --git a/vendor/github.com/moby/moby/api/types/registry/auth_response.go b/vendor/github.com/moby/moby/api/types/registry/auth_response.go index 94c2e1bb36..c7057d8606 100644 --- a/vendor/github.com/moby/moby/api/types/registry/auth_response.go +++ b/vendor/github.com/moby/moby/api/types/registry/auth_response.go @@ -2,9 +2,6 @@ package registry -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // AuthResponse An identity token was generated successfully. // // swagger:model AuthResponse diff --git a/vendor/github.com/moby/moby/api/types/storage/driver_data.go b/vendor/github.com/moby/moby/api/types/storage/driver_data.go index 65d5b4c20e..5e6cb22ab5 100644 --- a/vendor/github.com/moby/moby/api/types/storage/driver_data.go +++ b/vendor/github.com/moby/moby/api/types/storage/driver_data.go @@ -2,9 +2,6 @@ package storage -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // DriverData Information about the storage driver used to store the container's and // image's filesystem. // diff --git a/vendor/github.com/moby/moby/api/types/storage/root_f_s_storage.go b/vendor/github.com/moby/moby/api/types/storage/root_f_s_storage.go index d82f2b6bcb..ecf63ea0cc 100644 --- a/vendor/github.com/moby/moby/api/types/storage/root_f_s_storage.go +++ b/vendor/github.com/moby/moby/api/types/storage/root_f_s_storage.go @@ -2,9 +2,6 @@ package storage -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // RootFSStorage Information about the storage used for the container's root filesystem. // // swagger:model RootFSStorage diff --git a/vendor/github.com/moby/moby/api/types/storage/root_f_s_storage_snapshot.go b/vendor/github.com/moby/moby/api/types/storage/root_f_s_storage_snapshot.go index dd2b82d245..c040636da8 100644 --- a/vendor/github.com/moby/moby/api/types/storage/root_f_s_storage_snapshot.go +++ b/vendor/github.com/moby/moby/api/types/storage/root_f_s_storage_snapshot.go @@ -2,9 +2,6 @@ package storage -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // RootFSStorageSnapshot Information about a snapshot backend of the container's root filesystem. // // swagger:model RootFSStorageSnapshot diff --git a/vendor/github.com/moby/moby/api/types/storage/storage.go b/vendor/github.com/moby/moby/api/types/storage/storage.go index 77843db970..4cf31c54b5 100644 --- a/vendor/github.com/moby/moby/api/types/storage/storage.go +++ b/vendor/github.com/moby/moby/api/types/storage/storage.go @@ -2,9 +2,6 @@ package storage -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Storage Information about the storage used by the container. // // swagger:model Storage diff --git a/vendor/github.com/moby/moby/api/types/swarm/service_create_response.go b/vendor/github.com/moby/moby/api/types/swarm/service_create_response.go index ebbc097d90..2dcc49c903 100644 --- a/vendor/github.com/moby/moby/api/types/swarm/service_create_response.go +++ b/vendor/github.com/moby/moby/api/types/swarm/service_create_response.go @@ -2,9 +2,6 @@ package swarm -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // ServiceCreateResponse contains the information returned to a client on the // creation of a new service. // diff --git a/vendor/github.com/moby/moby/api/types/swarm/service_update_response.go b/vendor/github.com/moby/moby/api/types/swarm/service_update_response.go index b7649096a0..be5d44c4cf 100644 --- a/vendor/github.com/moby/moby/api/types/swarm/service_update_response.go +++ b/vendor/github.com/moby/moby/api/types/swarm/service_update_response.go @@ -2,9 +2,6 @@ package swarm -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // ServiceUpdateResponse service update response // Example: {"Warnings":["unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"]} // diff --git a/vendor/github.com/moby/moby/api/types/volume/create_request.go b/vendor/github.com/moby/moby/api/types/volume/create_request.go index 3217df8270..17c5f86784 100644 --- a/vendor/github.com/moby/moby/api/types/volume/create_request.go +++ b/vendor/github.com/moby/moby/api/types/volume/create_request.go @@ -2,9 +2,6 @@ package volume -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // CreateRequest VolumeConfig // // # Volume configuration diff --git a/vendor/github.com/moby/moby/api/types/volume/disk_usage.go b/vendor/github.com/moby/moby/api/types/volume/disk_usage.go index e2afbac659..cbf740e33c 100644 --- a/vendor/github.com/moby/moby/api/types/volume/disk_usage.go +++ b/vendor/github.com/moby/moby/api/types/volume/disk_usage.go @@ -2,9 +2,6 @@ package volume -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // DiskUsage represents system data usage for volume resources. // // swagger:model DiskUsage diff --git a/vendor/github.com/moby/moby/api/types/volume/list_response.go b/vendor/github.com/moby/moby/api/types/volume/list_response.go index f257762f09..02dc415a5f 100644 --- a/vendor/github.com/moby/moby/api/types/volume/list_response.go +++ b/vendor/github.com/moby/moby/api/types/volume/list_response.go @@ -2,9 +2,6 @@ package volume -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // ListResponse VolumeListResponse // // # Volume list response diff --git a/vendor/github.com/moby/moby/api/types/volume/volume.go b/vendor/github.com/moby/moby/api/types/volume/volume.go index 524ebfb8ac..a3d6d82864 100644 --- a/vendor/github.com/moby/moby/api/types/volume/volume.go +++ b/vendor/github.com/moby/moby/api/types/volume/volume.go @@ -2,9 +2,6 @@ package volume -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - // Volume volume // // swagger:model Volume diff --git a/vendor/github.com/moby/moby/client/client.go b/vendor/github.com/moby/moby/client/client.go index 3dbcacdeb9..f407505e01 100644 --- a/vendor/github.com/moby/moby/client/client.go +++ b/vendor/github.com/moby/moby/client/client.go @@ -60,7 +60,6 @@ import ( "net/url" "path" "runtime" - "slices" "strings" "sync" "sync/atomic" @@ -250,10 +249,11 @@ func New(ops ...Opt) (*Client, error) { c.client.Transport = otelhttp.NewTransport(c.client.Transport, c.traceOpts...) - if len(cfg.responseHooks) > 0 { - c.client.Transport = &responseHookTransport{ - base: c.client.Transport, - hooks: slices.Clone(cfg.responseHooks), + if len(cfg.requestHooks) > 0 || len(cfg.responseHooks) > 0 { + c.client.Transport = &hookTransport{ + base: c.client.Transport, + reqHooks: cfg.requestHooks, + respHooks: cfg.responseHooks, } } diff --git a/vendor/github.com/moby/moby/client/client_hook.go b/vendor/github.com/moby/moby/client/client_hook.go new file mode 100644 index 0000000000..c9afa34ddd --- /dev/null +++ b/vendor/github.com/moby/moby/client/client_hook.go @@ -0,0 +1,70 @@ +package client + +import ( + "errors" + "io" + "net/http" +) + +type hookTransport struct { + base http.RoundTripper + reqHooks []RequestHook + respHooks []ResponseHook +} + +func (t *hookTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if len(t.reqHooks) > 0 { + hookReq := req.Clone(req.Context()) + + if hookReq.Body != nil { + hookReq.Body = hookBody{} + } + if hookReq.GetBody != nil { + hookReq.GetBody = func() (io.ReadCloser, error) { + return hookBody{}, nil + } + } + + for _, h := range t.reqHooks { + if err := h(hookReq); err != nil { + // The base transport never takes ownership, so close the original + // request body before returning the hook error. + if req.Body != nil { + _ = req.Body.Close() + } + return nil, err + } + } + // Restore the actual request body after the hooks have run. The + // modified request metadata is preserved on hookReq. + hookReq.Body = req.Body + hookReq.GetBody = req.GetBody + req = hookReq + } + + resp, err := t.base.RoundTrip(req) + if err != nil { + return resp, err + } + + if len(t.respHooks) > 0 { + hookResp := *resp + if hookResp.Body != nil { + hookResp.Body = hookBody{} + } + + for _, h := range t.respHooks { + h(&hookResp) + } + } + + return resp, nil +} + +type hookBody struct{} + +func (hookBody) Read([]byte) (int, error) { + return 0, errors.New("hooks must not read HTTP message body") +} + +func (hookBody) Close() error { return nil } diff --git a/vendor/github.com/moby/moby/client/client_options.go b/vendor/github.com/moby/moby/client/client_options.go index 3992557230..3499172c4d 100644 --- a/vendor/github.com/moby/moby/client/client_options.go +++ b/vendor/github.com/moby/moby/client/client_options.go @@ -58,13 +58,23 @@ type clientConfig struct { // takes precedence. Either field disables API-version negotiation. envAPIVersion string - // responseHooks is a list of custom response hooks to call on responses. + // requestHooks contains hooks to call before requests are made. + requestHooks []RequestHook + // responseHooks contains hooks to call on responses. responseHooks []ResponseHook // traceOpts is a list of options to configure the tracing span. traceOpts []otelhttp.Option } +// RequestHook is called for each HTTP request made by the client. +// Hooks are invoked in the order they were added. +// +// Hooks may inspect the request and modify request metadata, such as headers, +// before the request is sent. The request body cannot be read or closed by +// the hook. +type RequestHook func(*http.Request) error + // ResponseHook is called for each HTTP response returned by the daemon. // Hooks are invoked in the order they were added. // @@ -411,12 +421,25 @@ func WithTraceOptions(opts ...otelhttp.Option) Opt { } } -// WithResponseHook adds a ResponseHook to the client. ResponseHooks are called +// WithHTTPRequestHook adds a [RequestHook] to the client. RequestHooks are called +// before an HTTP request is made to the daemon. Hooks are invoked in the order +// they were added. +func WithHTTPRequestHook(h RequestHook) Opt { + return func(c *clientConfig) error { + if h == nil { + return errors.New("invalid request hook: hook is nil") + } + c.requestHooks = append(c.requestHooks, h) + return nil + } +} + +// WithHTTPResponseHook adds a [ResponseHook] to the client. ResponseHooks are called // for each HTTP response returned by the daemon. Hooks are invoked in the order // they were added. // // Hooks must not read or close resp.Body. -func WithResponseHook(h ResponseHook) Opt { +func WithHTTPResponseHook(h ResponseHook) Opt { return func(c *clientConfig) error { if h == nil { return errors.New("invalid response hook: hook is nil") @@ -425,3 +448,12 @@ func WithResponseHook(h ResponseHook) Opt { return nil } } + +// WithResponseHook is equivalent to [WithHTTPResponseHook]. +// +// Deprecated: use [WithHTTPResponseHook] instead. +// +//go:fix inline +func WithResponseHook(h ResponseHook) Opt { + return WithHTTPResponseHook(h) +} diff --git a/vendor/github.com/moby/moby/client/client_responsehook.go b/vendor/github.com/moby/moby/client/client_responsehook.go deleted file mode 100644 index 7c93f111c7..0000000000 --- a/vendor/github.com/moby/moby/client/client_responsehook.go +++ /dev/null @@ -1,23 +0,0 @@ -package client - -import ( - "net/http" -) - -type responseHookTransport struct { - base http.RoundTripper - hooks []ResponseHook -} - -func (t *responseHookTransport) RoundTrip(req *http.Request) (*http.Response, error) { - resp, err := t.base.RoundTrip(req) - if err != nil { - return resp, err - } - - for _, h := range t.hooks { - h(resp) - } - - return resp, nil -} diff --git a/vendor/github.com/moby/moby/client/container_attach.go b/vendor/github.com/moby/moby/client/container_attach.go index ce84122d32..9619e812b2 100644 --- a/vendor/github.com/moby/moby/client/container_attach.go +++ b/vendor/github.com/moby/moby/client/container_attach.go @@ -75,9 +75,8 @@ func (cli *Client) ContainerAttach(ctx context.Context, containerID string, opti query.Set("logs", "1") } - hijacked, err := cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{ - "Content-Type": {"text/plain"}, - }) + headers := http.Header{"Content-Type": {"text/plain"}} + hijacked, err := cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, headers, nil) if err != nil { return ContainerAttachResult{}, err } diff --git a/vendor/github.com/moby/moby/client/container_exec.go b/vendor/github.com/moby/moby/client/container_exec.go index 86c9474b48..d831521842 100644 --- a/vendor/github.com/moby/moby/client/container_exec.go +++ b/vendor/github.com/moby/moby/client/container_exec.go @@ -134,13 +134,11 @@ func (cli *Client) ExecAttach(ctx context.Context, execID string, options ExecAt if err != nil { return ExecAttachResult{}, err } - req := container.ExecStartRequest{ + headers := http.Header{"Content-Type": {"application/json"}} + response, err := cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, headers, container.ExecStartRequest{ Detach: false, Tty: options.TTY, ConsoleSize: consoleSize, - } - response, err := cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, req, http.Header{ - "Content-Type": {"application/json"}, }) return ExecAttachResult{HijackedResponse: response}, err } diff --git a/vendor/github.com/moby/moby/client/hijack.go b/vendor/github.com/moby/moby/client/hijack.go index 3b6b12c8fd..fb3a232608 100644 --- a/vendor/github.com/moby/moby/client/hijack.go +++ b/vendor/github.com/moby/moby/client/hijack.go @@ -13,7 +13,7 @@ import ( ) // postHijacked sends a POST request and hijacks the connection. -func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body any, headers map[string][]string) (HijackedResponse, error) { +func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, headers map[string][]string, body any) (HijackedResponse, error) { jsonBody, err := jsonEncode(body) if err != nil { return HijackedResponse{}, err @@ -22,7 +22,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu if err != nil { return HijackedResponse{}, err } - conn, mediaType, err := setupHijackConn(cli.dialer(), req, "tcp") + conn, mediaType, err := cli.setupHijackConn(req, "tcp") if err != nil { return HijackedResponse{}, err } @@ -38,16 +38,17 @@ func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[s } req = cli.addHeaders(req, meta) - conn, _, err := setupHijackConn(cli.Dialer(), req, proto) + conn, _, err := cli.setupHijackConn(req, proto) return conn, err } -func setupHijackConn(dialer func(context.Context) (net.Conn, error), req *http.Request, proto string) (_ net.Conn, _ string, retErr error) { +func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn, _ string, retErr error) { ctx := req.Context() req.Header.Set("Connection", "Upgrade") req.Header.Set("Upgrade", proto) - conn, err := dialer(ctx) + dial := cli.dialer() + conn, err := dial(ctx) if err != nil { return nil, "", fmt.Errorf("cannot connect to the Docker daemon. Is 'docker daemon' running on this host?: %w", err) } @@ -69,8 +70,19 @@ func setupHijackConn(dialer func(context.Context) (net.Conn, error), req *http.R hc := &hijackedConn{conn, bufio.NewReader(conn)} + cfg := &cli.clientConfig + + var rt http.RoundTripper = otelhttp.NewTransport(hc, cli.traceOpts...) + if len(cfg.requestHooks) > 0 || len(cfg.responseHooks) > 0 { + rt = &hookTransport{ + base: rt, + reqHooks: cfg.requestHooks, + respHooks: cfg.responseHooks, + } + } + // Server hijacks the connection, error 'connection closed' expected - resp, err := otelhttp.NewTransport(hc).RoundTrip(req) + resp, err := rt.RoundTrip(req) if err != nil { return nil, "", err } diff --git a/vendor/github.com/moby/moby/client/plugin_create.go b/vendor/github.com/moby/moby/client/plugin_create.go index f4e7c9a02f..774b9e36b5 100644 --- a/vendor/github.com/moby/moby/client/plugin_create.go +++ b/vendor/github.com/moby/moby/client/plugin_create.go @@ -19,12 +19,10 @@ type PluginCreateResult struct { // PluginCreate creates a plugin func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, createOptions PluginCreateOptions) (PluginCreateResult, error) { - headers := http.Header(make(map[string][]string)) - headers.Set("Content-Type", "application/x-tar") - query := url.Values{} query.Set("name", createOptions.RepoName) + headers := http.Header{"Content-Type": {"application/x-tar"}} resp, err := cli.postRaw(ctx, "/plugins/create", query, headers, createContext) defer ensureReaderClosed(resp) return PluginCreateResult{}, err diff --git a/vendor/modules.txt b/vendor/modules.txt index 982b0e9e78..b9349f3d10 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -167,7 +167,7 @@ github.com/moby/go-archive github.com/moby/go-archive/compression github.com/moby/go-archive/internal/archiveoptions github.com/moby/go-archive/tarheader -# github.com/moby/moby/api v1.56.0 +# github.com/moby/moby/api v1.56.1 ## explicit; go 1.24 github.com/moby/moby/api/pkg/authconfig github.com/moby/moby/api/pkg/stdcopy @@ -189,7 +189,7 @@ github.com/moby/moby/api/types/storage github.com/moby/moby/api/types/swarm github.com/moby/moby/api/types/system github.com/moby/moby/api/types/volume -# github.com/moby/moby/client v0.6.0 +# github.com/moby/moby/client v0.6.1 ## explicit; go 1.24 github.com/moby/moby/client github.com/moby/moby/client/internal From 6cb63efe6f0df2dc8b5658404edc6d7c0ad8ed96 Mon Sep 17 00:00:00 2001 From: Nick Sieger Date: Fri, 2 Oct 2026 16:45:34 -0500 Subject: [PATCH 13/26] fix(cli): recognize build/bake/builder aliasing before cloud help check docker --cloud build rejected every BuildKit-only flag (--secret, --ssh, --push, --output, ...) because cloudHelpRequest parsed remaining args against the legacy build command's flag set before processAliases rewrites build into a buildx invocation. Treat build/bake/builder/image build the same as plugin commands: only recognize --help/-h immediately after the resolved command path instead of validating flags. Fixes #7350 Signed-off-by: Nick Sieger --- cmd/docker/cloud.go | 18 +++++++++++++++++- cmd/docker/cloud_test.go | 5 +++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cmd/docker/cloud.go b/cmd/docker/cloud.go index f2a127bb42..72a37bd44d 100644 --- a/cmd/docker/cloud.go +++ b/cmd/docker/cloud.go @@ -199,7 +199,17 @@ func cloudHelpRequest(rootCmd *cobra.Command, args []string) (bool, error) { if err != nil || cmd == rootCmd || pluginmanager.IsPluginCommand(cmd) { // Plugin flags are opaque. Only recognize help immediately after the // plugin name; deeper help is available through "docker help PLUGIN". - return len(args) > 1 && (args[1] == "--help" || args[1] == "-h" || args[1] == "--help=true"), nil + return len(args) > 1 && isHelpFlag(args[1]), nil + } + + // "build", "bake", "builder", and "image build" are builtin commands that + // processAliases may still rewrite into a call to the builder plugin + // (buildx) after cloud resolution runs, so their flag set here is only the + // legacy builder's and does not reflect what will actually parse the + // remaining args. Treat them like a plugin command above: only recognize + // help immediately after the resolved command path. + if _, _, _, forwarded := forwardBuilder(builderDefaultPlugin, args, args); forwarded { + return len(remaining) > 0 && isHelpFlag(remaining[0]), nil } cmd.InitDefaultHelpFlag() @@ -226,6 +236,12 @@ func cloudHelpRequest(rootCmd *cobra.Command, args []string) (bool, error) { return help, nil } +// isHelpFlag reports whether arg requests help, in any of the forms pflag +// accepts for a boolean flag. +func isHelpFlag(arg string) bool { + return arg == "--help" || arg == "-h" || arg == "--help=true" +} + // cloudPluginArgs only rewrites the global prefix, leaving subcommand arguments // untouched. Parsing also distinguishes --cloud from another flag's value. func cloudPluginArgs(cmd *cobra.Command, osArgs []string, contextName string) ([]string, error) { diff --git a/cmd/docker/cloud_test.go b/cmd/docker/cloud_test.go index f1ce8a60a8..9f6b1ab463 100644 --- a/cmd/docker/cloud_test.go +++ b/cmd/docker/cloud_test.go @@ -62,6 +62,11 @@ func TestCloudHelpRequest(t *testing.T) { {name: "container help", args: []string{"run", "alpine", "--help"}}, {name: "flag value", args: []string{"run", "--name", "--help", "alpine"}}, {name: "help disabled", args: []string{"run", "--help=false", "alpine"}}, + {name: "build help", args: []string{"build", "--help"}, help: true}, + {name: "build buildkit-only flag", args: []string{"build", "--secret", "id=s,src=./s", "."}}, + {name: "image build buildkit-only flag", args: []string{"image", "build", "--push", "."}}, + {name: "builder build buildkit-only flag", args: []string{"builder", "build", "--ssh", "default", "."}}, + {name: "bake help", args: []string{"bake", "--help"}, help: true}, } { t.Run(tc.name, func(t *testing.T) { dockerCli, err := command.NewDockerCli() From 488292ca1f1a6529098639bf801368106f553d9e Mon Sep 17 00:00:00 2001 From: Nicolas Beck Date: Mon, 5 Oct 2026 19:59:25 +0000 Subject: [PATCH 14/26] cmd/docker: Allow interactive cloud context resolution Forward stdin and stderr to cloud context providers when both are terminals, allowing prompts during --cloud resolution. Pass file handles directly to preserve terminal detection and leave piped or redirected input available to the requested command. Use the standard console handles when Windows terminal wrappers hide their underlying files. Keep stdout reserved for the JSON response. Signed-off-by: Nicolas Beck --- cmd/docker/cloud.go | 28 ++++++++- cmd/docker/cloud_test.go | 120 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 2 deletions(-) diff --git a/cmd/docker/cloud.go b/cmd/docker/cloud.go index 72a37bd44d..cc3a775e49 100644 --- a/cmd/docker/cloud.go +++ b/cmd/docker/cloud.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "os/exec" + "runtime" "strconv" "strings" @@ -43,8 +44,11 @@ import ( // The effective config directory is also passed as DOCKER_CONFIG. // The provider must provision into that context store without changing the saved // current context or recursively forwarding --cloud. -// It inherits the environment, receives no interactive stdin, and sends progress -// to stderr. +// It inherits the environment and sends progress and prompts to stderr. Stdin +// is forwarded only when both stdin and stderr are terminals with file handles; +// wrapped Windows consoles use the corresponding standard handles. Otherwise +// the provider receives EOF and must not prompt or open a terminal +// separately. Piped and redirected input belongs to the requested command. // Stdout must contain exactly one JSON object: // // {"DOCKER_CONTEXT":"provisioned-context"} @@ -140,6 +144,26 @@ func resolveCloudContext(ctx context.Context, dockerCli *command.DockerCli, root cmd := exec.CommandContext(ctx, plugin.Path, "--config="+config.Dir(), plugin.Name, "__resolve-context", "--", name) // #nosec G204 -- executable validated through CLI plugin discovery cmd.Env = append(os.Environ(), config.EnvOverrideConfigDir+"="+config.Dir(), metadata.ReexecEnvvar+"="+os.Args[0]) cmd.Stderr = dockerCli.Err() + stdinTerminal := dockerCli.In().IsTerminal() + stderrTerminal := dockerCli.Err().IsTerminal() + stdin, stdinFile := dockerCli.In().File() + stderr, stderrFile := dockerCli.Err().File() + if runtime.GOOS == "windows" { + // term.StdStreams can wrap console handles for terminal emulation, + // preventing File from exposing them to the child process. + if stdinTerminal && !stdinFile { + stdin, stdinFile = os.Stdin, true + } + if stderrTerminal && !stderrFile { + stderr, stderrFile = os.Stderr, true + } + } + if stdinTerminal && stderrTerminal && stdinFile && stderrFile { + // Pass files directly: wrapping them makes os/exec copy through pipes, + // hiding terminal identity and potentially consuming the command's input. + cmd.Stdin = stdin + cmd.Stderr = stderr + } out, err := cmd.Output() if err != nil { diff --git a/cmd/docker/cloud_test.go b/cmd/docker/cloud_test.go index 9f6b1ab463..4f25a97b8b 100644 --- a/cmd/docker/cloud_test.go +++ b/cmd/docker/cloud_test.go @@ -16,6 +16,7 @@ import ( "testing" "time" + "github.com/creack/pty" "github.com/docker/cli/cli-plugins/metadata" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/config" @@ -488,6 +489,125 @@ printf '%s\n' "$@" > "$CLOUD_TEST_ARGS" } } +func TestCloudResolverInput(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("fixture plugins use shell scripts and pseudo-terminals") + } + + executable, err := os.Executable() + assert.NilError(t, err) + + for _, tc := range []struct { + name string + stdinType string + terminalErr bool + prompt bool + }{ + {name: "interactive", stdinType: "terminal", terminalErr: true, prompt: true}, + {name: "piped stdin", stdinType: "pipe", terminalErr: true}, + {name: "redirected stdin", stdinType: "file", terminalErr: true}, + {name: "redirected stderr", stdinType: "terminal"}, + {name: "noninteractive", stdinType: "pipe"}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Setenv("DOCKER_CLI_HOOKS", "false") + configDir := t.TempDir() + pluginDir := filepath.Join(configDir, "cli-plugins") + assert.NilError(t, os.MkdirAll(pluginDir, 0o755)) + assert.NilError(t, os.WriteFile(filepath.Join(pluginDir, "docker-offload"), []byte(`#!/bin/sh +if [ "$1" = docker-cli-plugin-metadata ]; then + echo '{"SchemaVersion":"0.1.0","Vendor":"test","Features":{"cloud-context-resolver":true}}' + exit 0 +fi +if [ -t 0 ]; then + [ -t 2 ] || exit 1 + printf 'Continue? ' >&2 + IFS= read -r reply || exit 1 + printf '%s\n' "$reply" > "$DOCKER_CONFIG/resolver-input" +elif IFS= read -r unexpected; then + echo 'resolver consumed command input' >&2 + exit 1 +fi +echo '{"DOCKER_CONTEXT":"resolved"}' +`), 0o755)) + assert.NilError(t, os.WriteFile(filepath.Join(pluginDir, "docker-cloudtest"), []byte(`#!/bin/sh +if [ "$1" = docker-cli-plugin-metadata ]; then + echo '{"SchemaVersion":"0.1.0","Vendor":"test"}' + exit 0 +fi +IFS= read -r input || exit 1 +printf '%s\n' "$input" +`), 0o755)) + + contextStore := store.New(filepath.Join(configDir, "contexts"), command.DefaultContextStoreConfig()) + assert.NilError(t, contextStore.CreateOrUpdate(store.Metadata{ + Name: "resolved", + Endpoints: map[string]any{contextdocker.DockerEndpoint: contextdocker.EndpointMeta{Host: "tcp://127.0.0.1:1"}}, + })) + + terminal, tty, err := pty.Open() + assert.NilError(t, err) + t.Cleanup(func() { + _ = tty.Close() + _ = terminal.Close() + }) + + const commandInput = "input for the original command\n" + var stdin *os.File + switch tc.stdinType { + case "terminal": + stdin = tty + input := commandInput + if tc.prompt { + input = "yes\n" + input + } + _, err = terminal.WriteString(input) + assert.NilError(t, err) + case "pipe": + var writer *os.File + stdin, writer, err = os.Pipe() + assert.NilError(t, err) + t.Cleanup(func() { _ = stdin.Close() }) + t.Cleanup(func() { _ = writer.Close() }) + _, err = writer.WriteString(commandInput) + assert.NilError(t, err) + assert.NilError(t, writer.Close()) + case "file": + inputPath := filepath.Join(configDir, "command-input") + assert.NilError(t, os.WriteFile(inputPath, []byte(commandInput), 0o600)) + stdin, err = os.Open(inputPath) + assert.NilError(t, err) + t.Cleanup(func() { _ = stdin.Close() }) + } + + payload, err := json.Marshal([]string{"docker", "--config=" + configDir, "--cloud", "cloudtest"}) + assert.NilError(t, err) + ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) + defer cancel() + var stdout, stderr bytes.Buffer + cmd := exec.CommandContext(ctx, executable, "-test.run=^TestCloudCommandProcess$") + cmd.Env = append(os.Environ(), "CLOUD_TEST_COMMAND="+string(payload)) + cmd.Stdin = stdin + cmd.Stdout = &stdout + cmd.Stderr = &stderr + cmd.WaitDelay = time.Second + if tc.terminalErr { + cmd.Stderr = tty + } + assert.NilError(t, cmd.Run(), stderr.String()) + assert.Equal(t, stdout.String(), commandInput) + + reply, err := os.ReadFile(filepath.Join(configDir, "resolver-input")) + if tc.prompt { + assert.NilError(t, err) + assert.Equal(t, string(reply), "yes\n") + } else { + assert.Assert(t, os.IsNotExist(err)) + } + }) + } +} + // Run startup in a separate process because it installs process-wide signal // handlers that intentionally outlive an individual command. func TestCloudCommandProcess(t *testing.T) { From 8503a98b68c761c2b537a34dc0dd8bd47865250d Mon Sep 17 00:00:00 2001 From: Nick Sieger Date: Mon, 5 Oct 2026 15:29:43 -0500 Subject: [PATCH 15/26] refactor(cmd/docker): split resolveCloudContext to satisfy gocyclo - extract setResolverStdio for resolver terminal wiring - extract validateResolvedContext for context/endpoint checks Signed-off-by: Nick Sieger --- cmd/docker/cloud.go | 68 ++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/cmd/docker/cloud.go b/cmd/docker/cloud.go index cc3a775e49..1999e70be0 100644 --- a/cmd/docker/cloud.go +++ b/cmd/docker/cloud.go @@ -143,6 +143,38 @@ func resolveCloudContext(ctx context.Context, dockerCli *command.DockerCli, root cmd := exec.CommandContext(ctx, plugin.Path, "--config="+config.Dir(), plugin.Name, "__resolve-context", "--", name) // #nosec G204 -- executable validated through CLI plugin discovery cmd.Env = append(os.Environ(), config.EnvOverrideConfigDir+"="+config.Dir(), metadata.ReexecEnvvar+"="+os.Args[0]) + setResolverStdio(cmd, dockerCli) + + out, err := cmd.Output() + if err != nil { + if ctx.Err() != nil { + return "", ctx.Err() + } + return "", fmt.Errorf("cloud resolver failed: %w", err) + } + + var response struct { + DockerContext string `json:"DOCKER_CONTEXT"` + } + if err := json.Unmarshal(out, &response); err != nil { + return "", fmt.Errorf("invalid cloud resolver response: %w", err) + } + response.DockerContext = strings.TrimSpace(response.DockerContext) + if response.DockerContext == "" || response.DockerContext == command.DefaultContextName { + return "", errors.New("cloud resolver must return a non-default DOCKER_CONTEXT") + } + + if err := validateResolvedContext(dockerCli, response.DockerContext); err != nil { + return "", err + } + + return response.DockerContext, nil +} + +// setResolverStdio connects the resolver to the terminal when both stdin and +// stderr are terminals, so the plugin can prompt interactively. Otherwise +// stderr is forwarded and stdin is left unset. +func setResolverStdio(cmd *exec.Cmd, dockerCli *command.DockerCli) { cmd.Stderr = dockerCli.Err() stdinTerminal := dockerCli.In().IsTerminal() stderrTerminal := dockerCli.Err().IsTerminal() @@ -164,41 +196,25 @@ func resolveCloudContext(ctx context.Context, dockerCli *command.DockerCli, root cmd.Stdin = stdin cmd.Stderr = stderr } +} - out, err := cmd.Output() +// validateResolvedContext checks that the context exists and has a Docker +// endpoint host, so a missing context or endpoint cannot fall back to the +// local engine. +func validateResolvedContext(dockerCli *command.DockerCli, name string) error { + meta, err := dockerCli.ContextStore().GetMetadata(name) if err != nil { - if ctx.Err() != nil { - return "", ctx.Err() - } - return "", fmt.Errorf("cloud resolver failed: %w", err) - } - - var response struct { - DockerContext string `json:"DOCKER_CONTEXT"` - } - if err := json.Unmarshal(out, &response); err != nil { - return "", fmt.Errorf("invalid cloud resolver response: %w", err) - } - response.DockerContext = strings.TrimSpace(response.DockerContext) - if response.DockerContext == "" || response.DockerContext == command.DefaultContextName { - return "", errors.New("cloud resolver must return a non-default DOCKER_CONTEXT") - } - - // Do not allow a missing context or endpoint to fall back to the local engine. - meta, err := dockerCli.ContextStore().GetMetadata(response.DockerContext) - if err != nil { - return "", fmt.Errorf("loading resolved context %q: %w", response.DockerContext, err) + return fmt.Errorf("loading resolved context %q: %w", name, err) } endpoint, err := contextdocker.EndpointFromContext(meta) if err != nil { - return "", fmt.Errorf("invalid resolved context %q: %w", response.DockerContext, err) + return fmt.Errorf("invalid resolved context %q: %w", name, err) } if endpoint.Host == "" { - return "", fmt.Errorf("resolved context %q has no Docker endpoint host", response.DockerContext) + return fmt.Errorf("resolved context %q has no Docker endpoint host", name) } - - return response.DockerContext, nil + return nil } // cloudHelpRequest avoids provisioning for help and shell completion. From fd58705f3a3273f23a39cdc118fcc49b04d3d1bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 08:46:12 +0000 Subject: [PATCH 16/26] build(deps): bump the codeql-actions group across 1 directory with 3 updates Bumps the codeql-actions group with 3 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action). Updates `github/codeql-action/init` from 4.38.0 to 4.38.2 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2) Updates `github/codeql-action/autobuild` from 4.38.0 to 4.38.2 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2) Updates `github/codeql-action/analyze` from 4.38.0 to 4.38.2 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2) --- updated-dependencies: - dependency-name: github/codeql-action/analyze dependency-version: 4.38.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: codeql-actions - dependency-name: github/codeql-action/autobuild dependency-version: 4.38.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: codeql-actions - dependency-name: github/codeql-action/init dependency-version: 4.38.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: codeql-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c7be2e9277..48e32d6ef1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -68,14 +68,14 @@ jobs: cache: false - name: Initialize CodeQL - uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 with: languages: go - name: Autobuild - uses: github/codeql-action/autobuild@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 with: category: "/language:go" From e11705385d993d2718c121ddb0b5481459e50f53 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 6 Oct 2026 11:05:44 +0200 Subject: [PATCH 17/26] vendor: github.com/mattn/go-runewidth v0.0.30 - Wrap: measure grapheme clusters, not runes - Skip grapheme segmentation for text that cannot form clusters - Keep strings that are not valid UTF-8 on the segmenter - #111 - Take the rune fast path in the Truncate functions too full diff: https://github.com/mattn/go-runewidth/compare/v0.0.29...v0.0.30 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 4 +- .../mattn/go-runewidth/runewidth.go | 252 +++++++++++++++++- .../mattn/go-runewidth/runewidth_table.go | 117 ++++++++ vendor/modules.txt | 2 +- 5 files changed, 365 insertions(+), 12 deletions(-) diff --git a/vendor.mod b/vendor.mod index fd127d2ab4..d58bf5fc7c 100644 --- a/vendor.mod +++ b/vendor.mod @@ -31,7 +31,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/uuid v1.6.0 - github.com/mattn/go-runewidth v0.0.29 + github.com/mattn/go-runewidth v0.0.30 github.com/moby/go-archive v0.3.3 github.com/moby/moby/api v1.56.1 github.com/moby/moby/client v0.6.1 diff --git a/vendor.sum b/vendor.sum index 14e2e42170..a06d4cdfd7 100644 --- a/vendor.sum +++ b/vendor.sum @@ -82,8 +82,8 @@ github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLM github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mattn/go-runewidth v0.0.29 h1:3oGF3R/S2N9DQ3ptftzVIvg2eicmojCzlwBEmqEPDfQ= -github.com/mattn/go-runewidth v0.0.29/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8= +github.com/mattn/go-runewidth v0.0.30 h1:+KUuiDA4fF0R1p5FeueHefjDm+GIM+kWfFnDjybOPgk= +github.com/mattn/go-runewidth v0.0.30/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.3.3 h1:OxxR9paxsluYi+zDUEXTTaIxtkK3viymW+Ka7vRhhME= diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go index af03e996e9..c2e0946556 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -54,10 +54,24 @@ var ( strictWidthLUT [2][0x110000]byte strictWidthLUTLimit atomic.Int32 strictWidthLUTOnce sync.Once + + // joinerBits is the joiner table as a bitmap over + // [joinerBase, 0x10000), the range where the per-rune test has to be + // cheap for the fast paths in StringWidth and Wrap to pay off. It is + // 7.6 KB and init fills it in a few microseconds. Runes above it stay + // on the interval search: they are rare in the text these fast paths + // are for, and the emoji that are common there leave the fast path at + // their first joiner anyway. + joinerBits [(0x10000 - joinerBase) / 8]byte ) +// joinerBase is the lowest rune in the joiner table. CR is the only rune +// below it that can form a multi-rune cluster, by pairing with LF. +const joinerBase = 0x300 + func init() { initStrictWidthLUTLow() + fillJoinerBits() strictWidthLUTLimit.Store(0x300) handleEnv() } @@ -446,6 +460,60 @@ func (c *Condition) CreateLUT() { c.lutStrictEmojiNeutral = c.StrictEmojiNeutral } +// isASCII reports whether s has no byte above 0x7F, in which case every +// grapheme cluster in s is a single byte apart from CRLF. +func isASCII(s string) bool { + for i := 0; i < len(s); i++ { + if s[i] >= 0x80 { + return false + } + } + return true +} + +// fillJoinerBits paints joinerBits from the joiner table. +func fillJoinerBits() { + for _, iv := range joiner { + if iv.first >= 0x10000 { + break // the table is sorted, the rest is astral + } + lo, hi := int(iv.first)-joinerBase, int(iv.last)-joinerBase + if hi >= len(joinerBits)*8 { + hi = len(joinerBits)*8 - 1 + } + for lo <= hi { + if lo&7 == 0 && lo+7 <= hi { + joinerBits[lo>>3] = 0xFF + lo += 8 + continue + } + joinerBits[lo>>3] |= 1 << uint(lo&7) + lo++ + } + } + // A byte that is not valid UTF-8 decodes to U+FFFD, and the segmenter + // can gather a run of such bytes into one cluster, which a rune loop + // has no way to see. Marking U+FFFD keeps those strings on the + // segmenter, and the only string it holds back needlessly is one that + // really contains U+FFFD. + i := int(utf8.RuneError) - joinerBase + joinerBits[i>>3] |= 1 << uint(i&7) +} + +// isJoiner reports whether r can join with a neighbour into a multi-rune +// grapheme cluster. A string of runes for which it reports false has one +// rune per cluster, so measuring it needs no grapheme segmentation. +func isJoiner(r rune) bool { + if r < joinerBase { + return r == '\r' + } + if r < 0x10000 { + i := r - joinerBase + return joinerBits[i>>3]&(1<<(uint(i)&7)) != 0 + } + return inTable(r, joiner) +} + // graphemeWidth returns the width of a single grapheme cluster: the sum of // the widths of its runes, capped at 2 cells. The cap keeps multi-rune // sequences that render as a single glyph (ZWJ emoji, flags, Hangul jamo) @@ -489,6 +557,13 @@ func (c *Condition) StringWidth(s string) (width int) { return graphemes: + // Runes first: until one of them can join a cluster, each cluster is a + // single rune and segmenting the string would only find that out the + // expensive way. + if w, ok := c.runeWidthSum(s); ok { + width = w + return + } width = 0 g := graphemes.FromString(s) for g.Next() { @@ -497,12 +572,29 @@ graphemes: return } +// runeWidthSum adds up the widths of the runes in s, and reports false +// without a total once it meets a rune that can join a cluster, which is +// where per-rune widths stop being the whole story. +func (c *Condition) runeWidthSum(s string) (int, bool) { + width := 0 + for _, r := range s { + if isJoiner(r) { + return 0, false + } + width += c.RuneWidth(r) + } + return width, true +} + // Truncate return string truncated with w cells func (c *Condition) Truncate(s string, w int, tail string) string { if c.StringWidth(s) <= w { return s } w -= c.StringWidth(tail) + if pos, ok := c.truncateRunes(s, w); ok { + return s[:pos] + tail + } var width int pos := len(s) g := graphemes.FromString(s) @@ -517,12 +609,45 @@ func (c *Condition) Truncate(s string, w int, tail string) string { return s[:pos] + tail } +// truncateRunes is the loop in Truncate with every rune taken for a whole +// cluster, which holds until a rune can join one. It reports false there +// and leaves the string to the segmenter. +func (c *Condition) truncateRunes(s string, w int) (int, bool) { + width := 0 + for i, r := range s { + if isJoiner(r) { + return 0, false + } + cw := c.RuneWidth(r) + if width+cw > w { + return i, true + } + width += cw + } + return len(s), true +} + +// endsCluster reports whether the byte at i, which follows a rune that +// cannot join a cluster, also starts one. Cutting there is only safe when +// the rune that follows does not reach back. +func endsCluster(s string, i int) bool { + if i >= len(s) { + return true + } + r, _ := utf8.DecodeRuneInString(s[i:]) + return !isJoiner(r) +} + // TruncateLeft cuts w cells from the beginning of the `s`. func (c *Condition) TruncateLeft(s string, w int, prefix string) string { if c.StringWidth(s) <= w { return prefix } + if pos, pad, ok := c.truncateLeftRunes(s, w); ok { + return prefix + strings.Repeat(" ", pad) + s[pos:] + } + var width int pos := len(s) @@ -547,6 +672,32 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string { return prefix + s[pos:] } +// truncateLeftRunes is the loop in TruncateLeft with every rune taken for a +// whole cluster, returning the cut and the padding that replaces the cell +// the cut lands inside. It reports false at the first rune that can join a +// cluster. +func (c *Condition) truncateLeftRunes(s string, w int) (pos, pad int, ok bool) { + width := 0 + for i, r := range s { + if isJoiner(r) { + return 0, 0, false + } + cw := c.RuneWidth(r) + if width+cw > w { + if width >= w { + return i, 0, true + } + end := i + utf8.RuneLen(r) + if !endsCluster(s, end) { + return 0, 0, false + } + return end, width + cw - w, true + } + width += cw + } + return len(s), 0, true +} + // TruncatePrefix cuts the beginning of `s` so the result fits in w cells, with prefix prepended func (c *Condition) TruncatePrefix(s string, w int, prefix string) string { if c.StringWidth(prefix) >= w { @@ -558,6 +709,9 @@ func (c *Condition) TruncatePrefix(s string, w int, prefix string) string { return s } w -= c.StringWidth(prefix) + if pos, ok := c.truncatePrefixRunes(s, sw, w); ok { + return prefix + s[pos:] + } var width int var pos int g := graphemes.FromString(s) @@ -573,29 +727,111 @@ func (c *Condition) TruncatePrefix(s string, w int, prefix string) string { return prefix + s[pos:] } -// Wrap return string wrapped with w cells -func (c *Condition) Wrap(s string, w int) string { +// truncatePrefixRunes is the loop in TruncatePrefix with every rune taken +// for a whole cluster, reporting false at the first rune that can join one. +func (c *Condition) truncatePrefixRunes(s string, sw, w int) (int, bool) { + width := 0 + for i, r := range s { + if isJoiner(r) { + return 0, false + } + cw := c.RuneWidth(r) + if sw-(width+cw) <= w { + end := i + utf8.RuneLen(r) + if !endsCluster(s, end) { + return 0, false + } + return end, true + } + width += cw + } + return 0, true +} + +// wrapRunes wraps s treating every rune as its own grapheme cluster, and +// reports false without a result once it meets a rune that can join one. +func (c *Condition) wrapRunes(s string, w int) (string, bool) { width := 0 var out strings.Builder - // max keeps the capacity hint from dividing by zero when w is 0; a - // non-positive width breaks before every rune, as it always has. out.Grow(len(s) + len(s)/max(w, 1) + 1) for _, r := range s { + if isJoiner(r) { + return "", false + } cw := c.RuneWidth(r) if r == '\n' { out.WriteRune(r) width = 0 continue - } else if width+cw > w { + } + if width+cw > w { out.WriteByte('\n') width = 0 - out.WriteRune(r) - width += cw - continue } out.WriteRune(r) width += cw } + return out.String(), true +} + +// Wrap return string wrapped with w cells +func (c *Condition) Wrap(s string, w int) string { + // ASCII fast path: no grapheme clustering needed for pure ASCII + if isASCII(s) { + width := 0 + var out strings.Builder + // max keeps the capacity hint from dividing by zero when w is 0; + // a non-positive width breaks before every cluster, as it always + // has. + out.Grow(len(s) + len(s)/max(w, 1) + 1) + for i := 0; i < len(s); i++ { + b := s[i] + if b == '\n' { + out.WriteByte(b) + width = 0 + continue + } + // Same rule as the StringWidth fast path: no ASCII byte is + // wide or ambiguous, so the flags in c cannot change this. + cw := 0 + if b >= 0x20 && b != 0x7F { + cw = 1 + } + if width+cw > w { + out.WriteByte('\n') + width = 0 + } + out.WriteByte(b) + width += cw + } + return out.String() + } + // Runes first, as in StringWidth. Reaching a rune that can join a + // cluster throws the wrapped text away and starts over on the + // segmenter, which is the uncommon case. + if out, ok := c.wrapRunes(s, w); ok { + return out + } + width := 0 + var out strings.Builder + out.Grow(len(s) + len(s)/max(w, 1) + 1) + g := graphemes.FromString(s) + for g.Next() { + cluster := g.Value() + // LF and CRLF are each a single cluster + if strings.HasSuffix(cluster, "\n") { + out.WriteString(cluster) + width = 0 + continue + } + cw := c.graphemeWidth(cluster) + if width+cw > w { + out.WriteByte('\n') + width = 0 + } + out.WriteString(cluster) + width += cw + } return out.String() } diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_table.go b/vendor/github.com/mattn/go-runewidth/runewidth_table.go index 62488d97da..be9618dd36 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_table.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_table.go @@ -590,3 +590,120 @@ var emoji = table{ {0x1F947, 0x1F9FF}, {0x1FA58, 0x1FA5F}, {0x1FA6E, 0x1FAFF}, {0x1FC00, 0x1FFFD}, } + +var joiner = table{ + {0x0300, 0x036F}, {0x0483, 0x0489}, {0x0591, 0x05BD}, + {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5}, + {0x05C7, 0x05C7}, {0x0600, 0x0605}, {0x0610, 0x061A}, + {0x064B, 0x065F}, {0x0670, 0x0670}, {0x06D6, 0x06DD}, + {0x06DF, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, + {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A}, + {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x07FD, 0x07FD}, + {0x0816, 0x0819}, {0x081B, 0x0823}, {0x0825, 0x0827}, + {0x0829, 0x082D}, {0x0859, 0x085B}, {0x0890, 0x0891}, + {0x0897, 0x089F}, {0x08CA, 0x0903}, {0x093A, 0x093C}, + {0x093E, 0x094F}, {0x0951, 0x0957}, {0x0962, 0x0963}, + {0x0981, 0x0983}, {0x09BC, 0x09BC}, {0x09BE, 0x09C4}, + {0x09C7, 0x09C8}, {0x09CB, 0x09CD}, {0x09D7, 0x09D7}, + {0x09E2, 0x09E3}, {0x09FE, 0x09FE}, {0x0A01, 0x0A03}, + {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, {0x0A47, 0x0A48}, + {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, {0x0A70, 0x0A71}, + {0x0A75, 0x0A75}, {0x0A81, 0x0A83}, {0x0ABC, 0x0ABC}, + {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD}, + {0x0AE2, 0x0AE3}, {0x0AFA, 0x0AFF}, {0x0B01, 0x0B03}, + {0x0B3C, 0x0B3C}, {0x0B3E, 0x0B44}, {0x0B47, 0x0B48}, + {0x0B4B, 0x0B4D}, {0x0B55, 0x0B57}, {0x0B62, 0x0B63}, + {0x0B82, 0x0B82}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, + {0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7}, {0x0C00, 0x0C04}, + {0x0C3C, 0x0C3C}, {0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, + {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0C62, 0x0C63}, + {0x0C81, 0x0C83}, {0x0CBC, 0x0CBC}, {0x0CBE, 0x0CC4}, + {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6}, + {0x0CE2, 0x0CE3}, {0x0CF3, 0x0CF3}, {0x0D00, 0x0D03}, + {0x0D3B, 0x0D3C}, {0x0D3E, 0x0D44}, {0x0D46, 0x0D48}, + {0x0D4A, 0x0D4E}, {0x0D57, 0x0D57}, {0x0D62, 0x0D63}, + {0x0D81, 0x0D83}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, + {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, {0x0DF2, 0x0DF3}, + {0x0E31, 0x0E31}, {0x0E33, 0x0E3A}, {0x0E47, 0x0E4E}, + {0x0EB1, 0x0EB1}, {0x0EB3, 0x0EBC}, {0x0EC8, 0x0ECE}, + {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, {0x0F37, 0x0F37}, + {0x0F39, 0x0F39}, {0x0F3E, 0x0F3F}, {0x0F71, 0x0F84}, + {0x0F86, 0x0F87}, {0x0F8D, 0x0F97}, {0x0F99, 0x0FBC}, + {0x0FC6, 0x0FC6}, {0x102D, 0x1037}, {0x1039, 0x103E}, + {0x1056, 0x1059}, {0x105E, 0x1060}, {0x1071, 0x1074}, + {0x1082, 0x1082}, {0x1084, 0x1086}, {0x108D, 0x108D}, + {0x109D, 0x109D}, {0x1100, 0x11FF}, {0x135D, 0x135F}, + {0x1712, 0x1715}, {0x1732, 0x1734}, {0x1752, 0x1753}, + {0x1772, 0x1773}, {0x17B4, 0x17D3}, {0x17DD, 0x17DD}, + {0x180B, 0x180D}, {0x180F, 0x180F}, {0x1885, 0x1886}, + {0x18A9, 0x18A9}, {0x1920, 0x192B}, {0x1930, 0x193B}, + {0x1A17, 0x1A1B}, {0x1A55, 0x1A5E}, {0x1A60, 0x1A60}, + {0x1A62, 0x1A62}, {0x1A65, 0x1A7C}, {0x1A7F, 0x1A7F}, + {0x1AB0, 0x1ADD}, {0x1AE0, 0x1AEB}, {0x1B00, 0x1B04}, + {0x1B34, 0x1B44}, {0x1B6B, 0x1B73}, {0x1B80, 0x1B82}, + {0x1BA1, 0x1BAD}, {0x1BE6, 0x1BF3}, {0x1C24, 0x1C37}, + {0x1CD0, 0x1CD2}, {0x1CD4, 0x1CE8}, {0x1CED, 0x1CED}, + {0x1CF4, 0x1CF4}, {0x1CF7, 0x1CF9}, {0x1DC0, 0x1DFF}, + {0x200C, 0x200D}, {0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, + {0x2D7F, 0x2D7F}, {0x2DE0, 0x2DFF}, {0x302A, 0x302F}, + {0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D}, + {0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA802, 0xA802}, + {0xA806, 0xA806}, {0xA80B, 0xA80B}, {0xA823, 0xA827}, + {0xA82C, 0xA82C}, {0xA880, 0xA881}, {0xA8B4, 0xA8C5}, + {0xA8E0, 0xA8F1}, {0xA8FF, 0xA8FF}, {0xA926, 0xA92D}, + {0xA947, 0xA953}, {0xA960, 0xA97C}, {0xA980, 0xA983}, + {0xA9B3, 0xA9C0}, {0xA9E5, 0xA9E5}, {0xAA29, 0xAA36}, + {0xAA43, 0xAA43}, {0xAA4C, 0xAA4D}, {0xAA7C, 0xAA7C}, + {0xAAB0, 0xAAB0}, {0xAAB2, 0xAAB4}, {0xAAB7, 0xAAB8}, + {0xAABE, 0xAABF}, {0xAAC1, 0xAAC1}, {0xAAEB, 0xAAEF}, + {0xAAF5, 0xAAF6}, {0xABE3, 0xABEA}, {0xABEC, 0xABED}, + {0xAC00, 0xD7A3}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, + {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, + {0xFF9E, 0xFF9F}, {0x101FD, 0x101FD}, {0x102E0, 0x102E0}, + {0x10376, 0x1037A}, {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, + {0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, + {0x10AE5, 0x10AE6}, {0x10D24, 0x10D27}, {0x10D69, 0x10D6D}, + {0x10EAB, 0x10EAC}, {0x10EFA, 0x10EFF}, {0x10F46, 0x10F50}, + {0x10F82, 0x10F85}, {0x11000, 0x11002}, {0x11038, 0x11046}, + {0x11070, 0x11070}, {0x11073, 0x11074}, {0x1107F, 0x11082}, + {0x110B0, 0x110BA}, {0x110BD, 0x110BD}, {0x110C2, 0x110C2}, + {0x110CD, 0x110CD}, {0x11100, 0x11102}, {0x11127, 0x11134}, + {0x11145, 0x11146}, {0x11173, 0x11173}, {0x11180, 0x11182}, + {0x111B3, 0x111C0}, {0x111C2, 0x111C3}, {0x111C9, 0x111CC}, + {0x111CE, 0x111CF}, {0x1122C, 0x11237}, {0x1123E, 0x1123E}, + {0x11241, 0x11241}, {0x112DF, 0x112EA}, {0x11300, 0x11303}, + {0x1133B, 0x1133C}, {0x1133E, 0x11344}, {0x11347, 0x11348}, + {0x1134B, 0x1134D}, {0x11357, 0x11357}, {0x11362, 0x11363}, + {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x113B8, 0x113C0}, + {0x113C2, 0x113C2}, {0x113C5, 0x113C5}, {0x113C7, 0x113CA}, + {0x113CC, 0x113D2}, {0x113E1, 0x113E2}, {0x11435, 0x11446}, + {0x1145E, 0x1145E}, {0x114B0, 0x114C3}, {0x115AF, 0x115B5}, + {0x115B8, 0x115C0}, {0x115DC, 0x115DD}, {0x11630, 0x11640}, + {0x116AB, 0x116B7}, {0x1171D, 0x1171F}, {0x11722, 0x1172B}, + {0x1182C, 0x1183A}, {0x11930, 0x11935}, {0x11937, 0x11938}, + {0x1193B, 0x11943}, {0x119D1, 0x119D7}, {0x119DA, 0x119E0}, + {0x119E4, 0x119E4}, {0x11A01, 0x11A0A}, {0x11A33, 0x11A3E}, + {0x11A47, 0x11A47}, {0x11A51, 0x11A5B}, {0x11A84, 0x11A99}, + {0x11B60, 0x11B67}, {0x11C2F, 0x11C36}, {0x11C38, 0x11C3F}, + {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x11D31, 0x11D36}, + {0x11D3A, 0x11D3A}, {0x11D3C, 0x11D3D}, {0x11D3F, 0x11D47}, + {0x11D8A, 0x11D8E}, {0x11D90, 0x11D91}, {0x11D93, 0x11D97}, + {0x11EF3, 0x11EF6}, {0x11F00, 0x11F03}, {0x11F34, 0x11F3A}, + {0x11F3E, 0x11F42}, {0x11F5A, 0x11F5A}, {0x13440, 0x13440}, + {0x13447, 0x13455}, {0x1611E, 0x1612F}, {0x16AF0, 0x16AF4}, + {0x16B30, 0x16B36}, {0x16D63, 0x16D63}, {0x16D67, 0x16D6A}, + {0x16F4F, 0x16F4F}, {0x16F51, 0x16F87}, {0x16F8F, 0x16F92}, + {0x16FE4, 0x16FE4}, {0x16FF0, 0x16FF1}, {0x1BC9D, 0x1BC9E}, + {0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1D165, 0x1D169}, + {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, + {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1DA00, 0x1DA36}, + {0x1DA3B, 0x1DA6C}, {0x1DA75, 0x1DA75}, {0x1DA84, 0x1DA84}, + {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, + {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, + {0x1E026, 0x1E02A}, {0x1E08F, 0x1E08F}, {0x1E130, 0x1E136}, + {0x1E2AE, 0x1E2AE}, {0x1E2EC, 0x1E2EF}, {0x1E4EC, 0x1E4EF}, + {0x1E5EE, 0x1E5EF}, {0x1E6E3, 0x1E6E3}, {0x1E6E6, 0x1E6E6}, + {0x1E6EE, 0x1E6EF}, {0x1E6F5, 0x1E6F5}, {0x1E8D0, 0x1E8D6}, + {0x1E944, 0x1E94A}, {0x1F1E6, 0x1F1FF}, {0x1F3FB, 0x1F3FF}, + {0xE0020, 0xE007F}, {0xE0100, 0xE01EF}, +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 99abe258b6..fec8e98ed5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -155,7 +155,7 @@ github.com/klauspost/compress/internal/le github.com/klauspost/compress/internal/snapref github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash -# github.com/mattn/go-runewidth v0.0.29 +# github.com/mattn/go-runewidth v0.0.30 ## explicit; go 1.23 github.com/mattn/go-runewidth # github.com/moby/docker-image-spec v1.3.1 From 862e7e6ad4138958ec703fcc8f5fbd77be0e6688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Wed, 7 Oct 2026 16:54:38 +0200 Subject: [PATCH 18/26] gha/e2e: Also test against moby master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "master" engine-version to the e2e matrix to catch regressions against the upcoming engine release before it reaches an rc. There is no "master" dind image, so just copy the engine binary from the moby/moby-bin:master image and put it into the latest dind image. Signed-off-by: Paweł Gronowski --- .github/workflows/e2e.yml | 1 + e2e/compose-env.yaml | 1 + e2e/testdata/Dockerfile.connhelper-ssh | 10 +++++++++- e2e/testdata/engine/Dockerfile | 11 ++++++++++- scripts/test/e2e/run | 5 +++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 37d55d6dbe..b7b46b5e71 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -37,6 +37,7 @@ jobs: - alpine - debian engine-version: + - master # moby/moby-bin:master - rc # latest rc - 29 # latest - 28 # latest - 1 diff --git a/e2e/compose-env.yaml b/e2e/compose-env.yaml index c4f3774319..975b1b18eb 100644 --- a/e2e/compose-env.yaml +++ b/e2e/compose-env.yaml @@ -31,6 +31,7 @@ services: dockerfile: engine/Dockerfile args: ENGINE_VERSION: ${ENGINE_VERSION:-29} + ENGINE_SOURCE: ${ENGINE_SOURCE:-dind} privileged: true command: ['--insecure-registry=registry:5000', '--insecure-registry=privateregistry:5001', '--experimental'] environment: diff --git a/e2e/testdata/Dockerfile.connhelper-ssh b/e2e/testdata/Dockerfile.connhelper-ssh index 6f65ea7934..61cde646f1 100644 --- a/e2e/testdata/Dockerfile.connhelper-ssh +++ b/e2e/testdata/Dockerfile.connhelper-ssh @@ -3,8 +3,16 @@ # ENGINE_VERSION is the version of the (docker-in-docker) Docker Engine to # test against. ARG ENGINE_VERSION=29 +# ENGINE_SOURCE is "dind" or "moby-bin" (moby/moby-bin:master). +ARG ENGINE_SOURCE=dind -FROM docker:${ENGINE_VERSION}-dind +FROM docker:${ENGINE_VERSION}-dind AS engine-dind + +# moby/moby-bin only has the daemon binaries. +FROM docker:dind AS engine-moby-bin +COPY --link --from=moby/moby-bin:master / /usr/local/bin/ + +FROM engine-${ENGINE_SOURCE} # the openssh-client update is needed for security reasons when using docker:23.0-dind, currently maintained as an lts by mirantis RUN apk --no-cache add openssl openssh-client openssh-server shadow && \ diff --git a/e2e/testdata/engine/Dockerfile b/e2e/testdata/engine/Dockerfile index d688a20606..3dea13eabc 100644 --- a/e2e/testdata/engine/Dockerfile +++ b/e2e/testdata/engine/Dockerfile @@ -1,5 +1,14 @@ ARG ENGINE_VERSION -FROM docker:${ENGINE_VERSION}-dind +# ENGINE_SOURCE is "dind" or "moby-bin" (moby/moby-bin:master). +ARG ENGINE_SOURCE=dind + +FROM docker:${ENGINE_VERSION}-dind AS engine-dind + +# moby/moby-bin only has the daemon binaries. +FROM docker:dind AS engine-moby-bin +COPY --link --from=moby/moby-bin:master / /usr/local/bin/ + +FROM engine-${ENGINE_SOURCE} # Trust the tlsregistry CA so dockerd connects without --insecure-registry. COPY registry/certs/ca.crt /usr/local/share/ca-certificates/tlsregistry-ca.crt diff --git a/scripts/test/e2e/run b/scripts/test/e2e/run index ad6caaaa13..6f1cc1a4c9 100755 --- a/scripts/test/e2e/run +++ b/scripts/test/e2e/run @@ -42,6 +42,11 @@ setup() { sh e2e/testdata/registry/certs/gen-certs.sh fi + # ENGINE_VERSION=master tests against moby/moby-bin:master. + if [ "${ENGINE_VERSION:-}" = "master" ]; then + export ENGINE_SOURCE=moby-bin + fi + COMPOSE_PROJECT_NAME=$project COMPOSE_FILE=$file docker compose up --build -d >&2 # Ensure supporting services exist before running tests. If one fails to start, From 374636ff15ddba8b09d6f444d8278cf0052fa499 Mon Sep 17 00:00:00 2001 From: Nicolas Beck Date: Wed, 7 Oct 2026 16:48:27 +0000 Subject: [PATCH 19/26] cmd/docker: Add guidance for unavailable cloud plugins Explain how to install the Offload plugin when --cloud cannot find it, and link to the cloud flag documentation. Preserve diagnostic details for invalid or incompatible plugins and limit installation guidance to Offload. Use standard default-value handling in the resolution tests to satisfy the lint complexity limit without changing test coverage. Co-authored-by: Allie Sadler <102604716+aevesdocker@users.noreply.github.com> Signed-off-by: Nicolas Beck --- cmd/docker/cloud.go | 16 +++++++-- cmd/docker/cloud_test.go | 73 ++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/cmd/docker/cloud.go b/cmd/docker/cloud.go index 1999e70be0..baf962c387 100644 --- a/cmd/docker/cloud.go +++ b/cmd/docker/cloud.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" + "github.com/containerd/errdefs" "github.com/docker/cli/cli" pluginmanager "github.com/docker/cli/cli-plugins/manager" "github.com/docker/cli/cli-plugins/metadata" @@ -99,22 +100,31 @@ func processCloud(ctx context.Context, dockerCli *command.DockerCli, cmd *cobra. // the __resolve-context contract. const cloudResolverFeature = "cloud-context-resolver" +const cloudPluginHelp = "to use --cloud, install the plugin. See https://docs.docker.com/go/cloud-flag/" + func cloudProvider(dockerCli config.Provider, rootCmd *cobra.Command) (*pluginmanager.Plugin, error) { provider := dockerCli.ConfigFile().Features["cloud"] if provider == "" { provider = "offload" } + var help string + if provider == "offload" { + help = "\n\n" + cloudPluginHelp + } plugin, err := pluginmanager.GetPlugin(provider, dockerCli, rootCmd) if err != nil { - return nil, fmt.Errorf("cloud resolver plugin %q unavailable: %w", provider, err) + if provider == "offload" && errdefs.IsNotFound(err) { + return nil, errors.New(cloudPluginHelp) + } + return nil, fmt.Errorf("plugin %q unavailable: %w%s", provider, err, help) } if plugin.Err != nil { - return nil, fmt.Errorf("invalid cloud resolver plugin %q: %w", provider, plugin.Err) + return nil, fmt.Errorf("invalid plugin %q: %w%s", provider, plugin.Err, help) } if supported, _ := plugin.Features[cloudResolverFeature].(bool); !supported { - return nil, fmt.Errorf("plugin %q does not support cloud context resolution", provider) + return nil, fmt.Errorf("plugin %q does not support --cloud%s", provider, help) } return plugin, nil diff --git a/cmd/docker/cloud_test.go b/cmd/docker/cloud_test.go index 4f25a97b8b..485f3bc2b0 100644 --- a/cmd/docker/cloud_test.go +++ b/cmd/docker/cloud_test.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "cmp" "context" "encoding/json" "fmt" @@ -175,19 +176,21 @@ func TestCloudResolution(t *testing.T) { assert.NilError(t, err) for _, tc := range []struct { - name string - args []string - response string - exit int - wantName string - wantErr string - plugin bool - skip bool - provider string - noProvider bool - legacyProvider bool - command []string - visible bool + name string + args []string + response string + exit int + wantName string + wantErr string + plugin bool + skip bool + provider string + noProvider bool + legacyProvider bool + invalidProvider bool + wantHelp bool + command []string + visible bool }{ { name: "default target", @@ -282,28 +285,45 @@ func TestCloudResolution(t *testing.T) { args: []string{"--cloud"}, noProvider: true, legacyProvider: true, - wantErr: `plugin "offload" does not support cloud context resolution`, + wantErr: `plugin "offload" does not support --cloud`, + wantHelp: true, skip: true, }, + { + name: "invalid default provider", + args: []string{"--cloud"}, + noProvider: true, + invalidProvider: true, + wantErr: `invalid plugin "offload": plugin metadata does not define a vendor`, + wantHelp: true, + skip: true, + }, + { + name: "invalid configured provider", + args: []string{"--cloud"}, + invalidProvider: true, + wantErr: `invalid plugin "foobar": plugin metadata does not define a vendor`, + skip: true, + }, { name: "legacy configured provider", args: []string{"--cloud"}, legacyProvider: true, - wantErr: `plugin "foobar" does not support cloud context resolution`, + wantErr: `plugin "foobar" does not support --cloud`, skip: true, }, { name: "configured provider unavailable", args: []string{"--cloud"}, provider: "missing", - wantErr: `cloud resolver plugin "missing" unavailable`, + wantErr: `plugin "missing" unavailable`, skip: true, }, { name: "provider cannot be a path", args: []string{"--cloud"}, provider: "../foobar", - wantErr: `cloud resolver plugin "../foobar" unavailable`, + wantErr: `plugin "../foobar" unavailable`, skip: true, }, { @@ -376,10 +396,7 @@ func TestCloudResolution(t *testing.T) { if !tc.noProvider { installedProvider = "foobar" cfg := configfile.New(filepath.Join(configDir, config.ConfigFileName)) - provider := tc.provider - if provider == "" { - provider = "foobar" - } + provider := cmp.Or(tc.provider, "foobar") cfg.Features = map[string]string{"cloud": provider} assert.NilError(t, cfg.Save()) } @@ -387,12 +404,12 @@ func TestCloudResolution(t *testing.T) { pluginDir := filepath.Join(configDir, "cli-plugins") assert.NilError(t, os.MkdirAll(pluginDir, 0o755)) - response := tc.response - if response == "" { - response = `{"DOCKER_CONTEXT":"resolved"}` - } + response := cmp.Or(tc.response, `{"DOCKER_CONTEXT":"resolved"}`) providerMetadata := metadata.Metadata{SchemaVersion: "0.1.0", Vendor: "test"} + if tc.invalidProvider { + providerMetadata.Vendor = "" + } if !tc.legacyProvider { providerMetadata.Features = map[string]any{cloudResolverFeature: true} } @@ -454,6 +471,7 @@ printf '%s\n' "$@" > "$CLOUD_TEST_ARGS" if tc.wantErr != "" { assert.Assert(t, err != nil) assert.Check(t, is.Contains(stderr.String(), tc.wantErr)) + assert.Equal(t, strings.Contains(stderr.String(), cloudPluginHelp), tc.wantHelp, stderr.String()) _, statErr := os.Stat(dispatchFile) assert.Assert(t, os.IsNotExist(statErr)) assert.Equal(t, stdout.String(), "") @@ -479,10 +497,7 @@ printf '%s\n' "$@" > "$CLOUD_TEST_ARGS" } else { assert.NilError(t, err) assert.Check(t, is.Contains(stderr.String(), "provisioning")) - name := tc.wantName - if name == "" { - name = "default" - } + name := cmp.Or(tc.wantName, "default") assert.Equal(t, string(invocation), "--config="+configDir+"\n"+installedProvider+"\n__resolve-context\n--\n"+name+"\n") } }) From 4ae247756e95990c51ae729d609fc1383b63b442 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 7 Oct 2026 23:56:10 +0200 Subject: [PATCH 20/26] vendor: github.com/Azure/go-ansiterm 8c912ac31dd4 - update minimum go version to go1.17 - update minimum golang.org/x/sys to v0.1.0 full diff: https://github.com/Azure/go-ansiterm/compare/e937bb47801a...8c912ac31dd4 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 5 ++--- vendor/modules.txt | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/vendor.mod b/vendor.mod index d58bf5fc7c..4a7f5853a8 100644 --- a/vendor.mod +++ b/vendor.mod @@ -70,7 +70,7 @@ require ( ) require ( - github.com/Azure/go-ansiterm v0.0.0-20260917205352-e937bb47801a // indirect + github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 // indirect github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0 // indirect; see https://github.com/microsoft/hcsshim/pull/2545 github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect diff --git a/vendor.sum b/vendor.sum index a06d4cdfd7..bb416723a4 100644 --- a/vendor.sum +++ b/vendor.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20260917205352-e937bb47801a h1:4hxax9ktNjSDoFn1tZSeL6gXMTRMpO0FzjdKfT01jgY= -github.com/Azure/go-ansiterm v0.0.0-20260917205352-e937bb47801a/go.mod h1:3EWSSOZ50kb+arhww0qIaEXHToib/3FjBj9Jj5lcP5g= +github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 h1:m2xcjRABtG288vnlV3U/PKh/HnPURxZp50RKNUwBxM8= +github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4/go.mod h1:MTUE7ZuZO89FAtAwozGg6AWD83pcdefnEq5gF82MB8s= github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0 h1:71VU8kW/LCxJkx41+YYys1EgQO+AUnPa1TrxTSyYUCU= github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0/go.mod h1:ma0QpxizD4fyyzJ1C7MIblymTD2Nxz5Mho/3CepwIZg= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -203,7 +203,6 @@ golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= diff --git a/vendor/modules.txt b/vendor/modules.txt index fec8e98ed5..dc910389f0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,8 +1,8 @@ # dario.cat/mergo v1.0.2 ## explicit; go 1.13 dario.cat/mergo -# github.com/Azure/go-ansiterm v0.0.0-20260917205352-e937bb47801a -## explicit; go 1.16 +# github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 +## explicit; go 1.17 github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm # github.com/Microsoft/go-winio v0.6.3-0.20260930231756-f19d9717deb0 From 63445d6b70df8a69fb518a649ec8db1405504cd5 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 8 Oct 2026 16:03:13 +0200 Subject: [PATCH 21/26] vendor: github.com/docker/go-connections v0.8.2 v0.8.2 - sockets: preserve configured TLS ALPN protocols - ci: add dependabot to update actions - ci: update runners to Ubuntu 26.04 - build(deps): bump actions/checkout from 6.0.2 to 7.0.1 - build(deps): bump actions/setup-go from 6.3.0 to 7.0.0 - build(deps): bump golangci/golangci-lint-action from 9.2.0 to 9.3.0 full diff: https://github.com/docker/go-connections/compare/v0.8.1...v0.8.2 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 4 ++-- .../github.com/docker/go-connections/sockets/tcp_socket.go | 6 +++++- vendor/modules.txt | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/vendor.mod b/vendor.mod index 4a7f5853a8..379731d356 100644 --- a/vendor.mod +++ b/vendor.mod @@ -22,7 +22,7 @@ require ( github.com/docker/cli-docs-tool v0.11.0 github.com/docker/distribution v2.8.3+incompatible github.com/docker/docker-credential-helpers v0.9.9 - github.com/docker/go-connections v0.8.1 + github.com/docker/go-connections v0.8.2 github.com/docker/go-units v0.5.0 github.com/fvbommel/sortorder v1.2.0 github.com/go-jose/go-jose/v4 v4.1.5 diff --git a/vendor.sum b/vendor.sum index bb416723a4..9c3ab4ab9e 100644 --- a/vendor.sum +++ b/vendor.sum @@ -37,8 +37,8 @@ github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBi github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.9.9 h1:BkydjIgZ46JnDbqyM2p2fc63KMw6y+KHL3Em/2AGJ7w= github.com/docker/docker-credential-helpers v0.9.9/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= -github.com/docker/go-connections v0.8.1 h1:JibmG5hULs5qXSr/cp/w3Pw5fZuStt4MOHMUExb29/M= -github.com/docker/go-connections v0.8.1/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= +github.com/docker/go-connections v0.8.2 h1:9d9DEokx5W7qlr0shkFXIxEA7+TTD+llwzcykSlxMNc= +github.com/docker/go-connections v0.8.2/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= github.com/docker/go-events v0.1.0 h1:J8VX4H7Ta8mmBhv/K/24x1kosKOrEEnYmGjcdFHTOW0= github.com/docker/go-events v0.1.0/go.mod h1:jwVwMgySJX4PiukIIRrind1wPGU8QhPa8aTEPkreUj4= github.com/docker/go-metrics v0.1.0 h1:r76KPNpstz+IvQKSWpYegSkkyzex0V3A1ZGVx6bhGlY= diff --git a/vendor/github.com/docker/go-connections/sockets/tcp_socket.go b/vendor/github.com/docker/go-connections/sockets/tcp_socket.go index 53cbb6c79e..3224ed97dc 100644 --- a/vendor/github.com/docker/go-connections/sockets/tcp_socket.go +++ b/vendor/github.com/docker/go-connections/sockets/tcp_socket.go @@ -9,13 +9,17 @@ import ( // NewTCPSocket creates a TCP socket listener with the specified address and // the specified tls configuration. If TLSConfig is set, will encapsulate the // TCP listener inside a TLS one. +// If no ALPN protocols are configured, it defaults to HTTP/1.1. func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { return nil, err } if tlsConfig != nil { - tlsConfig.NextProtos = []string{"http/1.1"} + if len(tlsConfig.NextProtos) == 0 { + tlsConfig = tlsConfig.Clone() + tlsConfig.NextProtos = []string{"http/1.1"} + } l = tls.NewListener(l, tlsConfig) } return l, nil diff --git a/vendor/modules.txt b/vendor/modules.txt index dc910389f0..d7082c4d04 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -71,7 +71,7 @@ github.com/docker/distribution/registry/storage/cache/memory ## explicit; go 1.21 github.com/docker/docker-credential-helpers/client github.com/docker/docker-credential-helpers/credentials -# github.com/docker/go-connections v0.8.1 +# github.com/docker/go-connections v0.8.2 ## explicit; go 1.23 github.com/docker/go-connections/nat github.com/docker/go-connections/sockets From 9db98021278ce511e75435bf23610f52880605ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 8 Oct 2026 20:19:46 +0200 Subject: [PATCH 22/26] Update to go1.26.9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This release includes 15 security fixes following the security policy: - net/http: HTTP/2 server crash due to HPACK encoder race HTTP/2 servers could end up crashing due to inadvertently modifying its HPACK encoder concurrently. This happens because the server modifies the HPACK encoder from two goroutines without synchronization: one uses the encoder to encode a HEADERS frame as part of a response sent to a client and the other modifies the encoder's table size when handling a SETTINGS frame containing SETTINGS_HEADER_TABLE_SIZE that a client sends. A malicious client can repeatedly send a request while changing the header table size to crash the server. Fix this issue by not applying SETTINGS_HEADER_TABLE_SIZE immediately. Instead, buffer any SETTINGS_HEADER_TABLE_SIZE received, and only apply the new value prior to the next time the server writes a frame. Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue. This is CVE-2026-97032 and Go issue https://go.dev/issue/81867. - net/http: HTTP/2 server memory exhaustion due to Trailer headers When "Trailer" headers are sent by a client, the HTTP server internally uses the header values to populate the Request.Trailer map passed to the server handler. Because Request.Trailer is a map, each entry incurs memory overhead. For HTTP/2 servers, a malicious client can exploit this by sending a "Trailer" header that declares a large number of fields, causing the server to allocate a disproportionate amount of memory while bypassing Server.MaxHeaderValueCount and Server.MaxHeaderBytes limits. This exploit is not applicable for HTTP/1 servers, which do not support multiplexing a large number of requests over one TCP connection, and whose Server.MaxHeaderBytes are calculated differently. Server.MaxHeaderValueCount and Server.MaxHeaderBytes limits are now applied towards the trailer fields declared in "Trailer" headers. Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue. This is CVE-2026-78659 and Go issue https://go.dev/issue/81857. - crypto/tls: reject malformed ECH outer extension references Multiple ECH outer extension references are not permitted under RFC 9849; previously, a client could send a well-crafted packet that could trigger memory exhaustion in the server process by specifying multiple references. We now reject these as malformed and curb the memory amplification vector as a result. This is CVE-2026-97031 and Go issue https://go.dev/issue/81855. - cmd/go: checksum bypass for golang.org/fips140 Previously, a user operating inside of a malicious Go project that defines a bogus golang.org/fips140 and operates a malicious GOMODPROXY the user chooses to connect to can serve an arbitrary module in its place. We now unpack the trusted ziphash for the bundled golang.org/fips140 module and construct its entry in the GOMODCACHE such that it can be verified by the toolchain. This is CVE-2026-94444 and Go issue https://go.dev/issue/81833. - cmd/go: checksum database bypass for golang.org/toolchain Previously, a user operating inside of a malicious Go project that defines a bogus golang.org/toolchain go.sum entry and operates a malicious GOMODPROXY the user chooses to use can bypass the intended checksum. We now ensure that golang.org/toolchain always goes to the network for the canonical checksum. This is CVE-2026-94447 and Go issue https://go.dev/issue/81834. - html/template: reset context tracking on consecutive template expressions When a JavaScript template literal contains consecutive expressions, the context tracking state was not properly reset upon entering a new expression. We now ensure that template-literal expression entries correctly reset context variables so all subsequent regular expression literals are accurately recognized and escaped. This is CVE-2026-94448 and Go issue https://go.dev/issue/81821. - html/template: recognize yield as regexp preceder keyword A trusted template author may have previously written a valid template wherein the use of the yield keyword would not be correctly escaped. We now ensure that valid keyword uses are escaped and non-keyword uses are not escaped. This is CVE-2026-97030 and Go issue https://go.dev/issue/81823. - net/textproto, mime/multipart: memory limit bypass when parsing MIME headers Parsing a multipart form could bypass memory limits and read an arbitrarily long line into memory when the remaining limit at the start of a part was less than 400 bytes. Multipart form memory limits are now properly enforced in this situation. Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue. This is CVE-2026-94440 and Go issue https://go.dev/issue/81741. - net/http: HTTP/1 client connection desynchronization after CONNECT rejection When http.Transport sends an HTTP/1 CONNECT request with a non-empty Request.Body, it writes the body directly to the connection without framing after the request headers. If the server rejects the CONNECT request with a non-2xx keep-alive response, Transport returns the connection to the idle pool. Because CONNECT requests do not have a request body, the server may interpret the trailing body bytes as a subsequent pipelined HTTP/1.1 request on the connection, leaving the pooled connection desynchronized and causing the next caller that reuses it to read the response to the injected request. In reverse proxies (including httputil.ReverseProxy) that forward CONNECT requests through a shared Transport, this can lead to cross-user response poisoning. The HTTP/1 transport now closes a connection after sending a CONNECT request, regardless of the response status. In addition, ReverseProxy now rejects incoming CONNECT requests with a 405 Method Not Allowed response. ReverseProxy has never handled CONNECT requests in a useful fashion (it does not convert the connection into a bidirectional tunnel), so we do not expect this change to negatively affect any current users. Thanks to Xclow3n (Rajat Raghav) for reporting this issue. This is CVE-2026-56866 and Go issue https://go.dev/issue/81740. - net/http: HTTP/1 server connection desynchronization after 2xx CONNECT response When an HTTP server handler sent a 2xx response to an HTTP/1 CONNECT request and returned without hijacking the connection, the server improperly continued to read and serve requests from the connection. Since a 2xx response to an HTTP/1 CONNECT converts the connection into a tunnel, the server should not treat the connection as continuing to contain HTTP. The impact of this misbehavior is mostly limited to potential request smuggling, where an intermediate proxy considers the data on the connection to be tunneled and the server considers it to be HTTP. The HTTP/1 server now always closes a connection after responding to a CONNECT request, regardless of the response status. Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue. This is CVE-2026-94439 and Go issue https://go.dev/issue/81744. - net/http: excessive CPU consumption from repeated initial window changes A malicious HTTP/2 peer could cause excessive CPU consumption in the client or server by opening a large number of streams and then sending many small SETTINGS frames containing SETTINGS_INITIAL_WINDOW_SIZE values. The HTTP/2 client and server now efficiently handle changes to the initial window size (O(1) rather than O(number of streams)). Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue. This is CVE-2026-78669 and Go issue https://go.dev/issue/81742. - net/http: HTTP/2 transport accepts malformed framing-related headers Historically, we have been rather lax about malformed framing-related headers in our HTTP/2 implementation, as they cannot interfere with HTTP/2 framing. However, this makes it possible for our HTTP/2 implementation to forward responses containing such headers to an HTTP/1 client when acting as a reverse proxy. If the HTTP/1 client also does not behave strictly enough, this can result in response smuggling. We now delete malformed framing-related headers when received by our HTTP/2 transport, so they will not be forwarded to a potentially vulnerable HTTP/1 client. Thanks to TJ Barton for reporting this issue. This is CVE-2026-78660 and Go issue https://go.dev/issue/81115. - os: Root.Mkdir(All) can follow junctions out of the root on Windows On Windows, when the target of Root.Mkdir or Root.MkdirAll was a junction pointing to an empty location, the operation would create a directory at the junction target even when that target was located outside the root. This only applies to operations where the last path component is a junction (path/to/junction, but not path/junction/target). Root.Mkdir and Root.MkdirAll now correctly avoid resolving junctions. Thanks to Daniele Ballarini for reporting this issue. This is CVE-2026-56857 and Go issue https://go.dev/issue/81739. - net/http: lack of limit on size of parsed Range headers When parsing a Range header containing a large number of small ranges, FileServer(FS), ServeContent, and ServeFile(FS) could consume an excessive amount of CPU. These functions now ignore Range headers containing more than 200 ranges. The limit is controlled by the new httpservecontentmaxranges= GODEBUG setting. Setting GODEBUG=httpservecontentmaxranges=0 disables the limit. Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue. This is CVE-2026-78667 and Go issue https://go.dev/issue/81858. - net/http: double flow control refund on HTTP/2 server streams The HTTP/2 server could refund connection-level flow control twice for the same data: Once when a client resets a stream (refunding data for any sent-but-unread portion of the stream), and again when a request handler reads the buffered data. A malicious client could exploit this to bypass the configured connection-level flow control limit (MaxReceiveBufferPerConnection). Total buffered data is still limited by the concurrent stream limit and stream-level flow control. The HTTP/2 server now waits to refund connection-level flow control for reset streams until after the request handler is complete. Thanks to Ali Sherif (https://www.linkedin.com/in/ali-sherif-13812b276/) for reporting this issue. This is CVE-2026-78663 and Go issue https://go.dev/issue/81743. release notes: https://go.dev/doc/devel/release#go1.26.9 Signed-off-by: Paweł Gronowski --- .github/workflows/codeql.yml | 2 +- .github/workflows/test.yml | 2 +- .github/workflows/validate.yml | 2 +- .golangci.yml | 2 +- Dockerfile | 2 +- dockerfiles/Dockerfile.dev | 2 +- dockerfiles/Dockerfile.lint | 2 +- dockerfiles/Dockerfile.vendor | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 48e32d6ef1..ead4a4f0f2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -64,7 +64,7 @@ jobs: name: Update Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: "1.26.8" + go-version: "1.26.9" cache: false - name: Initialize CodeQL diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 459abb3163..6b6a5ea564 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,7 +68,7 @@ jobs: name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: "1.26.8" + go-version: "1.26.9" cache: false - name: Test diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 25507e1aab..1396c8d7b0 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -101,7 +101,7 @@ jobs: name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: "1.26.8" + go-version: "1.26.9" cache: false - name: Run gocompat check diff --git a/.golangci.yml b/.golangci.yml index ad5a06f1d8..ac80456651 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,7 +5,7 @@ run: # which causes it to fallback to go1.17 semantics. # # TODO(thaJeztah): update "usetesting" settings to enable go1.24 features once our minimum version is go1.24 - go: "1.26.8" + go: "1.26.9" timeout: 5m diff --git a/Dockerfile b/Dockerfile index 02d1fc7d7d..59f519dcbe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ ARG BASE_VARIANT=alpine ARG ALPINE_VERSION=3.23 ARG BASE_DEBIAN_DISTRO=bookworm -ARG GO_VERSION=1.26.8 +ARG GO_VERSION=1.26.9 # XX_VERSION specifies the version of the xx utility to use. # It must be a valid tag in the docker.io/tonistiigi/xx image repository. diff --git a/dockerfiles/Dockerfile.dev b/dockerfiles/Dockerfile.dev index 7f02956252..c1a7d04c27 100644 --- a/dockerfiles/Dockerfile.dev +++ b/dockerfiles/Dockerfile.dev @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -ARG GO_VERSION=1.26.8 +ARG GO_VERSION=1.26.9 # ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image. # It must be a supported tag in the docker.io/library/alpine image repository diff --git a/dockerfiles/Dockerfile.lint b/dockerfiles/Dockerfile.lint index b0404ab8b8..e6acf6f718 100644 --- a/dockerfiles/Dockerfile.lint +++ b/dockerfiles/Dockerfile.lint @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -ARG GO_VERSION=1.26.8 +ARG GO_VERSION=1.26.9 # ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image. # It must be a supported tag in the docker.io/library/alpine image repository diff --git a/dockerfiles/Dockerfile.vendor b/dockerfiles/Dockerfile.vendor index d781ef9830..442e88286e 100644 --- a/dockerfiles/Dockerfile.vendor +++ b/dockerfiles/Dockerfile.vendor @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -ARG GO_VERSION=1.26.8 +ARG GO_VERSION=1.26.9 # ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image. # It must be a supported tag in the docker.io/library/alpine image repository From 949bf401dd8204107463c1fa24aeaeb49349f333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 8 Oct 2026 20:25:01 +0200 Subject: [PATCH 23/26] vendor: golang.org/x/net v0.60.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit full diff: https://golang.org/x/net/compare/v0.59.0...v0.60.0 Signed-off-by: Paweł Gronowski --- vendor.mod | 2 +- vendor.sum | 4 +- vendor/golang.org/x/net/http2/flow.go | 103 +++++++-- vendor/golang.org/x/net/http2/frame.go | 34 ++- vendor/golang.org/x/net/http2/server.go | 110 +++++---- vendor/golang.org/x/net/http2/transport.go | 142 ++++++++---- .../golang.org/x/net/http2/transport_wrap.go | 214 ++++++++++++++++-- vendor/golang.org/x/net/http2/writesched.go | 7 +- .../x/net/internal/httpcommon/gzip.go | 132 +++++++++++ vendor/modules.txt | 2 +- 10 files changed, 598 insertions(+), 152 deletions(-) create mode 100644 vendor/golang.org/x/net/internal/httpcommon/gzip.go diff --git a/vendor.mod b/vendor.mod index 4a7f5853a8..2245115c6c 100644 --- a/vendor.mod +++ b/vendor.mod @@ -102,7 +102,7 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect go.opentelemetry.io/proto/otlp v1.11.0 // indirect golang.org/x/mod v0.41.0 // indirect - golang.org/x/net v0.59.0 // indirect + golang.org/x/net v0.60.0 // indirect golang.org/x/time v0.16.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260825221802-da73d73af1c5 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect diff --git a/vendor.sum b/vendor.sum index bb416723a4..6754ef6f6e 100644 --- a/vendor.sum +++ b/vendor.sum @@ -193,8 +193,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn 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.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues= -golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= +golang.org/x/net v0.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU= +golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/vendor/golang.org/x/net/http2/flow.go b/vendor/golang.org/x/net/http2/flow.go index b7dbd18695..5066a39912 100644 --- a/vendor/golang.org/x/net/http2/flow.go +++ b/vendor/golang.org/x/net/http2/flow.go @@ -10,6 +10,9 @@ package http2 // flow control window update. const inflowMinRefresh = 4 << 10 +// maxFlowWindow is the maximum size of a flow control window. +const maxFlowWindow = (1 << 31) - 1 + // inflow accounts for an inbound flow control window. // It tracks both the latest window sent to the peer (used for enforcement) // and the accumulated unsent window. @@ -74,47 +77,99 @@ func takeInflows(f1, f2 *inflow, n uint32) bool { return true } -// outflow is the outbound flow control window's size. +// connOutflow is connection-level outbound flow control. +type connOutflow struct { + initial int32 // SETTINGS_INITIAL_WINDOW_SIZE, changes with settings updates + n int32 // connection-level flow control window + flowErr bool // set when a flow control error is encountered +} + +func (f *connOutflow) init() { + f.initial = initialWindowSize // initial stream window size + f.n = initialWindowSize // current connection window size +} + +func (f *connOutflow) changeInitialWindowSize(size int64) bool { + if size > maxFlowWindow { + f.flowErr = true + return false + } + f.initial = int32(size) + return true +} + +func (f *connOutflow) add(n int32) bool { + sum := int64(f.n) + int64(n) + if sum > maxFlowWindow { + f.flowErr = true + return false + } + f.n += n + return true +} + +// outflow is the stream-level outbound flow control window's size. type outflow struct { _ incomparable - // n is the number of DATA bytes we're allowed to send. - // An outflow is kept both on a conn and a per-stream. - n int32 + // delta is the difference between the stream's flow control window and + // the connection's initial window size (conn.initial). + // + // Another view is that delta is the number of flow control bytes provided to this + // stream in WINDOW_UPDATE frames, less the number of bytes sent on the stream. + delta int32 // conn points to the shared connection-level outflow that is - // shared by all streams on that conn. It is nil for the outflow - // that's on the conn directly. - conn *outflow + // shared by all streams on that conn. + conn *connOutflow } -func (f *outflow) setConnFlow(cf *outflow) { f.conn = cf } - -func (f *outflow) available() int32 { - n := f.n - if f.conn != nil && f.conn.n < n { - n = f.conn.n +func (f *outflow) available() (int32, bool) { + if f.conn == nil { + return maxFlowWindow, true // only happens in tests } - return n + if f.conn.flowErr { + // Block all sending once any stream observes a flow control error. + return 0, false + } + n := int64(f.conn.initial) + int64(f.delta) + if n > maxFlowWindow { + f.conn.flowErr = true + return 0, false + } + return min(int32(n), f.conn.n), true } func (f *outflow) take(n int32) { - if n > f.available() { + if f.conn == nil { + return // only happens in tests + } + avail, _ := f.available() + if n > avail { panic("internal error: took too much") } - f.n -= n - if f.conn != nil { - f.conn.n -= n - } + f.delta -= n + f.conn.n -= n } // add adds n bytes (positive or negative) to the flow control window. // It returns false if the sum would exceed 2^31-1. func (f *outflow) add(n int32) bool { - sum := f.n + n - if (sum > n) == (f.n > 0) { - f.n = sum - return true + if f.conn == nil { + return true // only happens in tests } - return false + avail := int64(f.conn.initial) + int64(f.delta) + if avail > maxFlowWindow { + // An earlier change to the initial window pushed this stream over the limit. + // This is a connection-level flow control error. + f.conn.flowErr = true + return false + } + if avail+int64(n) > maxFlowWindow { + // This update would push the stream over the limit. + // This is a stream-level flow control error. + return false + } + f.delta += n + return true } diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go index be75badcc0..3363bbafc8 100644 --- a/vendor/golang.org/x/net/http2/frame.go +++ b/vendor/golang.org/x/net/http2/frame.go @@ -1711,7 +1711,8 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (Frame, error) { mh := &MetaHeadersFrame{ HeadersFrame: hf, } - var remainSize = fr.maxHeaderListSize() + var headersRemainSize = fr.maxHeaderListSize() + var trailersRemainSize = fr.maxHeaderListSize() var sawRegular bool var invalid error // pseudo header field errors @@ -1743,14 +1744,29 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (Frame, error) { return } - size := hf.Size() - if size > remainSize { + var remainSize *uint32 + var size uint32 + if hf.Name == "trailer" { + remainSize = &trailersRemainSize + fieldCount := strings.Count(hf.Value, ",") + 1 + // Rather than actually constructing hpack.HeaderField for each + // trailer field and cumulatively adding its Size, just do the math + // manually to avoid unnecessary work. This does make it so + // whitespaces after comma are counted against the budget, but that + // should be innocuous. + size = uint32(len(hf.Value)-fieldCount+1) + uint32(fieldCount)*hpack.HeaderField{}.Size() + } else { + remainSize = &headersRemainSize + size = hf.Size() + } + if size > *remainSize { hdec.SetEmitEnabled(false) mh.Truncated = true - remainSize = 0 + headersRemainSize = 0 + trailersRemainSize = 0 return } - remainSize -= size + *remainSize -= size mh.Fields = append(mh.Fields, hf) }) @@ -1766,10 +1782,10 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (Frame, error) { // skip parsing the fragment and close the connection. // // "Too much" is either any CONTINUATION frame after we've already - // exceeded the max header list size (in which case remainSize is 0), - // or a frame whose encoded size is more than twice the remaining - // header list bytes we're willing to accept. - if int64(len(frag)) > int64(2*remainSize) { + // exceeded the max header list size (if so, both budgets are 0), or a + // frame whose encoded size is more than twice the remaining header + // list bytes we're willing to accept. + if int64(len(frag)) > 2*int64(headersRemainSize+trailersRemainSize) { if VerboseLogs { log.Printf("http2: header list too large") } diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index a7d2053b6c..a6cd66226d 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -280,7 +280,6 @@ func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverCon doneServing: make(chan struct{}), clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value" advMaxStreams: conf.MaxConcurrentStreams, - initialStreamSendWindowSize: initialWindowSize, initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream, maxFrameSize: initialMaxFrameSize, pingTimeout: conf.PingTimeout, @@ -320,7 +319,7 @@ func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverCon // These start at the RFC-specified defaults. If there is a higher // configured value for inflow, that will be updated when we send a // WINDOW_UPDATE shortly after sending SETTINGS. - sc.flow.add(initialWindowSize) + sc.flow.init() sc.inflow.init(initialWindowSize) sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf) sc.hpackEncoder.SetMaxDynamicTableSizeLimit(conf.MaxEncoderHeaderTableSize) @@ -427,7 +426,7 @@ type serverConn struct { wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes bodyReadCh chan bodyReadMsg // from handlers -> serve serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop - flow outflow // conn-wide (not stream-specific) outbound flow control + flow connOutflow // conn-wide (not stream-specific) outbound flow control inflow inflow // conn-wide inbound flow control tlsState *tls.ConnectionState // shared by all handlers, like net/http remoteAddrStr string @@ -441,6 +440,9 @@ type serverConn struct { sawFirstSettings bool // got the initial SETTINGS frame after the preface needToSendSettingsAck bool unackedSettings int // how many SETTINGS have we sent without ACKs? + pendingEncoderTableSize bool // peer changed SETTINGS_HEADER_TABLE_SIZE; apply to hpackEncoder before the next frame write + encoderTableSizeMin uint32 // smallest SETTINGS_HEADER_TABLE_SIZE since the last apply + encoderTableSize uint32 // latest SETTINGS_HEADER_TABLE_SIZE queuedControlFrames int // control frames in the writeSched queue clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit) advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client @@ -451,7 +453,6 @@ type serverConn struct { maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes streams map[uint32]*stream unstartedHandlers []unstartedHandler - initialStreamSendWindowSize int32 initialStreamRecvWindowSize int32 maxFrameSize int32 peerMaxHeaderListSize uint32 // zero means unknown (default) @@ -521,7 +522,8 @@ type stream struct { // immutable: sc *serverConn id uint32 - body *pipe // non-nil if expecting DATA frames + body *pipe // non-nil if expecting DATA frames + reqBody *requestBody cw closeWaiter // closed wait stream transitions to closed state ctx context.Context cancelCtx func() @@ -1172,6 +1174,16 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) { sc.writingFrame = true sc.needsFrameFlush = true + if sc.pendingEncoderTableSize { + // hpackEncoder may be in use by writeFrameAsync, so SETTINGS + // changes to it are deferred until no frame is being written. + // Replaying the smallest size before the latest one keeps the + // encoder's view identical to having applied every change + // (RFC 7541, Section 4.2). + sc.pendingEncoderTableSize = false + sc.hpackEncoder.SetMaxDynamicTableSize(sc.encoderTableSizeMin) + sc.hpackEncoder.SetMaxDynamicTableSize(sc.encoderTableSize) + } if wr.write.staysWithinBuffer(sc.bw.Available()) { sc.writingFrameAsync = false err := wr.write.writeFrame(sc) @@ -1271,6 +1283,11 @@ func (sc *serverConn) scheduleFrameWrite() { } sc.inFrameScheduleLoop = true for !sc.writingFrameAsync { + if sc.flow.flowErr && (!sc.inGoAway || sc.goAwayCode == ErrCodeNo) { + sc.inGoAway = true + sc.needToSendGoAway = true + sc.goAwayCode = ErrCodeFlowControl + } if sc.needToSendGoAway { sc.needToSendGoAway = false sc.startFrameWrite(FrameWriteRequest{ @@ -1294,6 +1311,9 @@ func (sc *serverConn) scheduleFrameWrite() { sc.startFrameWrite(wr) continue } + if sc.flow.flowErr { + continue + } } if sc.needsFrameFlush { sc.startFrameWrite(FrameWriteRequest{write: flushFrameWriter{}}) @@ -1526,6 +1546,10 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error { return nil } if !st.flow.add(int32(f.Increment)) { + if st.flow.conn.flowErr { + // This is a lazily-detected connection-level flow control error. + return sc.countError("bad_flow", ConnectionError(ErrCodeFlowControl)) + } return sc.countError("bad_flow", streamError(f.StreamID, ErrCodeFlowControl)) } default: // connection-level flow control @@ -1584,10 +1608,6 @@ func (sc *serverConn) closeStream(st *stream, err error) { } } if p := st.body; p != nil { - // Return any buffered unread bytes worth of conn-level flow control. - // See golang.org/issue/16481 - sc.sendWindowUpdate(nil, p.Len()) - p.CloseWithError(err) } if e, ok := err.(StreamError); ok { @@ -1641,7 +1661,12 @@ func (sc *serverConn) processSetting(s Setting) error { } switch s.ID { case SettingHeaderTableSize: - sc.hpackEncoder.SetMaxDynamicTableSize(s.Val) + // Applied by startFrameWrite; see comment there. + if !sc.pendingEncoderTableSize || s.Val < sc.encoderTableSizeMin { + sc.encoderTableSizeMin = s.Val + } + sc.encoderTableSize = s.Val + sc.pendingEncoderTableSize = true case SettingEnablePush: sc.pushEnabled = s.Val != 0 case SettingMaxConcurrentStreams: @@ -1672,28 +1697,14 @@ func (sc *serverConn) processSetting(s Setting) error { func (sc *serverConn) processSettingInitialWindowSize(val uint32) error { sc.serveG.check() - // Note: val already validated to be within range by - // processSetting's Valid call. - - // "A SETTINGS frame can alter the initial flow control window - // size for all current streams. When the value of - // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST - // adjust the size of all stream flow control windows that it - // maintains by the difference between the new value and the - // old value." - old := sc.initialStreamSendWindowSize - sc.initialStreamSendWindowSize = int32(val) - growth := int32(val) - old // may be negative - for _, st := range sc.streams { - if !st.flow.add(growth) { - // 6.9.2 Initial Flow Control Window Size - // "An endpoint MUST treat a change to - // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow - // control window to exceed the maximum size as a - // connection error (Section 5.4.1) of type - // FLOW_CONTROL_ERROR." - return sc.countError("setting_win_size", ConnectionError(ErrCodeFlowControl)) - } + if !sc.flow.changeInitialWindowSize(int64(val)) { + // 6.9.2 Initial Flow Control Window Size + // "An endpoint MUST treat a change to + // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow + // control window to exceed the maximum size as a + // connection error (Section 5.4.1) of type + // FLOW_CONTROL_ERROR." + return sc.countError("setting_win_size", ConnectionError(ErrCodeFlowControl)) } return nil } @@ -1966,7 +1977,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error { if st.reqTrailer != nil { st.trailer = make(http.Header) } - st.body = req.Body.(*requestBody).pipe // may be nil + st.body = st.reqBody.pipe // may be nil st.declBodyBytes = req.ContentLength handler := sc.handler.ServeHTTP @@ -1989,7 +2000,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error { st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout) } - return sc.scheduleHandler(id, rw, req, handler) + return sc.scheduleHandler(st, rw, req, handler) } func (sc *serverConn) upgradeRequest(req *http.Request) { @@ -2102,7 +2113,6 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState, priority } st.cw.Init() st.flow.conn = &sc.flow // link to conn-level counter - st.flow.add(sc.initialStreamSendWindowSize) st.inflow.init(sc.initialStreamRecvWindowSize) if sc.hs.WriteTimeout > 0 { st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout) @@ -2184,7 +2194,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res } else { req.ContentLength = -1 } - req.Body.(*requestBody).pipe = &pipe{ + st.reqBody.pipe = &pipe{ b: &dataBuffer{expected: req.ContentLength}, } } @@ -2204,7 +2214,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp httpcommon.Server return nil, nil, sc.countError(res.InvalidReason, streamError(st.id, ErrCodeProtocol)) } - body := &requestBody{ + st.reqBody = &requestBody{ conn: sc, stream: st, needsContinue: res.NeedsContinue, @@ -2220,7 +2230,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp httpcommon.Server ProtoMinor: 0, TLS: tlsState, Host: rp.Authority, - Body: body, + Body: st.reqBody, Trailer: res.Trailer, }).WithContext(st.ctx) rw := sc.newResponseWriter(st, req) @@ -2244,11 +2254,12 @@ type unstartedHandler struct { rw *responseWriter req *http.Request handler func(http.ResponseWriter, *http.Request) + body *pipe } // scheduleHandler starts a handler goroutine, // or schedules one to start as soon as an existing handler finishes. -func (sc *serverConn) scheduleHandler(streamID uint32, rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) error { +func (sc *serverConn) scheduleHandler(st *stream, rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) error { sc.serveG.check() maxHandlers := sc.advMaxStreams if sc.curHandlers < maxHandlers { @@ -2260,10 +2271,11 @@ func (sc *serverConn) scheduleHandler(streamID uint32, rw *responseWriter, req * return sc.countError("too_many_early_resets", ConnectionError(ErrCodeEnhanceYourCalm)) } sc.unstartedHandlers = append(sc.unstartedHandlers, unstartedHandler{ - streamID: streamID, + streamID: st.id, rw: rw, req: req, handler: handler, + body: st.body, }) return nil } @@ -2277,6 +2289,10 @@ func (sc *serverConn) handlerDone() { u := sc.unstartedHandlers[i] if sc.streams[u.streamID] == nil { // This stream was reset before its goroutine had a chance to start. + if u.body != nil { + u.body.BreakWithError(errClosedBody) + sc.sendWindowUpdate(nil, u.body.Len()) + } continue } if sc.curHandlers >= maxHandlers { @@ -2298,6 +2314,12 @@ func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler didPanic := true defer func() { rw.rws.stream.cancelCtx() + if b := rw.rws.stream.reqBody; b != nil { + // Closing the body refunds flow control credit for any unconsumed data. + // (reqBody is nil for Upgrade: h2c requests, but those do not use flow + // control for the request body.) + b.Close() + } if req.MultipartForm != nil { req.MultipartForm.RemoveAll() } @@ -2396,7 +2418,7 @@ func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) { func (sc *serverConn) noteBodyRead(st *stream, n int) { sc.serveG.check() sc.sendWindowUpdate(nil, n) // conn-level - if st.state != stateHalfClosedRemote && st.state != stateClosed { + if st != nil && st.state != stateHalfClosedRemote && st.state != stateClosed { // Don't send this WINDOW_UPDATE if the stream is closed // remotely. sc.sendWindowUpdate(st, n) @@ -2444,6 +2466,9 @@ func (b *requestBody) Close() error { b.closeOnce.Do(func() { if b.pipe != nil { b.pipe.BreakWithError(errClosedBody) + if unread := b.pipe.Len(); unread > 0 { + b.conn.noteBodyReadFromHandler(nil, unread, errClosedBody) + } } }) return nil @@ -2461,9 +2486,6 @@ func (b *requestBody) Read(p []byte) (n int, err error) { if err == io.EOF { b.sawEOF = true } - if b.conn == nil { - return - } b.conn.noteBodyReadFromHandler(b.stream, n, err) return } diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index 088eb9bef8..d894c6019c 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -27,6 +27,7 @@ import ( "net/http" "net/http/httptrace" "net/textproto" + "slices" "strconv" "sync" "sync/atomic" @@ -203,7 +204,7 @@ type ClientConn struct { mu sync.Mutex // guards following cond *sync.Cond // hold mu; broadcast on flow/closed changes - flow outflow // our conn-level flow control quota (cs.outflow is per stream) + flow connOutflow // our conn-level flow control quota (cs.outflow is per stream) inflow inflow // peer's conn-level flow control doNotReuse bool // whether conn is marked to not be reused for any future requests closing bool @@ -227,7 +228,6 @@ type ClientConn struct { maxConcurrentStreams uint32 peerMaxHeaderListSize uint64 peerMaxHeaderTableSize uint32 - initialWindowSize uint32 initialStreamRecvWindowSize int32 readIdleTimeout time.Duration pingTimeout time.Duration @@ -472,7 +472,6 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, internalStateHook readerDone: make(chan struct{}), nextStreamID: 1, maxFrameSize: 16 << 10, // spec default - initialWindowSize: 65535, // spec default initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream, maxConcurrentStreams: initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings. strictMaxConcurrentStreams: conf.StrictMaxConcurrentRequests, @@ -497,7 +496,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, internalStateHook } cc.cond = sync.NewCond(&cc.mu) - cc.flow.add(int32(initialWindowSize)) + cc.flow.init() // TODO: adjust this writer size to account for frame size + // MTU + crypto/tls record padding. @@ -876,6 +875,33 @@ func (cc *ClientConn) sendGoAway() error { return nil } +func (cc *ClientConn) goAwayAndClose(code ErrCode) { + cc.mu.Lock() + closed := cc.closed + cc.closing = true + cc.closed = true + cc.mu.Unlock() + if closed { + return + } + if f := cc.fr.countError; f != nil { + f(fmt.Sprintf("conn_close_error_%s", code.stringToken())) + } + done := make(chan struct{}) + go func() { + defer close(done) + cc.wmu.Lock() + cc.fr.WriteGoAway(0, code, nil) + cc.bw.Flush() + cc.wmu.Unlock() + }() + select { + case <-done: + case <-time.After(250 * time.Millisecond): + } + cc.closeForError(fmt.Errorf("http2: closing connection with %v", code)) +} + // closes the client connection immediately. In-flight requests are interrupted. // err is sent to streams. func (cc *ClientConn) closeForError(err error) { @@ -1319,7 +1345,9 @@ func (cs *clientStream) cleanupWriteRequest(err error) { } if err != nil { cs.abortStream(err) // possibly redundant, but harmless - if cs.sentHeaders { + if ce, ok := err.(ConnectionError); ok { + cc.goAwayAndClose(ErrCode(ce)) + } else if cs.sentHeaders { if se, ok := err.(StreamError); ok { if se.Cause != errFromPeer { cc.writeStreamReset(cs.ID, se.Code, false, err) @@ -1648,8 +1676,12 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) return 0, errRequestCanceled default: } - if a := cs.flow.available(); a > 0 { - take := a + avail, ok := cs.flow.available() + if !ok { + return 0, ConnectionError(ErrCodeFlowControl) + } + if avail > 0 { + take := avail if int(take) > maxBytes { take = int32(maxBytes) // can't truncate int; take is int32 @@ -1710,8 +1742,7 @@ type resAndError struct { // requires cc.mu be held. func (cc *ClientConn) addStreamLocked(cs *clientStream) { - cs.flow.add(int32(cc.initialWindowSize)) - cs.flow.setConnFlow(&cc.flow) + cs.flow.conn = &cc.flow cs.inflow.init(cc.initialStreamRecvWindowSize) cs.ID = cc.nextStreamID cc.nextStreamID += 2 @@ -2095,18 +2126,42 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra return nil, nil } + // Delete various headers that might mess up framing for HTTP/1. This is + // not a problem for HTTP/2, but someone might use HTTP/2 transport as a + // reverse proxy which forwards the response to an HTTP/1 client. Our + // HTTP/1 client transport will properly reject improper headers such as + // multiple conflicting Content-Length headers, but other implementations + // might not. + // TODO: just reject such responses? We deleted them for compatibility + // since this was done in a security fix (go.dev/issue/81115). However, + // rejecting them seems entirely reasonable and relatively safe. + + // Connection-specific header fields must not appear in an HTTP/2 message, + // and any message containing them is malformed. RFC 9113, Section 8.2.2. + for _, k := range connHeaders { + delete(res.Header, k) + } res.ContentLength = -1 - if clens := res.Header["Content-Length"]; len(clens) == 1 { - if cl, err := strconv.ParseUint(clens[0], 10, 63); err == nil { - res.ContentLength = int64(cl) + if clens, ok := res.Header["Content-Length"]; ok { + // Repeated Content-Length values may be collapsed into one only if + // they are identical per RFC 9110 Section 8.6. + // No need to trim whitespace, HTTP/2 header values must not have + // extraneous whitespace per RFC 9113 Section 8.2.1. + // Non-canonical headers are already rejected by our framer at this + // point. + conflicting := slices.ContainsFunc(clens[1:], func(clen string) bool { + return clen != clens[0] + }) + cl, err := strconv.ParseUint(clens[0], 10, 63) + if conflicting || err != nil { + delete(res.Header, "Content-Length") } else { - // TODO: care? unlike http/1, it won't mess up our framing, so it's - // more safe smuggling-wise to ignore. + res.Header["Content-Length"] = clens[:1] + res.ContentLength = int64(cl) } - } else if len(clens) > 1 { - // TODO: care? unlike http/1, it won't mess up our framing, so it's - // more safe smuggling-wise to ignore. - } else if f.StreamEnded() && !cs.isHead { + } + + if res.ContentLength < 0 && f.StreamEnded() && !cs.isHead { res.ContentLength = 0 } @@ -2417,6 +2472,10 @@ const ( func (rl *clientConnReadLoop) streamByID(id uint32, headerOrData bool) *clientStream { rl.cc.mu.Lock() defer rl.cc.mu.Unlock() + return rl.streamByIDLocked(id, headerOrData) +} + +func (rl *clientConnReadLoop) streamByIDLocked(id uint32, headerOrData bool) *clientStream { if headerOrData { // Work around an unfortunate gRPC behavior. // See comment on ClientConn.rstStreamPingsBlocked for details. @@ -2499,24 +2558,10 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { case SettingMaxHeaderListSize: cc.peerMaxHeaderListSize = uint64(s.Val) case SettingInitialWindowSize: - // Values above the maximum flow-control - // window size of 2^31-1 MUST be treated as a - // connection error (Section 5.4.1) of type - // FLOW_CONTROL_ERROR. - if s.Val > math.MaxInt32 { + if !cc.flow.changeInitialWindowSize(int64(s.Val)) { return ConnectionError(ErrCodeFlowControl) } - - // Adjust flow control of currently-open - // frames by the difference of the old initial - // window size and this one. - delta := int32(s.Val) - int32(cc.initialWindowSize) - for _, cs := range cc.streams { - cs.flow.add(delta) - } cc.cond.Broadcast() - - cc.initialWindowSize = s.Val case SettingHeaderTableSize: cc.henc.SetMaxDynamicTableSize(s.Val) cc.peerMaxHeaderTableSize = s.Val @@ -2558,29 +2603,30 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error { cc := rl.cc - cs := rl.streamByID(f.StreamID, notHeaderOrDataFrame) - if f.StreamID != 0 && cs == nil { - return nil - } - cc.mu.Lock() defer cc.mu.Unlock() - - fl := &cc.flow - if cs != nil { - fl = &cs.flow - } - if !fl.add(int32(f.Increment)) { - // For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR - if cs != nil { + if f.StreamID == 0 { + if !cc.flow.add(int32(f.Increment)) { + return ConnectionError(ErrCodeFlowControl) + } + } else { + cs := rl.streamByIDLocked(f.StreamID, notHeaderOrDataFrame) + if cs == nil { + return nil + } + if !cs.flow.add(int32(f.Increment)) { + if cs.flow.conn.flowErr { + // This is a lazily-detected connection-level flow control error. + return ConnectionError(ErrCodeFlowControl) + } + // For stream, the sender sends RST_STREAM with + // an error code of FLOW_CONTROL_ERROR. rl.endStreamErrorLocked(cs, StreamError{ StreamID: f.StreamID, Code: ErrCodeFlowControl, }) return nil } - - return ConnectionError(ErrCodeFlowControl) } cc.cond.Broadcast() return nil diff --git a/vendor/golang.org/x/net/http2/transport_wrap.go b/vendor/golang.org/x/net/http2/transport_wrap.go index 34dfb3cca6..eeaa95f03c 100644 --- a/vendor/golang.org/x/net/http2/transport_wrap.go +++ b/vendor/golang.org/x/net/http2/transport_wrap.go @@ -119,33 +119,27 @@ type http2TransportContextKey struct{} // DialFromContext dials a new connection using the http2.Transport's DialTLS/DialTLSContext. func (t transportConfig) DialFromContext(ctx context.Context, network, address string) (net.Conn, error) { - if ctx.Value(http2TransportContextKey{}) == nil { + dial, _ := ctx.Value(http2TransportContextKey{}).(*transportRoundTripState) + if dial == nil { // We're being called from a RoundTrip that did not start with an http2.Transport. // Use the http.Transport's dialer. return nil, errors.ErrUnsupported } - - tlsConf := t.t.TLSClientConfig - if tlsConf == nil { - tlsConf = &tls.Config{} - } else { - tlsConf = tlsConf.Clone() - } - if !slices.Contains(tlsConf.NextProtos, "h2") { - tlsConf.NextProtos = append([]string{"h2"}, tlsConf.NextProtos...) - } - if tlsConf.ServerName == "" { - host, _, err := net.SplitHostPort(address) - if err == nil { - tlsConf.ServerName = host - } - } - return t.t.dialTLS(ctx, network, address, tlsConf) + return t.t.dialForRoundTrip(ctx, dial, network, address) } type transportInternal struct { initOnce sync.Once lazyt1 *http.Transport + + dialMu sync.Mutex + dials map[string]*transportDialState +} + +type transportDialState struct { + dialc chan struct{} // close when dial returns + dialErr error // dial result, set before dialc is closed + rtdonec chan struct{} // closed when RoundTrip initiating the dial returns } func (t *Transport) init() *http.Transport { @@ -167,6 +161,52 @@ func (t *Transport) configure(t1 *http.Transport) { } } +// transportRoundTripState is the state of the dial for an http2.Transport.RoundTrip. +type transportRoundTripState struct { + mu sync.Mutex + rtdone bool // set when RoundTrip returns + rtdonec chan struct{} // closed when RoundTrip returns + gotconnc chan struct{} // closed when GotConn hook is called +} + +// startDial is called when a dial starts. +// +// It returns done=true if the RoundTrip has already returned, +// in which case we should skip dialing. +func (dial *transportRoundTripState) startDial() (gotconnc chan struct{}, done bool) { + dial.mu.Lock() + defer dial.mu.Unlock() + if dial.rtdone { + return nil, true + } + if dial.rtdonec == nil { + dial.rtdonec = make(chan struct{}) + } + dial.gotconnc = make(chan struct{}) + return dial.gotconnc, false +} + +// gotConn is called when RoundTrip gets a connection. +// This may happen multiple times per RoundTrip, if a request is retried. +func (dial *transportRoundTripState) gotConn() { + dial.mu.Lock() + defer dial.mu.Unlock() + if dial.gotconnc != nil { + close(dial.gotconnc) + dial.gotconnc = nil + } +} + +// roundTripDone is called when RoundTrip returns. +func (dial *transportRoundTripState) roundTripDone() { + dial.mu.Lock() + defer dial.mu.Unlock() + dial.rtdone = true + if dial.rtdonec != nil { + close(dial.rtdonec) + } +} + func (t *Transport) roundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) { t1 := t.init() @@ -186,12 +226,146 @@ func (t *Transport) roundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res // Both http.Transport and http2.Transport allow the user to provide a custom // dial function, and historically you only get the dial function from the // Transport you're calling RoundTrip on. - ctx := context.WithValue(req.Context(), http2TransportContextKey{}, t) + // + // In addition, http2.Transport coalesces dials, which http.Transport historically + // has not. + dial := &transportRoundTripState{} + defer dial.roundTripDone() + ctx := context.WithValue(req.Context(), http2TransportContextKey{}, dial) + ctx = httptrace.WithClientTrace(ctx, &httptrace.ClientTrace{ + GotConn: func(httptrace.GotConnInfo) { + // Tell dialForRoundTrip that we have received a connection. + dial.gotConn() + }, + }) req = req.WithContext(ctx) - return t1.RoundTrip(req) } +var errCoalescedDialAbandoned = errors.New("http2: abandoned coalesced dial") + +const coalescedDialRetryTimeout = 50 * time.Millisecond + +// dialForRoundTrip is called (indirectly) by net/http when dialing a new connection +// for a request call which originated as an http2.Transport.RoundTrip call. +// +// It uses the http2.Transport's Dial hooks and coalesces dials. +func (t *Transport) dialForRoundTrip(ctx context.Context, dial *transportRoundTripState, network, address string) (net.Conn, error) { + gotconnc, rtdone := dial.startDial() + if rtdone { + // RoundTrip returned, no need for this dial to proceed. + return nil, errCoalescedDialAbandoned + } + + var state *transportDialState + for { + // The first dial to an address registers itself with t.dials. + // When the dial finishes, it records the outcome and removes itself from t.dials + // so future dials will start a new round of coalescing. + // + // Subsequent dials observe that a dial is in progress, and skip dialing. + t.dialMu.Lock() + if t.dials == nil { + t.dials = make(map[string]*transportDialState) + } + leader := t.dials[address] + if leader == nil { + // No entry in t.dials to coalesce with. Add ourselves as leader. + state = &transportDialState{ + dialc: make(chan struct{}), + rtdonec: dial.rtdonec, + } + t.dials[address] = state + } + t.dialMu.Unlock() + if leader == nil { + // We are the leader, so we should dial for real. + break + } + + // Coalesce with a previous dial. + var ( + done = false + leaderdialc = leader.dialc + leaderrtdonec = leader.rtdonec + timerc <-chan time.Time + ) + for !done { + if leaderdialc == nil && leaderrtdonec == nil && timerc == nil { + // The leader finished dialing, and its RoundTrip finished. + // + // There are several possibilities, which reduce to: + // - The RoundTrip we are dialing for is about to receive + // a connection (possibly the one the leader just dialed), + // but we haven't observed it yet. + // - There's something wrong with the leader's connection, + // such as a TLS handshake failure. + // + // We have no good way to distinguish between these cases. + // + // Wait a short time for the leader's connection (or some + // other usable connection) to be delivered to our RoundTrip. + // If it is not, start a dial of our own. + timerc = time.After(coalescedDialRetryTimeout) + } + select { + case <-leaderdialc: + // The leader's dial completed. + if leader.dialErr != nil { + return nil, leader.dialErr + } + leaderdialc = nil + case <-leaderrtdonec: + // The leader's RoundTrip completed. + leaderrtdonec = nil + case <-timerc: + // The leader's dial and RoundTrip completed, and some time + // has passed. Assume we're not getting a connection and + // restart the dial process. + done = true + case <-dial.rtdonec: + // Our RoundTrip returned. + return nil, errCoalescedDialAbandoned + case <-gotconnc: + // Our RoundTrip got a connection. + return nil, errCoalescedDialAbandoned + case <-ctx.Done(): + // net/http abandoned the dial. + return nil, ctx.Err() + } + } + } + + // Dial for real. + tlsConf := t.TLSClientConfig + if tlsConf == nil { + tlsConf = &tls.Config{} + } else { + tlsConf = tlsConf.Clone() + } + if !slices.Contains(tlsConf.NextProtos, "h2") { + tlsConf.NextProtos = append([]string{"h2"}, tlsConf.NextProtos...) + } + if tlsConf.ServerName == "" { + host, _, err := net.SplitHostPort(address) + if err == nil { + tlsConf.ServerName = host + } + } + nc, err := t.dialTLS(ctx, network, address, tlsConf) + + // Remove this dial from t.dials, so future dial attempts will not coalesce with it. + t.dialMu.Lock() + delete(t.dials, address) + t.dialMu.Unlock() + + // Notify any dial coalesced with this one that we are done. + state.dialErr = err + close(state.dialc) + + return nc, err +} + func (t *Transport) closeIdleConnections() { t1 := t.init() t1.CloseIdleConnections() diff --git a/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go index 36ad5e32b4..f1903a8c66 100644 --- a/vendor/golang.org/x/net/http2/writesched.go +++ b/vendor/golang.org/x/net/http2/writesched.go @@ -79,10 +79,11 @@ func (wr FrameWriteRequest) Consume(n int32) (FrameWriteRequest, FrameWriteReque } // Might need to split after applying limits. - allowed := wr.stream.flow.available() - if n < allowed { - allowed = n + avail, ok := wr.stream.flow.available() + if !ok { + return empty, empty, 0 } + allowed := min(n, avail) if wr.stream.sc.maxFrameSize < allowed { allowed = wr.stream.sc.maxFrameSize } diff --git a/vendor/golang.org/x/net/internal/httpcommon/gzip.go b/vendor/golang.org/x/net/internal/httpcommon/gzip.go new file mode 100644 index 0000000000..819dd650cb --- /dev/null +++ b/vendor/golang.org/x/net/internal/httpcommon/gzip.go @@ -0,0 +1,132 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package httpcommon + +import ( + "compress/flate" + "compress/gzip" + "errors" + "io" + "io/fs" + "sync" +) + +var errConcurrentRead = errors.New("http: concurrent read on response body") + +// incomparable is a zero-width, non-comparable type. Adding it to a struct +// makes that struct also non-comparable, and generally doesn't add +// any size (as long as it's first). +type incomparable [0]func() + +// GzipReader wraps a response body so it can lazily +// get gzip.Reader from the pool on the first call to Read. +// After Close is called it puts gzip.Reader to the pool immediately +// if there is no Read in progress or later when Read completes. +type GzipReader struct { + _ incomparable + Body io.ReadCloser // underlying Response.Body + mu sync.Mutex // guards zr and zerr + zr *gzip.Reader // stores gzip reader from the pool between reads + zerr error // sticky gzip reader init error or sentinel value to detect concurrent read and read after close +} + +type eofReader struct{} + +func (eofReader) Read([]byte) (int, error) { return 0, io.EOF } +func (eofReader) ReadByte() (byte, error) { return 0, io.EOF } + +var gzipPool = sync.Pool{New: func() any { return new(gzip.Reader) }} + +// gzipPoolGet gets a gzip.Reader from the pool and resets it to read from r. +func gzipPoolGet(r io.Reader) (*gzip.Reader, error) { + zr := gzipPool.Get().(*gzip.Reader) + if err := zr.Reset(r); err != nil { + gzipPoolPut(zr) + return nil, err + } + return zr, nil +} + +// gzipPoolPut puts a gzip.Reader back into the pool. +func gzipPoolPut(zr *gzip.Reader) { + // Reset will allocate bufio.Reader if we pass it anything + // other than a flate.Reader, so ensure that it's getting one. + var r flate.Reader = eofReader{} + zr.Reset(r) + gzipPool.Put(zr) +} + +// acquire returns a gzip.Reader for reading response body. +// The reader must be released after use. +func (gz *GzipReader) acquire() (*gzip.Reader, error) { + gz.mu.Lock() + defer gz.mu.Unlock() + if gz.zerr != nil { + return nil, gz.zerr + } + if gz.zr == nil { + // gzipPoolGet might block indefinitely since it reads the gzip header. + // Therefore, drop mu temporarily when using gzipPoolGet. + // We set zerr to errConcurrentRead to prevent concurrent read + // even when mu is temporarily dropped. + gz.zerr = errConcurrentRead + gz.mu.Unlock() + zr, err := gzipPoolGet(gz.Body) + gz.mu.Lock() + // Guard against Close being called while gzipPoolGet is running. + if gz.zerr != errConcurrentRead { + if zr != nil { + gzipPoolPut(zr) + } + return nil, gz.zerr + } + gz.zr, gz.zerr = zr, err + if gz.zerr != nil { + return nil, gz.zerr + } + } + ret := gz.zr + gz.zr, gz.zerr = nil, errConcurrentRead + return ret, nil +} + +// release returns the gzip.Reader to the pool if Close was called during Read. +func (gz *GzipReader) release(zr *gzip.Reader) { + gz.mu.Lock() + defer gz.mu.Unlock() + if gz.zerr == errConcurrentRead { + gz.zr, gz.zerr = zr, nil + } else { // fs.ErrClosed + gzipPoolPut(zr) + } +} + +// close returns the gzip.Reader to the pool immediately or +// signals release to do so after Read completes. +func (gz *GzipReader) close() { + gz.mu.Lock() + defer gz.mu.Unlock() + if gz.zerr == nil && gz.zr != nil { + gzipPoolPut(gz.zr) + gz.zr = nil + } + gz.zerr = fs.ErrClosed +} + +func (gz *GzipReader) Read(p []byte) (n int, err error) { + zr, err := gz.acquire() + if err != nil { + return 0, err + } + defer gz.release(zr) + + return zr.Read(p) +} + +func (gz *GzipReader) Close() error { + gz.close() + + return gz.Body.Close() +} diff --git a/vendor/modules.txt b/vendor/modules.txt index dc910389f0..f23979c860 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -397,7 +397,7 @@ golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile golang.org/x/mod/module golang.org/x/mod/semver -# golang.org/x/net v0.59.0 +# golang.org/x/net v0.60.0 ## explicit; go 1.26.0 golang.org/x/net/http/httpguts golang.org/x/net/http2 From e63e4fe49873bdc7f1d39ce553a47f49b059efba Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 8 Oct 2026 21:51:14 +0200 Subject: [PATCH 24/26] vendor: github.com/mattn/go-runewidth v0.0.31 - Treat the remaining invisible format controls as zero width - Treat bidi isolates and other invisible format characters as zero width - Measure ambiguous Latin letters as one cell in East Asian locales - Fix width mismatches found by the Hegel property tests - Recognise CJK locales regardless of charset spelling full diff: https://github.com/mattn/go-runewidth/compare/v0.0.30...v0.0.31 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 4 +- .../github.com/mattn/go-runewidth/README.md | 5 + .../mattn/go-runewidth/runewidth.go | 122 ++++++++++++++---- .../mattn/go-runewidth/runewidth_posix.go | 43 ++++-- .../mattn/go-runewidth/runewidth_table.go | 110 ++++++++-------- vendor/modules.txt | 2 +- 7 files changed, 202 insertions(+), 86 deletions(-) diff --git a/vendor.mod b/vendor.mod index b4ea9125c1..368febf73d 100644 --- a/vendor.mod +++ b/vendor.mod @@ -31,7 +31,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/uuid v1.6.0 - github.com/mattn/go-runewidth v0.0.30 + github.com/mattn/go-runewidth v0.0.31 github.com/moby/go-archive v0.3.3 github.com/moby/moby/api v1.56.1 github.com/moby/moby/client v0.6.1 diff --git a/vendor.sum b/vendor.sum index c43a1e36ad..d66a534392 100644 --- a/vendor.sum +++ b/vendor.sum @@ -82,8 +82,8 @@ github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLM github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mattn/go-runewidth v0.0.30 h1:+KUuiDA4fF0R1p5FeueHefjDm+GIM+kWfFnDjybOPgk= -github.com/mattn/go-runewidth v0.0.30/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8= +github.com/mattn/go-runewidth v0.0.31 h1:1oCV4ReTlosDBc6rYRw5cL8S/4y8iv5oRl4SJ5IBgwo= +github.com/mattn/go-runewidth v0.0.31/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.3.3 h1:OxxR9paxsluYi+zDUEXTTaIxtkK3viymW+Ka7vRhhME= diff --git a/vendor/github.com/mattn/go-runewidth/README.md b/vendor/github.com/mattn/go-runewidth/README.md index 5e2cfd98cb..ecbaed99ca 100644 --- a/vendor/github.com/mattn/go-runewidth/README.md +++ b/vendor/github.com/mattn/go-runewidth/README.md @@ -15,6 +15,11 @@ Usage runewidth.StringWidth("つのだ☆HIRO") == 12 ``` +NOTE: Latin letters that Unicode gives ambiguous East Asian width, such as +`ü`, `é` and `ß`, are measured as one cell even when `EastAsianWidth` is +set, as terminals draw them in CJK locales too. Other ambiguous characters +such as `±`, `×` and `○` still take two cells there. + Author ------ diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go index c2e0946556..95d9ba548f 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -361,9 +361,11 @@ var private = table{ var nonprint = table{ {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, - {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, - {0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, - {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, + {0x061C, 0x061C}, {0x070F, 0x070F}, {0x180B, 0x180E}, + {0x200B, 0x200F}, {0x2028, 0x202E}, {0x2060, 0x2064}, + {0x2066, 0x206F}, {0xD800, 0xDFFF}, {0xFEFF, 0xFEFF}, + {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, {0x13430, 0x1343F}, + {0x1BCA0, 0x1BCA3}, {0x1D173, 0x1D17A}, {0xE0001, 0xE0001}, } // Condition have flag EastAsianWidth whether the current locale is CJK or not. @@ -514,19 +516,77 @@ func isJoiner(r rune) bool { return inTable(r, joiner) } +// clusterText returns s to segment in place of s. When s ends in a lead +// byte short of the bytes it promises, the segmenter gives up there and +// glues everything from it onto the cluster before, where the two-cell cap +// hides it, although the same bytes followed by anything else form +// clusters of their own. Such a string gets NULs after it, enough for any +// lead byte to be decoded; as controls they are clusters of their own, and +// the loops over the clusters stop at len(s) before reaching them. +func clusterText(s string) string { + if endsShort(s) { + return s + "\x00\x00\x00" + } + return s +} + +// endsShort reports whether one of the last three bytes of s is a lead +// byte that needs more bytes than are left, which is where the segmenter +// stops decoding. It only looks at the length the lead byte announces, not +// at whether the bytes after it could continue it, as the segmenter does. +func endsShort(s string) bool { + for i := max(len(s)-3, 0); i < len(s); i++ { + b, left := s[i], len(s)-i + if b >= 0xC2 && b < 0xE0 && left < 2 || + b >= 0xE0 && b < 0xF0 && left < 3 || + b >= 0xF0 && b < 0xF8 && left < 4 { + return true + } + } + return false +} + // graphemeWidth returns the width of a single grapheme cluster: the sum of -// the widths of its runes, capped at 2 cells. The cap keeps multi-rune -// sequences that render as a single glyph (ZWJ emoji, flags, Hangul jamo) -// from being counted wider than the two cells terminals give them. +// the widths of its runes, with the part from the first rune that starts a +// single glyph (an emoji, a regional indicator, a Hangul jamo or syllable) +// capped at 2 cells. The cap keeps multi-rune sequences that render as one +// glyph (ZWJ emoji, skin tones, flags, Hangul jamo) from being counted +// wider than the two cells terminals give them. What comes before it, such +// as a Prepend rune, and a cluster with no such rune, like a letter with a +// skin tone modifier after it, are shown rune by rune and summed. func (c *Condition) graphemeWidth(cluster string) int { - width := 0 + if r, size := utf8.DecodeRuneInString(cluster); size == len(cluster) { + return c.RuneWidth(r) // one rune, never over the cap + } + width, glyph := 0, -1 for _, r := range cluster { - width += c.RuneWidth(r) + w := c.RuneWidth(r) + if glyph < 0 && r >= 0x1100 && startsGlyph(r) { + glyph = 0 + } + if glyph >= 0 { + glyph += w + } else { + width += w + } } - if width > 2 { - width = 2 + return width + min(max(glyph, 0), 2) +} + +// startsGlyph reports whether r begins a sequence that a terminal draws as +// a single glyph however many runes it has. +func startsGlyph(r rune) bool { + switch { + case 0x1100 <= r && r <= 0x11FF, // Hangul jamo + 0xA960 <= r && r <= 0xA97F, // Hangul jamo extended-A + 0xAC00 <= r && r <= 0xD7FF, // Hangul syllables, jamo extended-B + 0x1F1E6 <= r && r <= 0x1F1FF: // regional indicators + return true + case r < 0x203C, 0x3299 < r && r < 0x1F004: + // Outside the emoji table: spares CJK text the search. + return false } - return width + return inTable(r, emoji) } // StringWidth return width as you can see @@ -536,6 +596,11 @@ func (c *Condition) StringWidth(s string) (width int) { if b < 0x20 || b == 0x7F { return 0 } + if b >= 0x80 { + // Not UTF-8 on its own: measure it as the U+FFFD every other + // path decodes it to, which is ambiguous width. + return c.RuneWidth(utf8.RuneError) + } return 1 } if len(s) > 0 && len(s) <= utf8.UTFMax { @@ -565,8 +630,8 @@ graphemes: return } width = 0 - g := graphemes.FromString(s) - for g.Next() { + g := graphemes.FromString(clusterText(s)) + for g.Next() && g.Start() < len(s) { width += c.graphemeWidth(g.Value()) } return @@ -597,8 +662,8 @@ func (c *Condition) Truncate(s string, w int, tail string) string { } var width int pos := len(s) - g := graphemes.FromString(s) - for g.Next() { + g := graphemes.FromString(clusterText(s)) + for g.Next() && g.Start() < len(s) { chWidth := c.graphemeWidth(g.Value()) if width+chWidth > w { pos = g.Start() @@ -651,8 +716,8 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string { var width int pos := len(s) - g := graphemes.FromString(s) - for g.Next() { + g := graphemes.FromString(clusterText(s)) + for g.Next() && g.Start() < len(s) { chWidth := c.graphemeWidth(g.Value()) if width+chWidth > w { @@ -714,8 +779,8 @@ func (c *Condition) TruncatePrefix(s string, w int, prefix string) string { } var width int var pos int - g := graphemes.FromString(s) - for g.Next() { + g := graphemes.FromString(clusterText(s)) + for g.Next() && g.Start() < len(s) { chWidth := c.graphemeWidth(g.Value()) if sw-(width+chWidth) <= w { pos = g.End() @@ -791,6 +856,14 @@ func (c *Condition) Wrap(s string, w int) string { width = 0 continue } + // CRLF is one cluster that ends the line, as on the + // segmenter, so it is never broken before. + if b == '\r' && i+1 < len(s) && s[i+1] == '\n' { + out.WriteString("\r\n") + width = 0 + i++ + continue + } // Same rule as the StringWidth fast path: no ASCII byte is // wide or ambiguous, so the flags in c cannot change this. cw := 0 @@ -815,8 +888,8 @@ func (c *Condition) Wrap(s string, w int) string { width := 0 var out strings.Builder out.Grow(len(s) + len(s)/max(w, 1) + 1) - g := graphemes.FromString(s) - for g.Next() { + g := graphemes.FromString(clusterText(s)) + for g.Next() && g.Start() < len(s) { cluster := g.Value() // LF and CRLF are each a single cluster if strings.HasSuffix(cluster, "\n") { @@ -862,8 +935,13 @@ func RuneWidth(r rune) int { } // IsAmbiguousWidth returns whether is ambiguous width or not. +// +// NOTE: The Latin letters of U+0080..U+017F that Unicode gives ambiguous +// width (ü, é, ß, æ, ø and so on) are reported as ambiguous here, but +// RuneWidth measures them as one cell even with EastAsianWidth, since +// terminals draw them narrow in CJK locales too. func IsAmbiguousWidth(r rune) bool { - return inTable(r, private) || inTable(r, ambiguous) + return inTable(r, private) || inTable(r, ambiguous) || inTable(r, ambiguousLatin) } // IsCombiningWidth returns whether is combining width or not. diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go index 16673af3a1..302c3d0c6e 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go @@ -14,9 +14,11 @@ func mblen(charset string) int { return 6 case "jis": return 8 + case "euctw", "gb18030": + return 4 case "eucjp": return 3 - case "euckr", "euccn", "sjis", "cp932", "cp51932", "cp936", "cp949", "cp950", "big5", "gbk", "gb2312": + case "euckr", "euccn", "sjis", "shiftjis", "cp932", "cp51932", "cp936", "cp949", "cp950", "big5", "big5hkscs", "gbk", "gb2312": return 2 } return 1 @@ -45,9 +47,35 @@ func localeCharset(locale string) string { return "" } +// isCJKLanguage reports whether the language code at the start of locale is +// Japanese, Korean or Chinese. +func isCJKLanguage(locale string) bool { + n := 0 + for n < len(locale) && locale[n] >= 'a' && locale[n] <= 'z' { + n++ + } + switch locale[:n] { + case "ja", "ko", "zh": + return true + } + return false +} + +// normalizeCharset drops the hyphens and underscores that charset names are +// spelled with or without, so that "EUC-JP" and "eucjp" compare equal. +func normalizeCharset(charset string) string { + return strings.Map(func(r rune) rune { + if r == '-' || r == '_' { + return -1 + } + return r + }, charset) +} + func isEastAsian(locale string) bool { charset := strings.ToLower(locale) - if cs := localeCharset(locale); cs != "" { + cs := localeCharset(locale) + if cs != "" { charset = strings.ToLower(cs) } @@ -61,14 +89,13 @@ func isEastAsian(locale string) bool { break } } - max := mblen(charset) - if max > 1 && (charset[0] != 'u' || - strings.HasPrefix(locale, "ja") || - strings.HasPrefix(locale, "ko") || - strings.HasPrefix(locale, "zh")) { + cjk := isCJKLanguage(locale) + if cs == "" && cjk { + // A CJK locale without a charset, such as "ja_JP" on macOS. return true } - return false + max := mblen(normalizeCharset(charset)) + return max > 1 && (charset[0] != 'u' || cjk) } // IsEastAsian return true if the current locale is CJK diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_table.go b/vendor/github.com/mattn/go-runewidth/runewidth_table.go index be9618dd36..81bc90752c 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_table.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_table.go @@ -173,65 +173,71 @@ var doublewidth = table{ var ambiguous = table{ {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, - {0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4}, - {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, - {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, + {0x00AD, 0x00AE}, {0x00B0, 0x00B4}, {0x00B6, 0x00B9}, + {0x00BC, 0x00BF}, {0x00D7, 0x00D7}, {0x00F7, 0x00F7}, + {0x01CE, 0x01CE}, {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, + {0x01D4, 0x01D4}, {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, + {0x01DA, 0x01DA}, {0x01DC, 0x01DC}, {0x0251, 0x0251}, + {0x0261, 0x0261}, {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, + {0x02C9, 0x02CB}, {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, + {0x02D8, 0x02DB}, {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, + {0x0300, 0x036F}, {0x0391, 0x03A1}, {0x03A3, 0x03A9}, + {0x03B1, 0x03C1}, {0x03C3, 0x03C9}, {0x0401, 0x0401}, + {0x0410, 0x044F}, {0x0451, 0x0451}, {0x2010, 0x2010}, + {0x2013, 0x2016}, {0x2018, 0x2019}, {0x201C, 0x201D}, + {0x2020, 0x2022}, {0x2024, 0x2027}, {0x2030, 0x2030}, + {0x2032, 0x2033}, {0x2035, 0x2035}, {0x203B, 0x203B}, + {0x203E, 0x203E}, {0x2074, 0x2074}, {0x207F, 0x207F}, + {0x2081, 0x2084}, {0x20AC, 0x20AC}, {0x2103, 0x2103}, + {0x2105, 0x2105}, {0x2109, 0x2109}, {0x2113, 0x2113}, + {0x2116, 0x2116}, {0x2121, 0x2122}, {0x2126, 0x2126}, + {0x212B, 0x212B}, {0x2153, 0x2154}, {0x215B, 0x215E}, + {0x2160, 0x216B}, {0x2170, 0x2179}, {0x2189, 0x2189}, + {0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, + {0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200}, + {0x2202, 0x2203}, {0x2207, 0x2208}, {0x220B, 0x220B}, + {0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215}, + {0x221A, 0x221A}, {0x221D, 0x2220}, {0x2223, 0x2223}, + {0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E}, + {0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248}, + {0x224C, 0x224C}, {0x2252, 0x2252}, {0x2260, 0x2261}, + {0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F}, + {0x2282, 0x2283}, {0x2286, 0x2287}, {0x2295, 0x2295}, + {0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, + {0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B}, + {0x2550, 0x2573}, {0x2580, 0x258F}, {0x2592, 0x2595}, + {0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, + {0x25B6, 0x25B7}, {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, + {0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, + {0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606}, + {0x2609, 0x2609}, {0x260E, 0x260F}, {0x261C, 0x261C}, + {0x261E, 0x261E}, {0x2640, 0x2640}, {0x2642, 0x2642}, + {0x2660, 0x2661}, {0x2663, 0x2665}, {0x2667, 0x266A}, + {0x266C, 0x266D}, {0x266F, 0x266F}, {0x269E, 0x269F}, + {0x26BF, 0x26BF}, {0x26C6, 0x26CD}, {0x26CF, 0x26D3}, + {0x26D5, 0x26E1}, {0x26E3, 0x26E3}, {0x26E8, 0x26E9}, + {0x26EB, 0x26F1}, {0x26F4, 0x26F4}, {0x26F6, 0x26F9}, + {0x26FB, 0x26FC}, {0x26FE, 0x26FF}, {0x273D, 0x273D}, + {0x2776, 0x277F}, {0x2B56, 0x2B59}, {0x3248, 0x324F}, + {0xE000, 0xF8FF}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, + {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, + {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xF0000, 0xFFFFD}, + {0x100000, 0x10FFFD}, +} + +var ambiguousLatin = table{ + {0x00AA, 0x00AA}, {0x00BA, 0x00BA}, {0x00C6, 0x00C6}, + {0x00D0, 0x00D0}, {0x00D8, 0x00D8}, {0x00DE, 0x00E1}, {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, - {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, + {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F8, 0x00FA}, {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101}, {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, - {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE}, - {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, - {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, - {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, - {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, - {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, - {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F}, - {0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, - {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F}, - {0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016}, - {0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022}, - {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, - {0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E}, - {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, - {0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105}, - {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, - {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B}, - {0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B}, - {0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199}, - {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4}, - {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, - {0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F}, - {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A}, - {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, - {0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237}, - {0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C}, - {0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267}, - {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283}, - {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, - {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312}, - {0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573}, - {0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1}, - {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, - {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, - {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5}, - {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609}, - {0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E}, - {0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661}, - {0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D}, - {0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF}, - {0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1}, - {0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1}, - {0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC}, - {0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F}, - {0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF}, - {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, {0x1F110, 0x1F12D}, - {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, {0x1F18F, 0x1F190}, - {0x1F19B, 0x1F1AC}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}, + {0x0166, 0x0167}, {0x016B, 0x016B}, } + var narrow = table{ {0x0020, 0x007E}, {0x00A2, 0x00A3}, {0x00A5, 0x00A6}, {0x00AC, 0x00AC}, {0x00AF, 0x00AF}, {0x27E6, 0x27ED}, diff --git a/vendor/modules.txt b/vendor/modules.txt index 8b034bc60f..642d6cb061 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -155,7 +155,7 @@ github.com/klauspost/compress/internal/le github.com/klauspost/compress/internal/snapref github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash -# github.com/mattn/go-runewidth v0.0.30 +# github.com/mattn/go-runewidth v0.0.31 ## explicit; go 1.23 github.com/mattn/go-runewidth # github.com/moby/docker-image-spec v1.3.1 From 730c880b35e8e7d7f99b31ff388040748baeaba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 8 Oct 2026 22:08:10 +0200 Subject: [PATCH 25/26] vendor: github.com/moby/moby/client v0.6.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit full diff: https://github.com/moby/moby/compare/client/v0.6.1...client/v0.6.2 Signed-off-by: Paweł Gronowski --- vendor.mod | 2 +- vendor.sum | 4 ++-- vendor/github.com/moby/moby/client/hijack.go | 16 +++++++++++++++- vendor/modules.txt | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/vendor.mod b/vendor.mod index b4ea9125c1..eb3bdf8cf2 100644 --- a/vendor.mod +++ b/vendor.mod @@ -34,7 +34,7 @@ require ( github.com/mattn/go-runewidth v0.0.30 github.com/moby/go-archive v0.3.3 github.com/moby/moby/api v1.56.1 - github.com/moby/moby/client v0.6.1 + github.com/moby/moby/client v0.6.2 github.com/moby/patternmatcher v0.6.1 github.com/moby/swarmkit/v2 v2.1.2 github.com/moby/sys/atomicwriter v0.1.0 diff --git a/vendor.sum b/vendor.sum index c43a1e36ad..3a3d7db825 100644 --- a/vendor.sum +++ b/vendor.sum @@ -90,8 +90,8 @@ github.com/moby/go-archive v0.3.3 h1:OxxR9paxsluYi+zDUEXTTaIxtkK3viymW+Ka7vRhhME github.com/moby/go-archive v0.3.3/go.mod h1:Npdv43fFqlhZW7Xo8fbm3ZMYFvAGNviUPqX21VERbcE= github.com/moby/moby/api v1.56.1 h1:PpWkvVPB7Fr/No8w+TfyJ/I6rWZ2YPZhT3JorIg+06c= github.com/moby/moby/api v1.56.1/go.mod h1:sZ+THbVWkjOmBPPfbnzdD/G1LuIexWhqlSHHPTDQ1Uk= -github.com/moby/moby/client v0.6.1 h1:gvfKmdcWw+9MzXYP0vAUKQtBTGu1L8475K2nsmL7O98= -github.com/moby/moby/client v0.6.1/go.mod h1:XHgTFqz9NCgS/VuoxXMmEDVmVgXQ4vFEc15wsCIwb24= +github.com/moby/moby/client v0.6.2 h1:ekSPlMccrZGcw6Scb8T9D39qE0mB+XupU/yS0zNw9N4= +github.com/moby/moby/client v0.6.2/go.mod h1:DGcnO7qmPJrqobx/ggQgQ/AUk+2wgVdQv7uxB0/mEsc= github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U= github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/swarmkit/v2 v2.1.2 h1:1WDZAI6HVYNKdCG4zlXnTAPyLsLwuhRGWlHoOUf5Z6I= diff --git a/vendor/github.com/moby/moby/client/hijack.go b/vendor/github.com/moby/moby/client/hijack.go index fb3a232608..fbb0402725 100644 --- a/vendor/github.com/moby/moby/client/hijack.go +++ b/vendor/github.com/moby/moby/client/hijack.go @@ -42,7 +42,7 @@ func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[s return conn, err } -func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn, _ string, retErr error) { +func (cli *Client) setupHijackConn(req *http.Request, proto string) (retConn net.Conn, mediaType string, retErr error) { ctx := req.Context() req.Header.Set("Connection", "Upgrade") req.Header.Set("Upgrade", proto) @@ -70,6 +70,20 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn, hc := &hijackedConn{conn, bufio.NewReader(conn)} + // Cancel the handshake without tying the returned connection to ctx. + cancelled := make(chan struct{}) + stop := context.AfterFunc(ctx, func() { + _ = hc.Conn.Close() + close(cancelled) + }) + defer func() { + if !stop() { + // Cancellation won the race; don't return a connection being closed. + <-cancelled + retConn, mediaType, retErr = nil, "", ctx.Err() + } + }() + cfg := &cli.clientConfig var rt http.RoundTripper = otelhttp.NewTransport(hc, cli.traceOpts...) diff --git a/vendor/modules.txt b/vendor/modules.txt index 8b034bc60f..876bf0cfa1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -189,7 +189,7 @@ github.com/moby/moby/api/types/storage github.com/moby/moby/api/types/swarm github.com/moby/moby/api/types/system github.com/moby/moby/api/types/volume -# github.com/moby/moby/client v0.6.1 +# github.com/moby/moby/client v0.6.2 ## explicit; go 1.24 github.com/moby/moby/client github.com/moby/moby/client/internal From cf809998ab8c05dd2abb5a8db26da276d18306ee Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 8 Oct 2026 21:58:50 +0200 Subject: [PATCH 26/26] cmd/docker-trust: update dependencies Signed-off-by: Sebastiaan van Stijn --- cmd/docker-trust/go.mod | 20 ++++++++++---------- cmd/docker-trust/go.sum | 41 ++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/cmd/docker-trust/go.mod b/cmd/docker-trust/go.mod index edbd6f2a25..2fecc990ac 100644 --- a/cmd/docker-trust/go.mod +++ b/cmd/docker-trust/go.mod @@ -5,13 +5,13 @@ go 1.26.0 require ( github.com/containerd/errdefs v1.0.0 github.com/distribution/reference v0.6.0 - github.com/docker/cli v29.7.2+incompatible + github.com/docker/cli v29.8.2+incompatible github.com/docker/cli-docs-tool v0.11.0 github.com/docker/distribution v2.8.3+incompatible - github.com/docker/go-connections v0.8.1 + github.com/docker/go-connections v0.8.2 github.com/fvbommel/sortorder v1.2.0 - github.com/moby/moby/api v1.55.0 - github.com/moby/moby/client v0.5.1 + github.com/moby/moby/api v1.56.1 + github.com/moby/moby/client v0.6.2 github.com/opencontainers/go-digest v1.0.0 github.com/sirupsen/logrus v1.10.2 github.com/spf13/cobra v1.10.2 @@ -22,7 +22,7 @@ require ( ) require ( - github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect @@ -66,11 +66,11 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.46.0 // indirect go.opentelemetry.io/otel/trace v1.46.0 // indirect go.opentelemetry.io/proto/otlp v1.11.0 // indirect - golang.org/x/crypto v0.56.0 // indirect - golang.org/x/net v0.58.0 // indirect - golang.org/x/sys v0.47.0 // indirect - golang.org/x/term v0.45.0 // indirect - golang.org/x/text v0.41.0 // indirect + golang.org/x/crypto v0.57.0 // indirect + golang.org/x/net v0.60.0 // indirect + golang.org/x/sys v0.48.0 // indirect + golang.org/x/term v0.46.0 // indirect + golang.org/x/text v0.42.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260825221802-da73d73af1c5 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect google.golang.org/grpc v1.83.2 // indirect diff --git a/cmd/docker-trust/go.sum b/cmd/docker-trust/go.sum index a92361e9a3..c1b0238dae 100644 --- a/cmd/docker-trust/go.sum +++ b/cmd/docker-trust/go.sum @@ -1,5 +1,5 @@ -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 h1:m2xcjRABtG288vnlV3U/PKh/HnPURxZp50RKNUwBxM8= +github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4/go.mod h1:MTUE7ZuZO89FAtAwozGg6AWD83pcdefnEq5gF82MB8s= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -42,8 +42,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v29.7.2+incompatible h1:dlkwallR8XqfeVnA2ELEhdwvb4lsSwuB4IgsG8Q9cLY= -github.com/docker/cli v29.7.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v29.8.2+incompatible h1:2zgdFuoFst2T80oS42vhKGxkd0JRo305eIEKTsxR7pQ= +github.com/docker/cli v29.8.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli-docs-tool v0.11.0 h1:7d8QARFb7QEobizqxmEM7fOteZEHwH/zWgHQtHZEcfE= github.com/docker/cli-docs-tool v0.11.0/go.mod h1:ma8BKiisUo8D6W05XEYIh3oa1UbgrZhi1nowyKFJa8Q= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= @@ -54,8 +54,8 @@ github.com/docker/docker-credential-helpers v0.9.9/go.mod h1:v1S+hepowrQXITkEfw6 github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-connections v0.8.1 h1:JibmG5hULs5qXSr/cp/w3Pw5fZuStt4MOHMUExb29/M= -github.com/docker/go-connections v0.8.1/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= +github.com/docker/go-connections v0.8.2 h1:9d9DEokx5W7qlr0shkFXIxEA7+TTD+llwzcykSlxMNc= +github.com/docker/go-connections v0.8.2/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.1.0 h1:r76KPNpstz+IvQKSWpYegSkkyzex0V3A1ZGVx6bhGlY= github.com/docker/go-metrics v0.1.0/go.mod h1:PciI3sONtB051kXALN1JoIlpcu54E1FuPh+4DuqEzyw= @@ -133,10 +133,10 @@ github.com/mitchellh/mapstructure v1.0.0 h1:vVpGvMXJPqSDh2VYHF7gsfQj8Ncx+Xw5Y1KH github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/moby/api v1.55.0 h1:2/sexvQyqIWS8pRSCFddBfpW2qE7vR7FCL+vN8pxwMc= -github.com/moby/moby/api v1.55.0/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= -github.com/moby/moby/client v0.5.1 h1:tYNaJno4c0HXz12y5BiqEDy0rVTYkWzI26lGvnTMiJw= -github.com/moby/moby/client v0.5.1/go.mod h1:odLstlZ6uSnfvAgVxMpvgmb8SUdd+siH2T0GBuxVAlM= +github.com/moby/moby/api v1.56.1 h1:PpWkvVPB7Fr/No8w+TfyJ/I6rWZ2YPZhT3JorIg+06c= +github.com/moby/moby/api v1.56.1/go.mod h1:sZ+THbVWkjOmBPPfbnzdD/G1LuIexWhqlSHHPTDQ1Uk= +github.com/moby/moby/client v0.6.2 h1:ekSPlMccrZGcw6Scb8T9D39qE0mB+XupU/yS0zNw9N4= +github.com/moby/moby/client v0.6.2/go.mod h1:DGcnO7qmPJrqobx/ggQgQ/AUk+2wgVdQv7uxB0/mEsc= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/sys/sequential v0.7.0 h1:ASQNGNROJSuOO6LL6bPHbKvuZu6NU8P4ldPWk31zj/8= @@ -236,27 +236,26 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= -golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= +golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= +golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= -golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= +golang.org/x/net v0.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU= +golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= -golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= +golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= -golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE= +golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= -golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= +golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=