Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions VERSION
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
go1.26.3
time 2026-05-04T20:36:18Z
go1.26.4
time 2026-05-29T15:26:39Z
3 changes: 2 additions & 1 deletion src/cmd/compile/internal/ssa/_gen/AMD64.rules
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,8 @@
(LEA(Q|L)2 [0] {s} (ADD(Q|L) x x) x) && s == nil => (SHL(Q|L)const [2] x)

// (x + x) << 2 -> x << 3 and similar
(SHL(Q|L)const [c] (ADD(Q|L) x x)) => (SHL(Q|L)const [c+1] x)
(SHLQconst [c] (ADDQ x x)) && c < 63 => (SHLQconst [c+1] x)
(SHLLconst [c] (ADDL x x)) && c < 31 => (SHLLconst [c+1] x)

// reverse ordering of compare instruction
(SETL (InvertFlags x)) => (SETG x)
Expand Down
6 changes: 4 additions & 2 deletions src/cmd/compile/internal/ssa/rewriteAMD64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/cmd/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
golang.org/x/sys v0.39.0
golang.org/x/telemetry v0.0.0-20251128220624-abf20d0e57ec
golang.org/x/term v0.38.0
golang.org/x/tools v0.39.1-0.20260323181443-4f499ecaa91d
golang.org/x/tools v0.39.1-0.20260527181557-0f52e3809b35
)

require (
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/tools v0.39.1-0.20260323181443-4f499ecaa91d h1:d9RYG/Z8xQk+tFy5IyhSwUrt4HhSsqHw/uhwmn1KaJg=
golang.org/x/tools v0.39.1-0.20260323181443-4f499ecaa91d/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
golang.org/x/tools v0.39.1-0.20260527181557-0f52e3809b35 h1:NtO66pjvzVNcFzUfpQKKOKMrSs1SYT4qPtV3xpdv6BE=
golang.org/x/tools v0.39.1-0.20260527181557-0f52e3809b35/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8=
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ=

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/cmd/vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ golang.org/x/text/internal/tag
golang.org/x/text/language
golang.org/x/text/transform
golang.org/x/text/unicode/norm
# golang.org/x/tools v0.39.1-0.20260323181443-4f499ecaa91d
# golang.org/x/tools v0.39.1-0.20260527181557-0f52e3809b35
## explicit; go 1.24.0
golang.org/x/tools/cmd/bisect
golang.org/x/tools/cover
Expand Down
67 changes: 8 additions & 59 deletions src/crypto/internal/fips140/drbg/entropy_fips140.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Entropy generation in FIPS 140-3 mode uses a scratch buffer in the BSS
// section (see below), which usually doesn't cost much, except on Wasm, due to
// the way the linear memory works. FIPS 140-3 mode is not supported on Wasm, so
// we just use a build tag to exclude it. (Could also exclude other platforms
// that does not support FIPS 140-3 mode, but as the BSS variable doesn't cost
// much, don't bother.)
//
//go:build !wasm

// This file contains reading from from entropy sources in FIPS-140
// mode. It uses a scratch buffer in the BSS section (see below),
// which usually doesn't cost much, except on Wasm, due to the way
// the linear memory works. FIPS-140 mode is not supported on Wasm,
// so we just use a build tag to exclude it. (Could also exclude other
// platforms that does not support FIPS-140 mode, but as the BSS
// variable doesn't cost much, don't bother.)

package drbg

import (
entropy "crypto/internal/entropy/v1.0.0"
"crypto/internal/sysrand"
"sync"
"sync/atomic"
)
import entropy "crypto/internal/entropy/v1.0.0"

// memory is a scratch buffer that is accessed between samples by the entropy
// source to expose it to memory access timings.
Expand Down Expand Up @@ -50,48 +44,3 @@ func getEntropy() *[SeedSize]byte {
}
return &seed
}

// getEntropy is very slow (~500µs), so we don't want it on the hot path.
// We keep both a persistent DRBG instance and a pool of additional instances.
// Occasional uses will use drbgInstance, even if the pool was emptied since the
// last use. Frequent concurrent uses will fill the pool and use it.
var drbgInstance atomic.Pointer[Counter]
var drbgPool = sync.Pool{
New: func() any {
return NewCounter(getEntropy())
},
}

func readFromEntropy(b []byte) {
// At every read, 128 random bits from the operating system are mixed as
// additional input, to make the output as strong as non-FIPS randomness.
// This is not credited as entropy for FIPS purposes, as allowed by Section
// 8.7.2: "Note that a DRBG does not rely on additional input to provide
// entropy, even though entropy could be provided in the additional input".
additionalInput := new([SeedSize]byte)
sysrand.Read(additionalInput[:16])

drbg := drbgInstance.Swap(nil)
if drbg == nil {
drbg = drbgPool.Get().(*Counter)
}
defer func() {
if !drbgInstance.CompareAndSwap(nil, drbg) {
drbgPool.Put(drbg)
}
}()

for len(b) > 0 {
size := min(len(b), maxRequestSize)
if reseedRequired := drbg.Generate(b[:size], additionalInput); reseedRequired {
// See SP 800-90A Rev. 1, Section 9.3.1, Steps 6-8, as explained in
// Section 9.3.2: if Generate reports a reseed is required, the
// additional input is passed to Reseed along with the entropy and
// then nulled before the next Generate call.
drbg.Reseed(getEntropy(), additionalInput)
additionalInput = nil
continue
}
b = b[size:]
}
}
4 changes: 2 additions & 2 deletions src/crypto/internal/fips140/drbg/entropy_wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

package drbg

func readFromEntropy(b []byte) {
panic("FIPS-140 entropy generation is not supported on Wasm")
func getEntropy() *[SeedSize]byte {
panic("FIPS 140-3 entropy generation is not supported on Wasm")
}
45 changes: 44 additions & 1 deletion src/crypto/internal/fips140/drbg/rand.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,21 @@ import (
"crypto/internal/fips140"
"crypto/internal/sysrand"
"io"
"sync"
"sync/atomic"
)

// getEntropy is very slow (~500µs), so we don't want it on the hot path.
// We keep both a persistent DRBG instance and a pool of additional instances.
// Occasional uses will use drbgInstance, even if the pool was emptied since the
// last use. Frequent concurrent uses will fill the pool and use it.
var drbgInstance atomic.Pointer[Counter]
var drbgPool = sync.Pool{
New: func() any {
return NewCounter(getEntropy())
},
}

// Read fills b with cryptographically secure random bytes. In FIPS mode, it
// uses an SP 800-90A Rev. 1 Deterministic Random Bit Generator (DRBG).
// Otherwise, it uses the operating system's random number generator.
Expand All @@ -32,7 +45,37 @@ func Read(b []byte) {
return
}

readFromEntropy(b)
// At every read, 128 random bits from the operating system are mixed as
// additional input, to make the output as strong as non-FIPS randomness.
// This is not credited as entropy for FIPS purposes, as allowed by Section
// 8.7.2: "Note that a DRBG does not rely on additional input to provide
// entropy, even though entropy could be provided in the additional input".
additionalInput := new([SeedSize]byte)
sysrand.Read(additionalInput[:16])

drbg := drbgInstance.Swap(nil)
if drbg == nil {
drbg = drbgPool.Get().(*Counter)
}
defer func() {
if !drbgInstance.CompareAndSwap(nil, drbg) {
drbgPool.Put(drbg)
}
}()

for len(b) > 0 {
size := min(len(b), maxRequestSize)
if reseedRequired := drbg.Generate(b[:size], additionalInput); reseedRequired {
// See SP 800-90A Rev. 1, Section 9.3.1, Steps 6-8, as explained in
// Section 9.3.2: if Generate reports a reseed is required, the
// additional input is passed to Reseed along with the entropy and
// then nulled before the next Generate call.
drbg.Reseed(getEntropy(), additionalInput)
additionalInput = nil
continue
}
b = b[size:]
}
}

var testingReader io.Reader
Expand Down
15 changes: 9 additions & 6 deletions src/crypto/x509/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (h HostnameError) Error() string {
c := h.Certificate
maxNamesIncluded := 100

if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, splitHostname(h.Host)) {
return "x509: certificate relies on legacy Common Name field, use SANs instead"
}

Expand Down Expand Up @@ -867,16 +867,14 @@ func matchExactly(hostA, hostB string) bool {
return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB)
}

func matchHostnames(pattern, host string) bool {
func matchHostnames(pattern string, hostParts []string) bool {
pattern = toLowerCaseASCII(pattern)
host = toLowerCaseASCII(strings.TrimSuffix(host, "."))

if len(pattern) == 0 || len(host) == 0 {
if len(pattern) == 0 || len(hostParts) == 0 {
return false
}

patternParts := strings.Split(pattern, ".")
hostParts := strings.Split(host, ".")

if len(patternParts) != len(hostParts) {
return false
Expand Down Expand Up @@ -954,6 +952,7 @@ func (c *Certificate) VerifyHostname(h string) error {

candidateName := toLowerCaseASCII(h) // Save allocations inside the loop.
validCandidateName := validHostnameInput(candidateName)
hostParts := splitHostname(candidateName)

for _, match := range c.DNSNames {
// Ideally, we'd only match valid hostnames according to RFC 6125 like
Expand All @@ -962,7 +961,7 @@ func (c *Certificate) VerifyHostname(h string) error {
// always allow perfect matches, and only apply wildcard and trailing
// dot processing to valid hostnames.
if validCandidateName && validHostnamePattern(match) {
if matchHostnames(match, candidateName) {
if matchHostnames(match, hostParts) {
return nil
}
} else {
Expand All @@ -975,6 +974,10 @@ func (c *Certificate) VerifyHostname(h string) error {
return HostnameError{c, h}
}

func splitHostname(host string) []string {
return strings.Split(toLowerCaseASCII(strings.TrimSuffix(host, ".")), ".")
}

func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
usages := make([]ExtKeyUsage, len(keyUsages))
copy(usages, keyUsages)
Expand Down
4 changes: 2 additions & 2 deletions src/mime/encodedword.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ func (d *WordDecoder) DecodeHeader(header string) (string, error) {
content, err := decode(encoding, text)
if err != nil {
betweenWords = false
buf.WriteString(header[:start+2])
header = header[start+2:]
buf.WriteString(header[:end])
header = header[end:]
continue
}

Expand Down
4 changes: 4 additions & 0 deletions src/mime/encodedword_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ func TestDecodeHeader(t *testing.T) {
{"=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=", "ab"},
{"=?ISO-8859-1?Q?a?= \r\n\t =?ISO-8859-1?Q?b?=", "ab"},
{"=?ISO-8859-1?Q?a_b?=", "a b"},
// Undecodable words
{"=?UTF-8?b?garbage?= =?UTF-8?b?QW5kcsOp?= =?UTF-8?b?garbage?=", "=?UTF-8?b?garbage?= André =?UTF-8?b?garbage?="},
{"=?UTF-8?b?QW5kcsOp", "=?UTF-8?b?QW5kcsOp"},
{"=?UTF-8?x?y?=?UTF-8?x?y=?", "=?UTF-8?x?y?=?UTF-8?x?y=?"},
}

for _, test := range tests {
Expand Down
6 changes: 3 additions & 3 deletions src/net/smtp/smtp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ func TestHello(t *testing.T) {
err = c.Hello("customhost")
case 1:
err = c.StartTLS(nil)
if err.Error() == "502 Not implemented" {
if err.Error() == `502 "Not implemented"` {
err = nil
}
case 2:
Expand Down Expand Up @@ -953,8 +953,8 @@ func TestAuthFailed(t *testing.T) {

if err == nil {
t.Error("Auth: expected error; got none")
} else if err.Error() != "535 Invalid credentials\nplease see www.example.com" {
t.Errorf("Auth: got error: %v, want: %s", err, "535 Invalid credentials\nplease see www.example.com")
} else if err.Error() != `535 "Invalid credentials\nplease see www.example.com"` {
t.Errorf("Auth: got error: %v, want: %s", err, `535 "Invalid credentials\nplease see www.example.com"`)
}

bcmdbuf.Flush()
Expand Down
Loading
Loading