2 Commits

Author SHA1 Message Date
Vorapol Rinsatitnon
25e497e367 Update to go1.23.6 2025-02-08 18:03:41 +07:00
Vorapol Rinsatitnon
716e5b5d05 Update to go1.23.5 2025-01-26 14:10:14 +08:00
15 changed files with 281 additions and 134 deletions

View File

@@ -1,2 +1,2 @@
go1.23.4 go1.23.6
time 2024-11-27T20:27:20Z time 2025-01-31T18:38:03Z

View File

@@ -252,6 +252,7 @@ func writebarrier(f *Func) {
var start, end int var start, end int
var nonPtrStores int var nonPtrStores int
values := b.Values values := b.Values
hasMove := false
FindSeq: FindSeq:
for i := len(values) - 1; i >= 0; i-- { for i := len(values) - 1; i >= 0; i-- {
w := values[i] w := values[i]
@@ -263,6 +264,9 @@ func writebarrier(f *Func) {
end = i + 1 end = i + 1
} }
nonPtrStores = 0 nonPtrStores = 0
if w.Op == OpMoveWB {
hasMove = true
}
case OpVarDef, OpVarLive: case OpVarDef, OpVarLive:
continue continue
case OpStore: case OpStore:
@@ -273,6 +277,17 @@ func writebarrier(f *Func) {
if nonPtrStores > 2 { if nonPtrStores > 2 {
break FindSeq break FindSeq
} }
if hasMove {
// We need to ensure that this store happens
// before we issue a wbMove, as the wbMove might
// use the result of this store as its source.
// Even though this store is not write-barrier
// eligible, it might nevertheless be the store
// of a pointer to the stack, which is then the
// source of the move.
// See issue 71228.
break FindSeq
}
default: default:
if last == nil { if last == nil {
continue continue

View File

@@ -662,7 +662,21 @@ func (r *gitRepo) statLocal(ctx context.Context, version, rev string) (*RevInfo,
} }
} }
} }
sort.Strings(info.Tags)
// Git 2.47.1 does not send the tags during shallow clone anymore
// (perhaps the exact version that changed behavior is an earlier one),
// so we have to also add tags from the refs list we fetched with ls-remote.
if refs, err := r.loadRefs(ctx); err == nil {
for ref, h := range refs {
if h == hash {
if tag, found := strings.CutPrefix(ref, "refs/tags/"); found {
info.Tags = append(info.Tags, tag)
}
}
}
}
slices.Sort(info.Tags)
info.Tags = slices.Compact(info.Tags)
// Used hash as info.Version above. // Used hash as info.Version above.
// Use caller's suggested version if it appears in the tag list // Use caller's suggested version if it appears in the tag list

View File

@@ -126,14 +126,23 @@ GLOBL p256mul<>(SB), 8, $160
#define PH V31 #define PH V31
#define CAR1 V6 #define CAR1 V6
#define SEL V8
#define ZER V9
// func p256NegCond(val *p256Point, cond int) // func p256NegCond(val *p256Point, cond int)
TEXT ·p256NegCond(SB), NOSPLIT, $0-16 TEXT ·p256NegCond(SB), NOSPLIT, $0-16
MOVD val+0(FP), P1ptr MOVD val+0(FP), P1ptr
MOVD $16, R16 MOVD $16, R16
MOVD cond+8(FP), R6 // Copy cond into SEL (cond is R1 + 8 (cond offset) + 32)
CMP $0, R6 MOVD $40, R17
BC 12, 2, LR // just return if cond == 0 LXVDSX (R1)(R17), SEL
// Zeroize ZER
VSPLTISB $0, ZER
// SEL controls whether to return the original value (Y1H/Y1L)
// or the negated value (T1H/T1L).
VCMPEQUD SEL, ZER, SEL
MOVD $p256mul<>+0x00(SB), CPOOL MOVD $p256mul<>+0x00(SB), CPOOL
@@ -150,6 +159,9 @@ TEXT ·p256NegCond(SB), NOSPLIT, $0-16
VSUBUQM PL, Y1L, T1L // subtract part2 giving result VSUBUQM PL, Y1L, T1L // subtract part2 giving result
VSUBEUQM PH, Y1H, CAR1, T1H // subtract part1 using carry from part2 VSUBEUQM PH, Y1H, CAR1, T1H // subtract part1 using carry from part2
VSEL T1H, Y1H, SEL, T1H
VSEL T1L, Y1L, SEL, T1L
XXPERMDI T1H, T1H, $2, T1H XXPERMDI T1H, T1H, $2, T1H
XXPERMDI T1L, T1L, $2, T1L XXPERMDI T1L, T1L, $2, T1L
@@ -166,6 +178,8 @@ TEXT ·p256NegCond(SB), NOSPLIT, $0-16
#undef PL #undef PL
#undef PH #undef PH
#undef CAR1 #undef CAR1
#undef SEL
#undef ZER
#define P3ptr R3 #define P3ptr R3
#define P1ptr R4 #define P1ptr R4

View File

@@ -852,6 +852,7 @@ func testResumption(t *testing.T, version uint16) {
MaxVersion: version, MaxVersion: version,
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
Certificates: testConfig.Certificates, Certificates: testConfig.Certificates,
Time: testTime,
} }
issuer, err := x509.ParseCertificate(testRSACertificateIssuer) issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
@@ -868,6 +869,7 @@ func testResumption(t *testing.T, version uint16) {
ClientSessionCache: NewLRUClientSessionCache(32), ClientSessionCache: NewLRUClientSessionCache(32),
RootCAs: rootCAs, RootCAs: rootCAs,
ServerName: "example.golang", ServerName: "example.golang",
Time: testTime,
} }
testResumeState := func(test string, didResume bool) { testResumeState := func(test string, didResume bool) {
@@ -914,7 +916,7 @@ func testResumption(t *testing.T, version uint16) {
// An old session ticket is replaced with a ticket encrypted with a fresh key. // An old session ticket is replaced with a ticket encrypted with a fresh key.
ticket = getTicket() ticket = getTicket()
serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) }
testResumeState("ResumeWithOldTicket", true) testResumeState("ResumeWithOldTicket", true)
if bytes.Equal(ticket, getTicket()) { if bytes.Equal(ticket, getTicket()) {
t.Fatal("old first ticket matches the fresh one") t.Fatal("old first ticket matches the fresh one")
@@ -922,13 +924,13 @@ func testResumption(t *testing.T, version uint16) {
// Once the session master secret is expired, a full handshake should occur. // Once the session master secret is expired, a full handshake should occur.
ticket = getTicket() ticket = getTicket()
serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + time.Minute) }
testResumeState("ResumeWithExpiredTicket", false) testResumeState("ResumeWithExpiredTicket", false)
if bytes.Equal(ticket, getTicket()) { if bytes.Equal(ticket, getTicket()) {
t.Fatal("expired first ticket matches the fresh one") t.Fatal("expired first ticket matches the fresh one")
} }
serverConfig.Time = func() time.Time { return time.Now() } // reset the time back serverConfig.Time = testTime // reset the time back
key1 := randomKey() key1 := randomKey()
serverConfig.SetSessionTicketKeys([][32]byte{key1}) serverConfig.SetSessionTicketKeys([][32]byte{key1})
@@ -945,11 +947,11 @@ func testResumption(t *testing.T, version uint16) {
testResumeState("KeyChangeFinish", true) testResumeState("KeyChangeFinish", true)
// Age the session ticket a bit, but not yet expired. // Age the session ticket a bit, but not yet expired.
serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) }
testResumeState("OldSessionTicket", true) testResumeState("OldSessionTicket", true)
ticket = getTicket() ticket = getTicket()
// Expire the session ticket, which would force a full handshake. // Expire the session ticket, which would force a full handshake.
serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + 2*time.Minute) }
testResumeState("ExpiredSessionTicket", false) testResumeState("ExpiredSessionTicket", false)
if bytes.Equal(ticket, getTicket()) { if bytes.Equal(ticket, getTicket()) {
t.Fatal("new ticket wasn't provided after old ticket expired") t.Fatal("new ticket wasn't provided after old ticket expired")
@@ -957,7 +959,7 @@ func testResumption(t *testing.T, version uint16) {
// Age the session ticket a bit at a time, but don't expire it. // Age the session ticket a bit at a time, but don't expire it.
d := 0 * time.Hour d := 0 * time.Hour
serverConfig.Time = func() time.Time { return time.Now().Add(d) } serverConfig.Time = func() time.Time { return testTime().Add(d) }
deleteTicket() deleteTicket()
testResumeState("GetFreshSessionTicket", false) testResumeState("GetFreshSessionTicket", false)
for i := 0; i < 13; i++ { for i := 0; i < 13; i++ {
@@ -968,7 +970,7 @@ func testResumption(t *testing.T, version uint16) {
// handshake occurs for TLS 1.2. Resumption should still occur for // handshake occurs for TLS 1.2. Resumption should still occur for
// TLS 1.3 since the client should be using a fresh ticket sent over // TLS 1.3 since the client should be using a fresh ticket sent over
// by the server. // by the server.
d += 12 * time.Hour d += 12*time.Hour + time.Minute
if version == VersionTLS13 { if version == VersionTLS13 {
testResumeState("ExpiredSessionTicket", true) testResumeState("ExpiredSessionTicket", true)
} else { } else {
@@ -984,6 +986,7 @@ func testResumption(t *testing.T, version uint16) {
MaxVersion: version, MaxVersion: version,
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
Certificates: testConfig.Certificates, Certificates: testConfig.Certificates,
Time: testTime,
} }
serverConfig.SetSessionTicketKeys([][32]byte{key2}) serverConfig.SetSessionTicketKeys([][32]byte{key2})
@@ -1009,6 +1012,7 @@ func testResumption(t *testing.T, version uint16) {
CurvePreferences: []CurveID{CurveP521, CurveP384, CurveP256}, CurvePreferences: []CurveID{CurveP521, CurveP384, CurveP256},
MaxVersion: version, MaxVersion: version,
Certificates: testConfig.Certificates, Certificates: testConfig.Certificates,
Time: testTime,
} }
testResumeState("InitialHandshake", false) testResumeState("InitialHandshake", false)
testResumeState("WithHelloRetryRequest", true) testResumeState("WithHelloRetryRequest", true)
@@ -1018,6 +1022,7 @@ func testResumption(t *testing.T, version uint16) {
MaxVersion: version, MaxVersion: version,
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
Certificates: testConfig.Certificates, Certificates: testConfig.Certificates,
Time: testTime,
} }
} }
@@ -1736,6 +1741,7 @@ func testVerifyConnection(t *testing.T, version uint16) {
serverConfig := &Config{ serverConfig := &Config{
MaxVersion: version, MaxVersion: version,
Certificates: []Certificate{testConfig.Certificates[0]}, Certificates: []Certificate{testConfig.Certificates[0]},
Time: testTime,
ClientCAs: rootCAs, ClientCAs: rootCAs,
NextProtos: []string{"protocol1"}, NextProtos: []string{"protocol1"},
} }
@@ -1749,6 +1755,7 @@ func testVerifyConnection(t *testing.T, version uint16) {
RootCAs: rootCAs, RootCAs: rootCAs,
ServerName: "example.golang", ServerName: "example.golang",
Certificates: []Certificate{testConfig.Certificates[0]}, Certificates: []Certificate{testConfig.Certificates[0]},
Time: testTime,
NextProtos: []string{"protocol1"}, NextProtos: []string{"protocol1"},
} }
test.configureClient(clientConfig, &clientCalled) test.configureClient(clientConfig, &clientCalled)
@@ -1791,8 +1798,6 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) {
rootCAs := x509.NewCertPool() rootCAs := x509.NewCertPool()
rootCAs.AddCert(issuer) rootCAs.AddCert(issuer)
now := func() time.Time { return time.Unix(1476984729, 0) }
sentinelErr := errors.New("TestVerifyPeerCertificate") sentinelErr := errors.New("TestVerifyPeerCertificate")
verifyPeerCertificateCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { verifyPeerCertificateCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error {
@@ -2038,7 +2043,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) {
config.ServerName = "example.golang" config.ServerName = "example.golang"
config.ClientAuth = RequireAndVerifyClientCert config.ClientAuth = RequireAndVerifyClientCert
config.ClientCAs = rootCAs config.ClientCAs = rootCAs
config.Time = now config.Time = testTime
config.MaxVersion = version config.MaxVersion = version
config.Certificates = make([]Certificate, 1) config.Certificates = make([]Certificate, 1)
config.Certificates[0].Certificate = [][]byte{testRSACertificate} config.Certificates[0].Certificate = [][]byte{testRSACertificate}
@@ -2055,7 +2060,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) {
config := testConfig.Clone() config := testConfig.Clone()
config.ServerName = "example.golang" config.ServerName = "example.golang"
config.RootCAs = rootCAs config.RootCAs = rootCAs
config.Time = now config.Time = testTime
config.MaxVersion = version config.MaxVersion = version
test.configureClient(config, &clientCalled) test.configureClient(config, &clientCalled)
clientErr := Client(c, config).Handshake() clientErr := Client(c, config).Handshake()
@@ -2368,7 +2373,7 @@ func testGetClientCertificate(t *testing.T, version uint16) {
serverConfig.RootCAs = x509.NewCertPool() serverConfig.RootCAs = x509.NewCertPool()
serverConfig.RootCAs.AddCert(issuer) serverConfig.RootCAs.AddCert(issuer)
serverConfig.ClientCAs = serverConfig.RootCAs serverConfig.ClientCAs = serverConfig.RootCAs
serverConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } serverConfig.Time = testTime
serverConfig.MaxVersion = version serverConfig.MaxVersion = version
clientConfig := testConfig.Clone() clientConfig := testConfig.Clone()
@@ -2539,6 +2544,7 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) {
ClientSessionCache: NewLRUClientSessionCache(32), ClientSessionCache: NewLRUClientSessionCache(32),
ServerName: "example.golang", ServerName: "example.golang",
RootCAs: roots, RootCAs: roots,
Time: testTime,
} }
serverConfig := testConfig.Clone() serverConfig := testConfig.Clone()
serverConfig.MaxVersion = ver serverConfig.MaxVersion = ver

View File

@@ -501,6 +501,7 @@ func testCrossVersionResume(t *testing.T, version uint16) {
serverConfig := &Config{ serverConfig := &Config{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
Certificates: testConfig.Certificates, Certificates: testConfig.Certificates,
Time: testTime,
} }
clientConfig := &Config{ clientConfig := &Config{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
@@ -508,6 +509,7 @@ func testCrossVersionResume(t *testing.T, version uint16) {
ClientSessionCache: NewLRUClientSessionCache(1), ClientSessionCache: NewLRUClientSessionCache(1),
ServerName: "servername", ServerName: "servername",
MinVersion: VersionTLS12, MinVersion: VersionTLS12,
Time: testTime,
} }
// Establish a session at TLS 1.3. // Establish a session at TLS 1.3.

View File

@@ -519,6 +519,11 @@ func fromHex(s string) []byte {
return b return b
} }
// testTime is 2016-10-20T17:32:09.000Z, which is within the validity period of
// [testRSACertificate], [testRSACertificateIssuer], [testRSA2048Certificate],
// [testRSA2048CertificateIssuer], and [testECDSACertificate].
var testTime = func() time.Time { return time.Unix(1476984729, 0) }
var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7") var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7")
var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76") var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76")

View File

@@ -1112,8 +1112,6 @@ func TestConnectionState(t *testing.T) {
rootCAs := x509.NewCertPool() rootCAs := x509.NewCertPool()
rootCAs.AddCert(issuer) rootCAs.AddCert(issuer)
now := func() time.Time { return time.Unix(1476984729, 0) }
const alpnProtocol = "golang" const alpnProtocol = "golang"
const serverName = "example.golang" const serverName = "example.golang"
var scts = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} var scts = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")}
@@ -1129,7 +1127,7 @@ func TestConnectionState(t *testing.T) {
} }
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
config := &Config{ config := &Config{
Time: now, Time: testTime,
Rand: zeroSource{}, Rand: zeroSource{},
Certificates: make([]Certificate, 1), Certificates: make([]Certificate, 1),
MaxVersion: v, MaxVersion: v,
@@ -1760,7 +1758,7 @@ func testVerifyCertificates(t *testing.T, version uint16) {
var serverVerifyPeerCertificates, clientVerifyPeerCertificates bool var serverVerifyPeerCertificates, clientVerifyPeerCertificates bool
clientConfig := testConfig.Clone() clientConfig := testConfig.Clone()
clientConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } clientConfig.Time = testTime
clientConfig.MaxVersion = version clientConfig.MaxVersion = version
clientConfig.MinVersion = version clientConfig.MinVersion = version
clientConfig.RootCAs = rootCAs clientConfig.RootCAs = rootCAs

View File

@@ -1607,6 +1607,23 @@ var nameConstraintsTests = []nameConstraintsTest{
leaf: leafSpec{sans: []string{"dns:.example.com"}}, leaf: leafSpec{sans: []string{"dns:.example.com"}},
expectedError: "cannot parse dnsName \".example.com\"", expectedError: "cannot parse dnsName \".example.com\"",
}, },
// #86: URIs with IPv6 addresses with zones and ports are rejected
{
roots: []constraintsSpec{
{
ok: []string{"uri:example.com"},
},
},
intermediates: [][]constraintsSpec{
{
{},
},
},
leaf: leafSpec{
sans: []string{"uri:http://[2006:abcd::1%25.example.com]:16/"},
},
expectedError: "URI with IP",
},
} }
func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {

View File

@@ -11,6 +11,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/netip"
"net/url" "net/url"
"reflect" "reflect"
"runtime" "runtime"
@@ -434,8 +435,10 @@ func matchURIConstraint(uri *url.URL, constraint string) (bool, error) {
} }
} }
if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") || // netip.ParseAddr will reject the URI IPv6 literal form "[...]", so we
net.ParseIP(host) != nil { // check if _either_ the string parses as an IP, or if it is enclosed in
// square brackets.
if _, err := netip.ParseAddr(host); err == nil || (strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]")) {
return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String()) return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
} }

View File

@@ -613,8 +613,9 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
reqBodyClosed = false // have we closed the current req.Body? reqBodyClosed = false // have we closed the current req.Body?
// Redirect behavior: // Redirect behavior:
redirectMethod string redirectMethod string
includeBody bool includeBody = true
stripSensitiveHeaders = false
) )
uerr := func(err error) error { uerr := func(err error) error {
// the body may have been closed already by c.send() // the body may have been closed already by c.send()
@@ -681,7 +682,12 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
// in case the user set Referer on their first request. // in case the user set Referer on their first request.
// If they really want to override, they can do it in // If they really want to override, they can do it in
// their CheckRedirect func. // their CheckRedirect func.
copyHeaders(req) if !stripSensitiveHeaders && reqs[0].URL.Host != req.URL.Host {
if !shouldCopyHeaderOnRedirect(reqs[0].URL, req.URL) {
stripSensitiveHeaders = true
}
}
copyHeaders(req, stripSensitiveHeaders)
// Add the Referer header from the most recent // Add the Referer header from the most recent
// request URL to the new one, if it's not https->http: // request URL to the new one, if it's not https->http:
@@ -744,7 +750,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
// makeHeadersCopier makes a function that copies headers from the // makeHeadersCopier makes a function that copies headers from the
// initial Request, ireq. For every redirect, this function must be called // initial Request, ireq. For every redirect, this function must be called
// so that it can copy headers into the upcoming Request. // so that it can copy headers into the upcoming Request.
func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) { func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensitiveHeaders bool) {
// The headers to copy are from the very initial request. // The headers to copy are from the very initial request.
// We use a closured callback to keep a reference to these original headers. // We use a closured callback to keep a reference to these original headers.
var ( var (
@@ -758,8 +764,7 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
} }
} }
preq := ireq // The previous request return func(req *Request, stripSensitiveHeaders bool) {
return func(req *Request) {
// If Jar is present and there was some initial cookies provided // If Jar is present and there was some initial cookies provided
// via the request header, then we may need to alter the initial // via the request header, then we may need to alter the initial
// cookies as we follow redirects since each redirect may end up // cookies as we follow redirects since each redirect may end up
@@ -796,12 +801,15 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
// Copy the initial request's Header values // Copy the initial request's Header values
// (at least the safe ones). // (at least the safe ones).
for k, vv := range ireqhdr { for k, vv := range ireqhdr {
if shouldCopyHeaderOnRedirect(k, preq.URL, req.URL) { sensitive := false
switch CanonicalHeaderKey(k) {
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
sensitive = true
}
if !(sensitive && stripSensitiveHeaders) {
req.Header[k] = vv req.Header[k] = vv
} }
} }
preq = req // Update previous Request with the current request
} }
} }
@@ -977,28 +985,23 @@ func (b *cancelTimerBody) Close() error {
return err return err
} }
func shouldCopyHeaderOnRedirect(headerKey string, initial, dest *url.URL) bool { func shouldCopyHeaderOnRedirect(initial, dest *url.URL) bool {
switch CanonicalHeaderKey(headerKey) { // Permit sending auth/cookie headers from "foo.com"
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2": // to "sub.foo.com".
// Permit sending auth/cookie headers from "foo.com"
// to "sub.foo.com".
// Note that we don't send all cookies to subdomains // Note that we don't send all cookies to subdomains
// automatically. This function is only used for // automatically. This function is only used for
// Cookies set explicitly on the initial outgoing // Cookies set explicitly on the initial outgoing
// client request. Cookies automatically added via the // client request. Cookies automatically added via the
// CookieJar mechanism continue to follow each // CookieJar mechanism continue to follow each
// cookie's scope as set by Set-Cookie. But for // cookie's scope as set by Set-Cookie. But for
// outgoing requests with the Cookie header set // outgoing requests with the Cookie header set
// directly, we don't know their scope, so we assume // directly, we don't know their scope, so we assume
// it's for *.domain.com. // it's for *.domain.com.
ihost := idnaASCIIFromURL(initial) ihost := idnaASCIIFromURL(initial)
dhost := idnaASCIIFromURL(dest) dhost := idnaASCIIFromURL(dest)
return isDomainOrSubdomain(dhost, ihost) return isDomainOrSubdomain(dhost, ihost)
}
// All other headers are copied:
return true
} }
// isDomainOrSubdomain reports whether sub is a subdomain (or exact // isDomainOrSubdomain reports whether sub is a subdomain (or exact

View File

@@ -1536,6 +1536,55 @@ func testClientCopyHeadersOnRedirect(t *testing.T, mode testMode) {
} }
} }
// Issue #70530: Once we strip a header on a redirect to a different host,
// the header should stay stripped across any further redirects.
func TestClientStripHeadersOnRepeatedRedirect(t *testing.T) {
run(t, testClientStripHeadersOnRepeatedRedirect)
}
func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) {
var proto string
ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
if r.Host+r.URL.Path != "a.example.com/" {
if h := r.Header.Get("Authorization"); h != "" {
t.Errorf("on request to %v%v, Authorization=%q, want no header", r.Host, r.URL.Path, h)
}
}
// Follow a chain of redirects from a to b and back to a.
// The Authorization header is stripped on the first redirect to b,
// and stays stripped even if we're sent back to a.
switch r.Host + r.URL.Path {
case "a.example.com/":
Redirect(w, r, proto+"://b.example.com/", StatusFound)
case "b.example.com/":
Redirect(w, r, proto+"://b.example.com/redirect", StatusFound)
case "b.example.com/redirect":
Redirect(w, r, proto+"://a.example.com/redirect", StatusFound)
case "a.example.com/redirect":
w.Header().Set("X-Done", "true")
default:
t.Errorf("unexpected request to %v", r.URL)
}
})).ts
proto, _, _ = strings.Cut(ts.URL, ":")
c := ts.Client()
c.Transport.(*Transport).Dial = func(_ string, _ string) (net.Conn, error) {
return net.Dial("tcp", ts.Listener.Addr().String())
}
req, _ := NewRequest("GET", proto+"://a.example.com/", nil)
req.Header.Add("Cookie", "foo=bar")
req.Header.Add("Authorization", "secretpassword")
res, err := c.Do(req)
if err != nil {
t.Fatal(err)
}
defer res.Body.Close()
if res.Header.Get("X-Done") != "true" {
t.Fatalf("response missing expected header: X-Done=true")
}
}
// Issue 22233: copy host when Client follows a relative redirect. // Issue 22233: copy host when Client follows a relative redirect.
func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) } func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) }
func testClientCopyHostOnRedirect(t *testing.T, mode testMode) { func testClientCopyHostOnRedirect(t *testing.T, mode testMode) {
@@ -1702,43 +1751,39 @@ func testClientAltersCookiesOnRedirect(t *testing.T, mode testMode) {
// Part of Issue 4800 // Part of Issue 4800
func TestShouldCopyHeaderOnRedirect(t *testing.T) { func TestShouldCopyHeaderOnRedirect(t *testing.T) {
tests := []struct { tests := []struct {
header string
initialURL string initialURL string
destURL string destURL string
want bool want bool
}{ }{
{"User-Agent", "http://foo.com/", "http://bar.com/", true},
{"X-Foo", "http://foo.com/", "http://bar.com/", true},
// Sensitive headers: // Sensitive headers:
{"cookie", "http://foo.com/", "http://bar.com/", false}, {"http://foo.com/", "http://bar.com/", false},
{"cookie2", "http://foo.com/", "http://bar.com/", false}, {"http://foo.com/", "http://bar.com/", false},
{"authorization", "http://foo.com/", "http://bar.com/", false}, {"http://foo.com/", "http://bar.com/", false},
{"authorization", "http://foo.com/", "https://foo.com/", true}, {"http://foo.com/", "https://foo.com/", true},
{"authorization", "http://foo.com:1234/", "http://foo.com:4321/", true}, {"http://foo.com:1234/", "http://foo.com:4321/", true},
{"www-authenticate", "http://foo.com/", "http://bar.com/", false}, {"http://foo.com/", "http://bar.com/", false},
{"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false}, {"http://foo.com/", "http://[::1%25.foo.com]/", false},
// But subdomains should work: // But subdomains should work:
{"www-authenticate", "http://foo.com/", "http://foo.com/", true}, {"http://foo.com/", "http://foo.com/", true},
{"www-authenticate", "http://foo.com/", "http://sub.foo.com/", true}, {"http://foo.com/", "http://sub.foo.com/", true},
{"www-authenticate", "http://foo.com/", "http://notfoo.com/", false}, {"http://foo.com/", "http://notfoo.com/", false},
{"www-authenticate", "http://foo.com/", "https://foo.com/", true}, {"http://foo.com/", "https://foo.com/", true},
{"www-authenticate", "http://foo.com:80/", "http://foo.com/", true}, {"http://foo.com:80/", "http://foo.com/", true},
{"www-authenticate", "http://foo.com:80/", "http://sub.foo.com/", true}, {"http://foo.com:80/", "http://sub.foo.com/", true},
{"www-authenticate", "http://foo.com:443/", "https://foo.com/", true}, {"http://foo.com:443/", "https://foo.com/", true},
{"www-authenticate", "http://foo.com:443/", "https://sub.foo.com/", true}, {"http://foo.com:443/", "https://sub.foo.com/", true},
{"www-authenticate", "http://foo.com:1234/", "http://foo.com/", true}, {"http://foo.com:1234/", "http://foo.com/", true},
{"authorization", "http://foo.com/", "http://foo.com/", true}, {"http://foo.com/", "http://foo.com/", true},
{"authorization", "http://foo.com/", "http://sub.foo.com/", true}, {"http://foo.com/", "http://sub.foo.com/", true},
{"authorization", "http://foo.com/", "http://notfoo.com/", false}, {"http://foo.com/", "http://notfoo.com/", false},
{"authorization", "http://foo.com/", "https://foo.com/", true}, {"http://foo.com/", "https://foo.com/", true},
{"authorization", "http://foo.com:80/", "http://foo.com/", true}, {"http://foo.com:80/", "http://foo.com/", true},
{"authorization", "http://foo.com:80/", "http://sub.foo.com/", true}, {"http://foo.com:80/", "http://sub.foo.com/", true},
{"authorization", "http://foo.com:443/", "https://foo.com/", true}, {"http://foo.com:443/", "https://foo.com/", true},
{"authorization", "http://foo.com:443/", "https://sub.foo.com/", true}, {"http://foo.com:443/", "https://sub.foo.com/", true},
{"authorization", "http://foo.com:1234/", "http://foo.com/", true}, {"http://foo.com:1234/", "http://foo.com/", true},
} }
for i, tt := range tests { for i, tt := range tests {
u0, err := url.Parse(tt.initialURL) u0, err := url.Parse(tt.initialURL)
@@ -1751,10 +1796,10 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) {
t.Errorf("%d. dest URL %q parse error: %v", i, tt.destURL, err) t.Errorf("%d. dest URL %q parse error: %v", i, tt.destURL, err)
continue continue
} }
got := Export_shouldCopyHeaderOnRedirect(tt.header, u0, u1) got := Export_shouldCopyHeaderOnRedirect(u0, u1)
if got != tt.want { if got != tt.want {
t.Errorf("%d. shouldCopyHeaderOnRedirect(%q, %q => %q) = %v; want %v", t.Errorf("%d. shouldCopyHeaderOnRedirect(%q => %q) = %v; want %v",
i, tt.header, tt.initialURL, tt.destURL, got, tt.want) i, tt.initialURL, tt.destURL, got, tt.want)
} }
} }
} }

View File

@@ -10,56 +10,56 @@ import "strings"
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs // LocalhostCert is a PEM-encoded TLS cert with SAN IPs
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT. // "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
// generated from src/crypto/tls: // generated from src/crypto/tls:
// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h // go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com,*.example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE----- var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
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
WkBKOclmOV2xlTVuPw== rF7r4gUnKeC7mYIH1zypY7laskopiLFAfe96Kg==
-----END CERTIFICATE-----`) -----END CERTIFICATE-----`)
// LocalhostKey is the private key for LocalhostCert. // LocalhostKey is the private key for LocalhostCert.
var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY----- var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY-----
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
ZboOWVe3icTy64BT3OQhmg== jel6uj2FOP9g54s+GzlSVg/T
-----END RSA TESTING KEY-----`)) -----END RSA TESTING KEY-----`))
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }

View File

@@ -3873,23 +3873,23 @@ func injectglist(glist *gList) {
if glist.empty() { if glist.empty() {
return return
} }
trace := traceAcquire()
if trace.ok() {
for gp := glist.head.ptr(); gp != nil; gp = gp.schedlink.ptr() {
trace.GoUnpark(gp, 0)
}
traceRelease(trace)
}
// Mark all the goroutines as runnable before we put them // Mark all the goroutines as runnable before we put them
// on the run queues. // on the run queues.
head := glist.head.ptr() head := glist.head.ptr()
var tail *g var tail *g
qsize := 0 qsize := 0
trace := traceAcquire()
for gp := head; gp != nil; gp = gp.schedlink.ptr() { for gp := head; gp != nil; gp = gp.schedlink.ptr() {
tail = gp tail = gp
qsize++ qsize++
casgstatus(gp, _Gwaiting, _Grunnable) casgstatus(gp, _Gwaiting, _Grunnable)
if trace.ok() {
trace.GoUnpark(gp, 0)
}
}
if trace.ok() {
traceRelease(trace)
} }
// Turn the gList into a gQueue. // Turn the gList into a gQueue.

View File

@@ -53,3 +53,28 @@ func combine4slice(p *[4][]byte, a, b, c, d []byte) {
// arm64:-`.*runtime[.]gcWriteBarrier` // arm64:-`.*runtime[.]gcWriteBarrier`
p[3] = d p[3] = d
} }
type S struct {
a, b string
c *int
}
var g1, g2 *int
func issue71228(dst *S, ptr *int) {
// Make sure that the non-write-barrier write.
// "sp.c = ptr" happens before the large write
// barrier "*dst = *sp". We approximate testing
// that by ensuring that two global variable write
// barriers aren't combined.
_ = *dst
var s S
sp := &s
//amd64:`.*runtime[.]gcWriteBarrier1`
g1 = nil
sp.c = ptr // outside of any write barrier
//amd64:`.*runtime[.]gcWriteBarrier1`
g2 = nil
//amd64:`.*runtime[.]wbMove`
*dst = *sp
}