fix: Bump golang.org/x/text and its dependencies to fix CVE

This commit is contained in:
João "Pisco" Fernandes
2026-07-22 16:49:49 +01:00
parent 12e11208ae
commit 78865b19bc
59 changed files with 3283 additions and 711 deletions
+8 -8
View File
@@ -36,11 +36,11 @@ require (
go.opentelemetry.io/proto/otlp v1.10.0 go.opentelemetry.io/proto/otlp v1.10.0
go.uber.org/automaxprocs v1.6.0 go.uber.org/automaxprocs v1.6.0
go.uber.org/mock v0.5.1 go.uber.org/mock v0.5.1
golang.org/x/crypto v0.52.0 golang.org/x/crypto v0.53.0
golang.org/x/net v0.55.0 golang.org/x/net v0.56.0
golang.org/x/sync v0.20.0 golang.org/x/sync v0.22.0
golang.org/x/sys v0.45.0 golang.org/x/sys v0.46.0
golang.org/x/term v0.43.0 golang.org/x/term v0.44.0
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@@ -91,10 +91,10 @@ require (
go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect
golang.org/x/arch v0.4.0 // indirect golang.org/x/arch v0.4.0 // indirect
golang.org/x/mod v0.35.0 // indirect golang.org/x/mod v0.37.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/text v0.37.0 // indirect golang.org/x/text v0.40.0 // indirect
golang.org/x/tools v0.44.0 // indirect golang.org/x/tools v0.47.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
google.golang.org/grpc v1.81.1 // indirect google.golang.org/grpc v1.81.1 // indirect
+16 -16
View File
@@ -245,21 +245,21 @@ golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -269,20 +269,20 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+825
View File
@@ -0,0 +1,825 @@
// Copyright 2017 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 cryptobyte
import (
encoding_asn1 "encoding/asn1"
"fmt"
"math/big"
"reflect"
"time"
"golang.org/x/crypto/cryptobyte/asn1"
)
// This file contains ASN.1-related methods for String and Builder.
// Builder
// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER.
func (b *Builder) AddASN1Int64(v int64) {
b.addASN1Signed(asn1.INTEGER, v)
}
// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the
// given tag.
func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) {
b.addASN1Signed(tag, v)
}
// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION.
func (b *Builder) AddASN1Enum(v int64) {
b.addASN1Signed(asn1.ENUM, v)
}
func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) {
b.AddASN1(tag, func(c *Builder) {
length := 1
for i := v; i >= 0x80 || i < -0x80; i >>= 8 {
length++
}
for ; length > 0; length-- {
i := v >> uint((length-1)*8) & 0xff
c.AddUint8(uint8(i))
}
})
}
// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER.
func (b *Builder) AddASN1Uint64(v uint64) {
b.AddASN1(asn1.INTEGER, func(c *Builder) {
length := 1
for i := v; i >= 0x80; i >>= 8 {
length++
}
for ; length > 0; length-- {
i := v >> uint((length-1)*8) & 0xff
c.AddUint8(uint8(i))
}
})
}
// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER.
func (b *Builder) AddASN1BigInt(n *big.Int) {
if b.err != nil {
return
}
b.AddASN1(asn1.INTEGER, func(c *Builder) {
if n.Sign() < 0 {
// A negative number has to be converted to two's-complement form. So we
// invert and subtract 1. If the most-significant-bit isn't set then
// we'll need to pad the beginning with 0xff in order to keep the number
// negative.
nMinus1 := new(big.Int).Neg(n)
nMinus1.Sub(nMinus1, bigOne)
bytes := nMinus1.Bytes()
for i := range bytes {
bytes[i] ^= 0xff
}
if len(bytes) == 0 || bytes[0]&0x80 == 0 {
c.add(0xff)
}
c.add(bytes...)
} else if n.Sign() == 0 {
c.add(0)
} else {
bytes := n.Bytes()
if bytes[0]&0x80 != 0 {
c.add(0)
}
c.add(bytes...)
}
})
}
// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING.
func (b *Builder) AddASN1OctetString(bytes []byte) {
b.AddASN1(asn1.OCTET_STRING, func(c *Builder) {
c.AddBytes(bytes)
})
}
const generalizedTimeFormatStr = "20060102150405Z0700"
// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME.
func (b *Builder) AddASN1GeneralizedTime(t time.Time) {
if t.Year() < 0 || t.Year() > 9999 {
b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t)
return
}
b.AddASN1(asn1.GeneralizedTime, func(c *Builder) {
c.AddBytes([]byte(t.Format(generalizedTimeFormatStr)))
})
}
// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime.
func (b *Builder) AddASN1UTCTime(t time.Time) {
b.AddASN1(asn1.UTCTime, func(c *Builder) {
// As utilized by the X.509 profile, UTCTime can only
// represent the years 1950 through 2049.
if t.Year() < 1950 || t.Year() >= 2050 {
b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t)
return
}
c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr)))
})
}
// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not
// support BIT STRINGs that are not a whole number of bytes.
func (b *Builder) AddASN1BitString(data []byte) {
b.AddASN1(asn1.BIT_STRING, func(b *Builder) {
b.AddUint8(0)
b.AddBytes(data)
})
}
func (b *Builder) addBase128Int(n int64) {
var length int
if n == 0 {
length = 1
} else {
for i := n; i > 0; i >>= 7 {
length++
}
}
for i := length - 1; i >= 0; i-- {
o := byte(n >> uint(i*7))
o &= 0x7f
if i != 0 {
o |= 0x80
}
b.add(o)
}
}
func isValidOID(oid encoding_asn1.ObjectIdentifier) bool {
if len(oid) < 2 {
return false
}
if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) {
return false
}
for _, v := range oid {
if v < 0 {
return false
}
}
return true
}
func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) {
b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) {
if !isValidOID(oid) {
b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid)
return
}
b.addBase128Int(int64(oid[0])*40 + int64(oid[1]))
for _, v := range oid[2:] {
b.addBase128Int(int64(v))
}
})
}
func (b *Builder) AddASN1Boolean(v bool) {
b.AddASN1(asn1.BOOLEAN, func(b *Builder) {
if v {
b.AddUint8(0xff)
} else {
b.AddUint8(0)
}
})
}
func (b *Builder) AddASN1NULL() {
b.add(uint8(asn1.NULL), 0)
}
// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if
// successful or records an error if one occurred.
func (b *Builder) MarshalASN1(v interface{}) {
// NOTE(martinkr): This is somewhat of a hack to allow propagation of
// encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a
// value embedded into a struct, its tag information is lost.
if b.err != nil {
return
}
bytes, err := encoding_asn1.Marshal(v)
if err != nil {
b.err = err
return
}
b.AddBytes(bytes)
}
// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag.
// Tags greater than 30 are not supported and result in an error (i.e.
// low-tag-number form only). The child builder passed to the
// BuilderContinuation can be used to build the content of the ASN.1 object.
func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) {
if b.err != nil {
return
}
// Identifiers with the low five bits set indicate high-tag-number format
// (two or more octets), which we don't support.
if tag&0x1f == 0x1f {
b.err = fmt.Errorf("cryptobyte: high-tag number identifier octets not supported: 0x%x", tag)
return
}
b.AddUint8(uint8(tag))
b.addLengthPrefixed(1, true, f)
}
// String
// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean
// representation into out and advances. It reports whether the read
// was successful.
func (s *String) ReadASN1Boolean(out *bool) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 {
return false
}
switch bytes[0] {
case 0:
*out = false
case 0xff:
*out = true
default:
return false
}
return true
}
// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does
// not point to an integer, to a big.Int, or to a []byte it panics. Only
// positive and zero values can be decoded into []byte, and they are returned as
// big-endian binary values that share memory with s. Positive values will have
// no leading zeroes, and zero will be returned as a single zero byte.
// ReadASN1Integer reports whether the read was successful.
func (s *String) ReadASN1Integer(out interface{}) bool {
switch out := out.(type) {
case *int, *int8, *int16, *int32, *int64:
var i int64
if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) {
return false
}
reflect.ValueOf(out).Elem().SetInt(i)
return true
case *uint, *uint8, *uint16, *uint32, *uint64:
var u uint64
if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) {
return false
}
reflect.ValueOf(out).Elem().SetUint(u)
return true
case *big.Int:
return s.readASN1BigInt(out)
case *[]byte:
return s.readASN1Bytes(out)
default:
panic("out does not point to an integer type")
}
}
func checkASN1Integer(bytes []byte) bool {
if len(bytes) == 0 {
// An INTEGER is encoded with at least one octet.
return false
}
if len(bytes) == 1 {
return true
}
if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 {
// Value is not minimally encoded.
return false
}
return true
}
var bigOne = big.NewInt(1)
func (s *String) readASN1BigInt(out *big.Int) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) {
return false
}
if bytes[0]&0x80 == 0x80 {
// Negative number.
neg := make([]byte, len(bytes))
for i, b := range bytes {
neg[i] = ^b
}
out.SetBytes(neg)
out.Add(out, bigOne)
out.Neg(out)
} else {
out.SetBytes(bytes)
}
return true
}
func (s *String) readASN1Bytes(out *[]byte) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) {
return false
}
if bytes[0]&0x80 == 0x80 {
return false
}
for len(bytes) > 1 && bytes[0] == 0 {
bytes = bytes[1:]
}
*out = bytes
return true
}
func (s *String) readASN1Int64(out *int64) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) {
return false
}
return true
}
func asn1Signed(out *int64, n []byte) bool {
length := len(n)
if length > 8 {
return false
}
for i := 0; i < length; i++ {
*out <<= 8
*out |= int64(n[i])
}
// Shift up and down in order to sign extend the result.
*out <<= 64 - uint8(length)*8
*out >>= 64 - uint8(length)*8
return true
}
func (s *String) readASN1Uint64(out *uint64) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) {
return false
}
return true
}
func asn1Unsigned(out *uint64, n []byte) bool {
length := len(n)
if length > 9 || length == 9 && n[0] != 0 {
// Too large for uint64.
return false
}
if n[0]&0x80 != 0 {
// Negative number.
return false
}
for i := 0; i < length; i++ {
*out <<= 8
*out |= uint64(n[i])
}
return true
}
// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out
// and advances. It reports whether the read was successful and resulted in a
// value that can be represented in an int64.
func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool {
var bytes String
return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes)
}
// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports
// whether the read was successful.
func (s *String) ReadASN1Enum(out *int) bool {
var bytes String
var i int64
if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) {
return false
}
if int64(int(i)) != i {
return false
}
*out = int(i)
return true
}
func (s *String) readBase128Int(out *int) bool {
ret := 0
for i := 0; len(*s) > 0; i++ {
if i == 5 {
return false
}
// Avoid overflowing int on a 32-bit platform.
// We don't want different behavior based on the architecture.
if ret >= 1<<(31-7) {
return false
}
ret <<= 7
b := s.read(1)[0]
// ITU-T X.690, section 8.19.2:
// The subidentifier shall be encoded in the fewest possible octets,
// that is, the leading octet of the subidentifier shall not have the value 0x80.
if i == 0 && b == 0x80 {
return false
}
ret |= int(b & 0x7f)
if b&0x80 == 0 {
*out = ret
return true
}
}
return false // truncated
}
// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and
// advances. It reports whether the read was successful.
func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 {
return false
}
// In the worst case, we get two elements from the first byte (which is
// encoded differently) and then every varint is a single byte long.
components := make([]int, len(bytes)+1)
// The first varint is 40*value1 + value2:
// According to this packing, value1 can take the values 0, 1 and 2 only.
// When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
// then there are no restrictions on value2.
var v int
if !bytes.readBase128Int(&v) {
return false
}
if v < 80 {
components[0] = v / 40
components[1] = v % 40
} else {
components[0] = 2
components[1] = v - 80
}
i := 2
for ; len(bytes) > 0; i++ {
if !bytes.readBase128Int(&v) {
return false
}
components[i] = v
}
*out = components[:i]
return true
}
// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and
// advances. It reports whether the read was successful.
func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.GeneralizedTime) {
return false
}
t := string(bytes)
res, err := time.Parse(generalizedTimeFormatStr, t)
if err != nil {
return false
}
if serialized := res.Format(generalizedTimeFormatStr); serialized != t {
return false
}
*out = res
return true
}
const defaultUTCTimeFormatStr = "060102150405Z0700"
// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances.
// It reports whether the read was successful.
func (s *String) ReadASN1UTCTime(out *time.Time) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.UTCTime) {
return false
}
t := string(bytes)
formatStr := defaultUTCTimeFormatStr
var err error
res, err := time.Parse(formatStr, t)
if err != nil {
// Fallback to minute precision if we can't parse second
// precision. If we are following X.509 or X.690 we shouldn't
// support this, but we do.
formatStr = "0601021504Z0700"
res, err = time.Parse(formatStr, t)
}
if err != nil {
return false
}
if serialized := res.Format(formatStr); serialized != t {
return false
}
if res.Year() >= 2050 {
// UTCTime interprets the low order digits 50-99 as 1950-99.
// This only applies to its use in the X.509 profile.
// See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
res = res.AddDate(-100, 0, 0)
}
*out = res
return true
}
// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances.
// It reports whether the read was successful.
func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 ||
len(bytes)*8/8 != len(bytes) {
return false
}
paddingBits := bytes[0]
bytes = bytes[1:]
if paddingBits > 7 ||
len(bytes) == 0 && paddingBits != 0 ||
len(bytes) > 0 && bytes[len(bytes)-1]&(1<<paddingBits-1) != 0 {
return false
}
out.BitLength = len(bytes)*8 - int(paddingBits)
out.Bytes = bytes
return true
}
// ReadASN1BitStringAsBytes decodes an ASN.1 BIT STRING into out and advances. It is
// an error if the BIT STRING is not a whole number of bytes. It reports
// whether the read was successful.
func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool {
var bytes String
if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 {
return false
}
paddingBits := bytes[0]
if paddingBits != 0 {
return false
}
*out = bytes[1:]
return true
}
// ReadASN1Bytes reads the contents of a DER-encoded ASN.1 element (not including
// tag and length bytes) into out, and advances. The element must match the
// given tag. It reports whether the read was successful.
func (s *String) ReadASN1Bytes(out *[]byte, tag asn1.Tag) bool {
return s.ReadASN1((*String)(out), tag)
}
// ReadASN1 reads the contents of a DER-encoded ASN.1 element (not including
// tag and length bytes) into out, and advances. The element must match the
// given tag. It reports whether the read was successful.
//
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
func (s *String) ReadASN1(out *String, tag asn1.Tag) bool {
var t asn1.Tag
if !s.ReadAnyASN1(out, &t) || t != tag {
return false
}
return true
}
// ReadASN1Element reads the contents of a DER-encoded ASN.1 element (including
// tag and length bytes) into out, and advances. The element must match the
// given tag. It reports whether the read was successful.
//
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool {
var t asn1.Tag
if !s.ReadAnyASN1Element(out, &t) || t != tag {
return false
}
return true
}
// ReadAnyASN1 reads the contents of a DER-encoded ASN.1 element (not including
// tag and length bytes) into out, sets outTag to its tag, and advances.
// It reports whether the read was successful.
//
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool {
return s.readASN1(out, outTag, true /* skip header */)
}
// ReadAnyASN1Element reads the contents of a DER-encoded ASN.1 element
// (including tag and length bytes) into out, sets outTag to is tag, and
// advances. It reports whether the read was successful.
//
// Tags greater than 30 are not supported (i.e. low-tag-number format only).
func (s *String) ReadAnyASN1Element(out *String, outTag *asn1.Tag) bool {
return s.readASN1(out, outTag, false /* include header */)
}
// PeekASN1Tag reports whether the next ASN.1 value on the string starts with
// the given tag.
func (s String) PeekASN1Tag(tag asn1.Tag) bool {
if len(s) == 0 {
return false
}
return asn1.Tag(s[0]) == tag
}
// SkipASN1 reads and discards an ASN.1 element with the given tag. It
// reports whether the operation was successful.
func (s *String) SkipASN1(tag asn1.Tag) bool {
var unused String
return s.ReadASN1(&unused, tag)
}
// ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.1
// element (not including tag and length bytes) tagged with the given tag into
// out. It stores whether an element with the tag was found in outPresent,
// unless outPresent is nil. It reports whether the read was successful.
func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) bool {
present := s.PeekASN1Tag(tag)
if outPresent != nil {
*outPresent = present
}
if present && !s.ReadASN1(out, tag) {
return false
}
return true
}
// SkipOptionalASN1 advances s over an ASN.1 element with the given tag, or
// else leaves s unchanged. It reports whether the operation was successful.
func (s *String) SkipOptionalASN1(tag asn1.Tag) bool {
if !s.PeekASN1Tag(tag) {
return true
}
var unused String
return s.ReadASN1(&unused, tag)
}
// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER explicitly
// tagged with tag into out and advances. If no element with a matching tag is
// present, it writes defaultValue into out instead. Otherwise, it behaves like
// ReadASN1Integer.
func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool {
var present bool
var i String
if !s.ReadOptionalASN1(&i, &present, tag) {
return false
}
if !present {
switch out.(type) {
case *int, *int8, *int16, *int32, *int64,
*uint, *uint8, *uint16, *uint32, *uint64, *[]byte:
reflect.ValueOf(out).Elem().Set(reflect.ValueOf(defaultValue))
case *big.Int:
if defaultValue, ok := defaultValue.(*big.Int); ok {
out.(*big.Int).Set(defaultValue)
} else {
panic("out points to big.Int, but defaultValue does not")
}
default:
panic("invalid integer type")
}
return true
}
if !i.ReadASN1Integer(out) || !i.Empty() {
return false
}
return true
}
// ReadOptionalASN1OctetString attempts to read an optional ASN.1 OCTET STRING
// explicitly tagged with tag into out and advances. If no element with a
// matching tag is present, it sets "out" to nil instead. It reports
// whether the read was successful.
func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag asn1.Tag) bool {
var present bool
var child String
if !s.ReadOptionalASN1(&child, &present, tag) {
return false
}
if outPresent != nil {
*outPresent = present
}
if present {
var oct String
if !child.ReadASN1(&oct, asn1.OCTET_STRING) || !child.Empty() {
return false
}
*out = oct
} else {
*out = nil
}
return true
}
// ReadOptionalASN1Boolean attempts to read an optional ASN.1 BOOLEAN
// explicitly tagged with tag into out and advances. If no element with a
// matching tag is present, it sets "out" to defaultValue instead. It reports
// whether the read was successful.
func (s *String) ReadOptionalASN1Boolean(out *bool, tag asn1.Tag, defaultValue bool) bool {
var present bool
var child String
if !s.ReadOptionalASN1(&child, &present, tag) {
return false
}
if !present {
*out = defaultValue
return true
}
return child.ReadASN1Boolean(out)
}
func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool {
if len(*s) < 2 {
return false
}
tag, lenByte := (*s)[0], (*s)[1]
if tag&0x1f == 0x1f {
// ITU-T X.690 section 8.1.2
//
// An identifier octet with a tag part of 0x1f indicates a high-tag-number
// form identifier with two or more octets. We only support tags less than
// 31 (i.e. low-tag-number form, single octet identifier).
return false
}
if outTag != nil {
*outTag = asn1.Tag(tag)
}
// ITU-T X.690 section 8.1.3
//
// Bit 8 of the first length byte indicates whether the length is short- or
// long-form.
var length, headerLen uint32 // length includes headerLen
if lenByte&0x80 == 0 {
// Short-form length (section 8.1.3.4), encoded in bits 1-7.
length = uint32(lenByte) + 2
headerLen = 2
} else {
// Long-form length (section 8.1.3.5). Bits 1-7 encode the number of octets
// used to encode the length.
lenLen := lenByte & 0x7f
var len32 uint32
if lenLen == 0 || lenLen > 4 || len(*s) < int(2+lenLen) {
return false
}
lenBytes := String((*s)[2 : 2+lenLen])
if !lenBytes.readUnsigned(&len32, int(lenLen)) {
return false
}
// ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
// with the minimum number of octets.
if len32 < 128 {
// Length should have used short-form encoding.
return false
}
if len32>>((lenLen-1)*8) == 0 {
// Leading octet is 0. Length should have been at least one byte shorter.
return false
}
headerLen = 2 + uint32(lenLen)
if headerLen+len32 < len32 {
// Overflow.
return false
}
length = headerLen + len32
}
if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) {
return false
}
if skipHeader && !out.Skip(int(headerLen)) {
panic("cryptobyte: internal error")
}
return true
}
+46
View File
@@ -0,0 +1,46 @@
// Copyright 2017 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 asn1 contains supporting types for parsing and building ASN.1
// messages with the cryptobyte package.
package asn1
// Tag represents an ASN.1 identifier octet, consisting of a tag number
// (indicating a type) and class (such as context-specific or constructed).
//
// Methods in the cryptobyte package only support the low-tag-number form, i.e.
// a single identifier octet with bits 7-8 encoding the class and bits 1-6
// encoding the tag number.
type Tag uint8
const (
classConstructed = 0x20
classContextSpecific = 0x80
)
// Constructed returns t with the constructed class bit set.
func (t Tag) Constructed() Tag { return t | classConstructed }
// ContextSpecific returns t with the context-specific class bit set.
func (t Tag) ContextSpecific() Tag { return t | classContextSpecific }
// The following is a list of standard tag and class combinations.
const (
BOOLEAN = Tag(1)
INTEGER = Tag(2)
BIT_STRING = Tag(3)
OCTET_STRING = Tag(4)
NULL = Tag(5)
OBJECT_IDENTIFIER = Tag(6)
ENUM = Tag(10)
UTF8String = Tag(12)
SEQUENCE = Tag(16 | classConstructed)
SET = Tag(17 | classConstructed)
PrintableString = Tag(19)
T61String = Tag(20)
IA5String = Tag(22)
UTCTime = Tag(23)
GeneralizedTime = Tag(24)
GeneralString = Tag(27)
)
+350
View File
@@ -0,0 +1,350 @@
// Copyright 2017 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 cryptobyte
import (
"errors"
"fmt"
)
// A Builder builds byte strings from fixed-length and length-prefixed values.
// Builders either allocate space as needed, or are fixed, which means that
// they write into a given buffer and produce an error if it's exhausted.
//
// The zero value is a usable Builder that allocates space as needed.
//
// Simple values are marshaled and appended to a Builder using methods on the
// Builder. Length-prefixed values are marshaled by providing a
// BuilderContinuation, which is a function that writes the inner contents of
// the value to a given Builder. See the documentation for BuilderContinuation
// for details.
type Builder struct {
err error
result []byte
fixedSize bool
child *Builder
offset int
pendingLenLen int
pendingIsASN1 bool
inContinuation *bool
}
// NewBuilder creates a Builder that appends its output to the given buffer.
// Like append(), the slice will be reallocated if its capacity is exceeded.
// Use Bytes to get the final buffer.
func NewBuilder(buffer []byte) *Builder {
return &Builder{
result: buffer,
}
}
// NewFixedBuilder creates a Builder that appends its output into the given
// buffer. This builder does not reallocate the output buffer. Writes that
// would exceed the buffer's capacity are treated as an error.
func NewFixedBuilder(buffer []byte) *Builder {
return &Builder{
result: buffer,
fixedSize: true,
}
}
// SetError sets the value to be returned as the error from Bytes. Writes
// performed after calling SetError are ignored.
func (b *Builder) SetError(err error) {
b.err = err
}
// Bytes returns the bytes written by the builder or an error if one has
// occurred during building.
func (b *Builder) Bytes() ([]byte, error) {
if b.err != nil {
return nil, b.err
}
return b.result[b.offset:], nil
}
// BytesOrPanic returns the bytes written by the builder or panics if an error
// has occurred during building.
func (b *Builder) BytesOrPanic() []byte {
if b.err != nil {
panic(b.err)
}
return b.result[b.offset:]
}
// AddUint8 appends an 8-bit value to the byte string.
func (b *Builder) AddUint8(v uint8) {
b.add(byte(v))
}
// AddUint16 appends a big-endian, 16-bit value to the byte string.
func (b *Builder) AddUint16(v uint16) {
b.add(byte(v>>8), byte(v))
}
// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest
// byte of the 32-bit input value is silently truncated.
func (b *Builder) AddUint24(v uint32) {
b.add(byte(v>>16), byte(v>>8), byte(v))
}
// AddUint32 appends a big-endian, 32-bit value to the byte string.
func (b *Builder) AddUint32(v uint32) {
b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
// AddUint48 appends a big-endian, 48-bit value to the byte string.
func (b *Builder) AddUint48(v uint64) {
b.add(byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
// AddUint64 appends a big-endian, 64-bit value to the byte string.
func (b *Builder) AddUint64(v uint64) {
b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
// AddBytes appends a sequence of bytes to the byte string.
func (b *Builder) AddBytes(v []byte) {
b.add(v...)
}
// BuilderContinuation is a continuation-passing interface for building
// length-prefixed byte sequences. Builder methods for length-prefixed
// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation
// supplied to them. The child builder passed to the continuation can be used
// to build the content of the length-prefixed sequence. For example:
//
// parent := cryptobyte.NewBuilder()
// parent.AddUint8LengthPrefixed(func (child *Builder) {
// child.AddUint8(42)
// child.AddUint8LengthPrefixed(func (grandchild *Builder) {
// grandchild.AddUint8(5)
// })
// })
//
// It is an error to write more bytes to the child than allowed by the reserved
// length prefix. After the continuation returns, the child must be considered
// invalid, i.e. users must not store any copies or references of the child
// that outlive the continuation.
//
// If the continuation panics with a value of type BuildError then the inner
// error will be returned as the error from Bytes. If the child panics
// otherwise then Bytes will repanic with the same value.
type BuilderContinuation func(child *Builder)
// BuildError wraps an error. If a BuilderContinuation panics with this value,
// the panic will be recovered and the inner error will be returned from
// Builder.Bytes.
type BuildError struct {
Err error
}
// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence.
func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) {
b.addLengthPrefixed(1, false, f)
}
// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence.
func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) {
b.addLengthPrefixed(2, false, f)
}
// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence.
func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) {
b.addLengthPrefixed(3, false, f)
}
// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence.
func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) {
b.addLengthPrefixed(4, false, f)
}
func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) {
if !*b.inContinuation {
*b.inContinuation = true
defer func() {
*b.inContinuation = false
r := recover()
if r == nil {
return
}
if buildError, ok := r.(BuildError); ok {
b.err = buildError.Err
} else {
panic(r)
}
}()
}
f(arg)
}
func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) {
// Subsequent writes can be ignored if the builder has encountered an error.
if b.err != nil {
return
}
offset := len(b.result)
b.add(make([]byte, lenLen)...)
if b.inContinuation == nil {
b.inContinuation = new(bool)
}
b.child = &Builder{
result: b.result,
fixedSize: b.fixedSize,
offset: offset,
pendingLenLen: lenLen,
pendingIsASN1: isASN1,
inContinuation: b.inContinuation,
}
b.callContinuation(f, b.child)
b.flushChild()
if b.child != nil {
panic("cryptobyte: internal error")
}
}
func (b *Builder) flushChild() {
if b.child == nil {
return
}
b.child.flushChild()
child := b.child
b.child = nil
if child.err != nil {
b.err = child.err
return
}
length := len(child.result) - child.pendingLenLen - child.offset
if length < 0 {
panic("cryptobyte: internal error") // result unexpectedly shrunk
}
if child.pendingIsASN1 {
// For ASN.1, we reserved a single byte for the length. If that turned out
// to be incorrect, we have to move the contents along in order to make
// space.
if child.pendingLenLen != 1 {
panic("cryptobyte: internal error")
}
var lenLen, lenByte uint8
if int64(length) > 0xfffffffe {
b.err = errors.New("pending ASN.1 child too long")
return
} else if length > 0xffffff {
lenLen = 5
lenByte = 0x80 | 4
} else if length > 0xffff {
lenLen = 4
lenByte = 0x80 | 3
} else if length > 0xff {
lenLen = 3
lenByte = 0x80 | 2
} else if length > 0x7f {
lenLen = 2
lenByte = 0x80 | 1
} else {
lenLen = 1
lenByte = uint8(length)
length = 0
}
// Insert the initial length byte, make space for successive length bytes,
// and adjust the offset.
child.result[child.offset] = lenByte
extraBytes := int(lenLen - 1)
if extraBytes != 0 {
child.add(make([]byte, extraBytes)...)
childStart := child.offset + child.pendingLenLen
copy(child.result[childStart+extraBytes:], child.result[childStart:])
}
child.offset++
child.pendingLenLen = extraBytes
}
l := length
for i := child.pendingLenLen - 1; i >= 0; i-- {
child.result[child.offset+i] = uint8(l)
l >>= 8
}
if l != 0 {
b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen)
return
}
if b.fixedSize && &b.result[0] != &child.result[0] {
panic("cryptobyte: BuilderContinuation reallocated a fixed-size buffer")
}
b.result = child.result
}
func (b *Builder) add(bytes ...byte) {
if b.err != nil {
return
}
if b.child != nil {
panic("cryptobyte: attempted write while child is pending")
}
if len(b.result)+len(bytes) < len(bytes) {
b.err = errors.New("cryptobyte: length overflow")
}
if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) {
b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer")
return
}
b.result = append(b.result, bytes...)
}
// Unwrite rolls back non-negative n bytes written directly to the Builder.
// An attempt by a child builder passed to a continuation to unwrite bytes
// from its parent will panic.
func (b *Builder) Unwrite(n int) {
if b.err != nil {
return
}
if b.child != nil {
panic("cryptobyte: attempted unwrite while child is pending")
}
length := len(b.result) - b.pendingLenLen - b.offset
if length < 0 {
panic("cryptobyte: internal error")
}
if n < 0 {
panic("cryptobyte: attempted to unwrite negative number of bytes")
}
if n > length {
panic("cryptobyte: attempted to unwrite more than was written")
}
b.result = b.result[:len(b.result)-n]
}
// A MarshalingValue marshals itself into a Builder.
type MarshalingValue interface {
// Marshal is called by Builder.AddValue. It receives a pointer to a builder
// to marshal itself into. It may return an error that occurred during
// marshaling, such as unset or invalid values.
Marshal(b *Builder) error
}
// AddValue calls Marshal on v, passing a pointer to the builder to append to.
// If Marshal returns an error, it is set on the Builder so that subsequent
// appends don't have an effect.
func (b *Builder) AddValue(v MarshalingValue) {
err := v.Marshal(b)
if err != nil {
b.err = err
}
}
+183
View File
@@ -0,0 +1,183 @@
// Copyright 2017 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 cryptobyte contains types that help with parsing and constructing
// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage
// contains useful ASN.1 constants.)
//
// The String type is for parsing. It wraps a []byte slice and provides helper
// functions for consuming structures, value by value.
//
// The Builder type is for constructing messages. It providers helper functions
// for appending values and also for appending length-prefixed submessages
// without having to worry about calculating the length prefix ahead of time.
//
// See the documentation and examples for the Builder and String types to get
// started.
package cryptobyte
// String represents a string of bytes. It provides methods for parsing
// fixed-length and length-prefixed values from it.
type String []byte
// read advances a String by n bytes and returns them. If less than n bytes
// remain, it returns nil.
func (s *String) read(n int) []byte {
if len(*s) < n || n < 0 {
return nil
}
v := (*s)[:n]
*s = (*s)[n:]
return v
}
// Skip advances the String by n byte and reports whether it was successful.
func (s *String) Skip(n int) bool {
return s.read(n) != nil
}
// ReadUint8 decodes an 8-bit value into out and advances over it.
// It reports whether the read was successful.
func (s *String) ReadUint8(out *uint8) bool {
v := s.read(1)
if v == nil {
return false
}
*out = uint8(v[0])
return true
}
// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it.
// It reports whether the read was successful.
func (s *String) ReadUint16(out *uint16) bool {
v := s.read(2)
if v == nil {
return false
}
*out = uint16(v[0])<<8 | uint16(v[1])
return true
}
// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it.
// It reports whether the read was successful.
func (s *String) ReadUint24(out *uint32) bool {
v := s.read(3)
if v == nil {
return false
}
*out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2])
return true
}
// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it.
// It reports whether the read was successful.
func (s *String) ReadUint32(out *uint32) bool {
v := s.read(4)
if v == nil {
return false
}
*out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3])
return true
}
// ReadUint48 decodes a big-endian, 48-bit value into out and advances over it.
// It reports whether the read was successful.
func (s *String) ReadUint48(out *uint64) bool {
v := s.read(6)
if v == nil {
return false
}
*out = uint64(v[0])<<40 | uint64(v[1])<<32 | uint64(v[2])<<24 | uint64(v[3])<<16 | uint64(v[4])<<8 | uint64(v[5])
return true
}
// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it.
// It reports whether the read was successful.
func (s *String) ReadUint64(out *uint64) bool {
v := s.read(8)
if v == nil {
return false
}
*out = uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7])
return true
}
func (s *String) readUnsigned(out *uint32, length int) bool {
v := s.read(length)
if v == nil {
return false
}
var result uint32
for i := 0; i < length; i++ {
result <<= 8
result |= uint32(v[i])
}
*out = result
return true
}
func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
lenBytes := s.read(lenLen)
if lenBytes == nil {
return false
}
var length uint32
for _, b := range lenBytes {
length = length << 8
length = length | uint32(b)
}
v := s.read(int(length))
if v == nil {
return false
}
*outChild = v
return true
}
// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value
// into out and advances over it. It reports whether the read was successful.
func (s *String) ReadUint8LengthPrefixed(out *String) bool {
return s.readLengthPrefixed(1, out)
}
// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit
// length-prefixed value into out and advances over it. It reports whether the
// read was successful.
func (s *String) ReadUint16LengthPrefixed(out *String) bool {
return s.readLengthPrefixed(2, out)
}
// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit
// length-prefixed value into out and advances over it. It reports whether
// the read was successful.
func (s *String) ReadUint24LengthPrefixed(out *String) bool {
return s.readLengthPrefixed(3, out)
}
// ReadBytes reads n bytes into out and advances over them. It reports
// whether the read was successful.
func (s *String) ReadBytes(out *[]byte, n int) bool {
v := s.read(n)
if v == nil {
return false
}
*out = v
return true
}
// CopyBytes copies len(out) bytes into out and advances over them. It reports
// whether the copy operation was successful
func (s *String) CopyBytes(out []byte) bool {
n := len(out)
v := s.read(n)
if v == nil {
return false
}
return copy(out, v) == n
}
// Empty reports whether the string does not contain any bytes.
func (s String) Empty() bool {
return len(s) == 0
}
+4 -1
View File
@@ -634,7 +634,10 @@ func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (boo
drain: drain:
for { for {
select { select {
case <-ch.msg: case _, ok := <-ch.msg:
if !ok {
break drain
}
default: default:
break drain break drain
} }
+85
View File
@@ -88,6 +88,32 @@ func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
} }
// NewControlClientConn establishes an SSH connection over an OpenSSH
// ControlMaster socket c in proxy mode.
//
// Note that this package only implements the client side of the multiplexing
// protocol. The provided net.Conn must be a local, secure connection (such as a
// Unix domain socket) connected to an already-running OpenSSH process acting as
// the ControlMaster.
//
// WARNING: Because proxy mode bypasses the standard cryptographic handshake
// passing a standard network connection (e.g., TCP) will result in plaintext
// data leakage.
//
// The Request and NewChannel channels must be serviced or the connection
// will hang.
func NewControlClientConn(c net.Conn) (Conn, <-chan NewChannel, <-chan *Request, error) {
conn := &connection{
sshConn: sshConn{conn: c},
}
var err error
if conn.transport, err = handshakeControlProxy(c); err != nil {
return nil, nil, nil, fmt.Errorf("ssh: control proxy handshake failed: %w", err)
}
conn.mux = newMux(conn.transport)
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
}
// clientHandshake performs the client side key exchange. See RFC 4253 Section // clientHandshake performs the client side key exchange. See RFC 4253 Section
// 7. // 7.
func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error {
@@ -197,6 +223,59 @@ type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
// the server. A BannerCallback receives the message sent by the remote server. // the server. A BannerCallback receives the message sent by the remote server.
type BannerCallback func(message string) error type BannerCallback func(message string) error
// ClientAuthContext contains information about the current state of the
// authentication process, passed to [ClientAuthCallback].
type ClientAuthContext struct {
// Metadata contains the connection metadata.
Metadata ConnMetadata
// Algorithms contains the negotiated algorithms.
Algorithms NegotiatedAlgorithms
// AllowedMethods lists the authentication methods currently accepted
// by the server. These are the protocol-level names defined in RFC 4252
// such as "publickey", "password".
AllowedMethods []string
// PartialSuccessMethods lists the authentication methods that have already
// succeeded, indicating a multi-step authentication flow. This list
// represents the exact sequence of partial successes and may contain
// duplicates if the same method succeeded multiple times.
PartialSuccessMethods []string
// TriedMethods lists the methods that have already been attempted and
// failed during this session. This list represents the exact sequence of
// failures and may contain duplicates. This allows the callback to also
// track the number of failed attempts for a specific method.
TriedMethods []string
}
// ClientAuthCallback is a hook invoked before each authentication attempt. It
// allows the client to dynamically select an authentication method based on the
// current context, server capabilities, or previous failures.
//
// The callback is invoked after the initial "none" authentication method, once
// the server's supported authentication methods are known.
//
// Return values:
// - (AuthMethod, nil): The client will attempt this specific method next.
// The returned method does NOT need to be present in [ClientConfig.Auth].
// This allows for dynamic authentication strategies (e.g., prompting
// for a password only if public key auth fails). Callers should inspect
// [ClientAuthContext.TriedMethods] to avoid repeatedly returning the
// same failing method.
// - (nil, nil): The client selects from [ClientConfig.Auth] the first
// instance of a method that has not been tried yet, or aborts if none
// are left. If authentication is not successful, the callback is invoked
// again before the following attempt.
// - (nil, error): The authentication process is aborted immediately,
// causing the ongoing SSH handshake to fail with the provided error.
//
// To bound resource use, the client caps the total number of authentication
// attempts (failures and partial successes combined) at 64. If the cap is
// exceeded the handshake aborts with an error.
type ClientAuthCallback func(ctx *ClientAuthContext) (AuthMethod, error)
// A ClientConfig structure is used to configure a Client. It must not be // A ClientConfig structure is used to configure a Client. It must not be
// modified after having been passed to an SSH function. // modified after having been passed to an SSH function.
type ClientConfig struct { type ClientConfig struct {
@@ -210,6 +289,9 @@ type ClientConfig struct {
// Auth contains possible authentication methods to use with the // Auth contains possible authentication methods to use with the
// server. Only the first instance of a particular RFC 4252 method will // server. Only the first instance of a particular RFC 4252 method will
// be used during authentication. // be used during authentication.
//
// If AuthCallback is set, these AuthMethod are only used if the
// callback returns nil.
Auth []AuthMethod Auth []AuthMethod
// HostKeyCallback is called during the cryptographic // HostKeyCallback is called during the cryptographic
@@ -240,6 +322,9 @@ type ClientConfig struct {
// //
// A Timeout of zero means no timeout. // A Timeout of zero means no timeout.
Timeout time.Duration Timeout time.Duration
// AuthCallback, if non-nil, is invoked before each authentication attempt.
AuthCallback ClientAuthCallback
} }
// InsecureIgnoreHostKey returns a function that can be used for // InsecureIgnoreHostKey returns a function that can be used for
+49 -13
View File
@@ -21,6 +21,12 @@ const (
authSuccess authSuccess
) )
// maxAuthClientTried bounds the total number of authentication attempts
// (failures and partial successes combined) the client makes before
// aborting the loop, to prevent unbounded growth when an AuthCallback
// keeps supplying methods.
const maxAuthClientTried = 64
// clientAuthenticate authenticates with the remote server. See RFC 4252. // clientAuthenticate authenticates with the remote server. See RFC 4252.
func (c *connection) clientAuthenticate(config *ClientConfig) error { func (c *connection) clientAuthenticate(config *ClientConfig) error {
// initiate user auth session // initiate user auth session
@@ -67,32 +73,62 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
// then any untried methods suggested by the server. // then any untried methods suggested by the server.
var tried []string var tried []string
var lastMethods []string var lastMethods []string
var partialSuccess []string
sessionID := c.transport.getSessionID() sessionID := c.transport.getSessionID()
for auth := AuthMethod(new(noneAuth)); auth != nil; { for auth := AuthMethod(new(noneAuth)); auth != nil; {
ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions) ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions)
if err != nil { if err != nil {
// On disconnect, return error immediately // On disconnect, return error immediately
if _, ok := err.(*disconnectMsg); ok { if _, isDisconnect := err.(*disconnectMsg); isDisconnect {
return err return err
} }
// We return the error later if there is no other method left to // We return the error later if there is no other method
// try. // left to try.
ok = authFailure ok = authFailure
} }
if ok == authSuccess {
// success switch ok {
case authSuccess:
return nil return nil
} else if ok == authFailure { case authPartialSuccess:
if m := auth.method(); !slices.Contains(tried, m) { partialSuccess = append(partialSuccess, auth.method())
tried = append(tried, m) case authFailure:
tried = append(tried, auth.method())
} }
if len(partialSuccess)+len(tried) > maxAuthClientTried {
return fmt.Errorf("ssh: too many authentication attempts (%d), aborting",
len(partialSuccess)+len(tried))
} }
if methods == nil { if methods == nil {
methods = lastMethods methods = lastMethods
} }
lastMethods = methods lastMethods = methods
// If AuthCallback is set it takes precedence: it picks the next
// AuthMethod dynamically. The returned method need not be in
// config.Auth. If the callback returns (nil, nil) we fall back to
// selecting the next untried method from config.Auth below; on
// (nil, error) the handshake aborts.
if config.AuthCallback != nil {
ctx := &ClientAuthContext{
Metadata: c,
Algorithms: c.Algorithms(),
AllowedMethods: slices.Clone(methods),
PartialSuccessMethods: slices.Clone(partialSuccess),
TriedMethods: slices.Clone(tried),
}
altAuth, cbErr := config.AuthCallback(ctx)
if cbErr != nil {
return cbErr
}
if altAuth != nil {
auth = altAuth
continue
}
}
auth = nil auth = nil
findNext: findNext:
@@ -377,11 +413,11 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
return authFailure, nil, err return authFailure, nil, err
} }
// If authentication succeeds or the list of available methods does not // If authentication succeeds or partially succeeds, return immediately
// contain the "publickey" method, do not attempt to authenticate with any // so the caller can select the next auth method. According to RFC 4252
// other keys. According to RFC 4252 Section 7, the latter can occur when // Section 7, if the server no longer lists "publickey" among its
// additional authentication methods are required. // allowed methods, do not attempt to authenticate with any other keys.
if success == authSuccess || !slices.Contains(methods, cb.method()) { if success == authSuccess || success == authPartialSuccess || !slices.Contains(methods, cb.method()) {
return success, methods, err return success, methods, err
} }
} }
+9 -1
View File
@@ -91,9 +91,17 @@ func DiscardRequests(in <-chan *Request) {
} }
} }
// A connTransport represents the transport for a connection.
type connTransport interface {
packetConn
getAlgorithms() NegotiatedAlgorithms
getSessionID() []byte
waitSession() error
}
// A connection represents an incoming connection. // A connection represents an incoming connection.
type connection struct { type connection struct {
transport *handshakeTransport transport connTransport
sshConn sshConn
// The connection protocol. // The connection protocol.
+155
View File
@@ -0,0 +1,155 @@
// 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 ssh
import (
"encoding/binary"
"errors"
"fmt"
"io"
"golang.org/x/crypto/cryptobyte"
)
const (
muxProtocolVersion = 4
muxMsgHello = 0x00000001
muxCProxy = 0x1000000f
muxSProxy = 0x8000000f
)
const controlProxyRequestID = 0
// handshakeControlProxy attempts to establish a transport connection with an
// OpenSSH ControlMaster socket in proxy mode. For details see:
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.mux
func handshakeControlProxy(rw io.ReadWriteCloser) (connTransport, error) {
if err := controlProxyWritePacket(rw, func(b *cryptobyte.Builder) {
b.AddUint32(muxMsgHello)
b.AddUint32(muxProtocolVersion)
}); err != nil {
return nil, fmt.Errorf("mux hello write failed: %w", err)
}
if err := controlProxyWritePacket(rw, func(b *cryptobyte.Builder) {
b.AddUint32(muxCProxy)
b.AddUint32(controlProxyRequestID)
}); err != nil {
return nil, fmt.Errorf("mux client proxy write failed: %w", err)
}
messageType, body, err := controlProxyReadMessage(rw)
if err != nil {
return nil, fmt.Errorf("mux hello read failed: %w", err)
}
if messageType != muxMsgHello {
return nil, fmt.Errorf("expected hello response, got %v", messageType)
}
var v uint32
if !body.ReadUint32(&v) {
return nil, errors.New("EOF reading mux protocol version")
}
if v != muxProtocolVersion {
return nil, fmt.Errorf("mux server has unsupported version %v", v)
}
messageType, body, err = controlProxyReadMessage(rw)
if err != nil {
return nil, fmt.Errorf("mux server proxy read failed: %w", err)
}
if messageType != muxSProxy {
return nil, fmt.Errorf("expected server proxy response, got %v", messageType)
}
var reqID uint32
if !body.ReadUint32(&reqID) {
return nil, errors.New("EOF reading request id")
}
if reqID != controlProxyRequestID {
return nil, fmt.Errorf("expected request id %v, got %v", controlProxyRequestID, reqID)
}
return &controlProxyTransport{rw}, nil
}
// controlProxyTransport implements the connTransport interface for
// ControlMaster connections. Each controlMessage has zero length padding and
// no MAC.
type controlProxyTransport struct {
rw io.ReadWriteCloser
}
func (p *controlProxyTransport) Close() error {
return p.rw.Close()
}
func (p *controlProxyTransport) writePacket(controlMessage []byte) error {
return controlProxyWritePacket(p.rw, func(b *cryptobyte.Builder) {
b.AddUint8(0) // Padding length.
b.AddBytes(controlMessage)
})
}
func (p *controlProxyTransport) readPacket() ([]byte, error) {
buf, err := controlProxyReadPacket(p.rw)
if err != nil {
return nil, fmt.Errorf("ssh: error reading control message: %w", err)
}
// Discard the padding length.
if len(buf) < 1 {
return nil, errors.New("ssh: EOF reading padding length")
}
if buf[0] != 0 {
return nil, errors.New("ssh: unexpected non-zero padding in control message")
}
return buf[1:], nil
}
func (p *controlProxyTransport) getAlgorithms() NegotiatedAlgorithms {
return NegotiatedAlgorithms{}
}
func (p *controlProxyTransport) getSessionID() []byte {
return nil
}
func (p *controlProxyTransport) waitSession() error {
return nil
}
func controlProxyWritePacket(w io.Writer, f cryptobyte.BuilderContinuation) error {
var buf []byte
b := cryptobyte.NewBuilder(buf)
b.AddUint32LengthPrefixed(f)
out, err := b.Bytes()
if err != nil {
return err
}
_, err = w.Write(out)
return err
}
func controlProxyReadPacket(r io.Reader) (cryptobyte.String, error) {
var l uint32
if err := binary.Read(r, binary.BigEndian, &l); err != nil {
return nil, err
}
if l > maxPacket {
return nil, fmt.Errorf("message length %v exceeds maximum %v", l, maxPacket)
}
buf := make([]byte, l)
if _, err := io.ReadFull(r, buf); err != nil {
return nil, err
}
return buf, nil
}
func controlProxyReadMessage(r io.Reader) (messageType uint32, body cryptobyte.String, err error) {
body, err = controlProxyReadPacket(r)
if err != nil {
return 0, nil, fmt.Errorf("error reading message body: %w", err)
}
if !body.ReadUint32(&messageType) {
return 0, nil, errors.New("EOF reading message type")
}
return messageType, body, nil
}
+66 -9
View File
@@ -16,6 +16,7 @@ import (
"io" "io"
"math/big" "math/big"
"slices" "slices"
"sync"
"golang.org/x/crypto/curve25519" "golang.org/x/crypto/curve25519"
) )
@@ -718,15 +719,9 @@ func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshak
kexDHGexRequest.MaxBits, kexDHGexRequest.PreferredBits) kexDHGexRequest.MaxBits, kexDHGexRequest.PreferredBits)
} }
var p *big.Int p, err := chooseDH(kexDHGexRequest)
// We hardcode sending Oakley Group 14 (2048 bits), Oakley Group 15 (3072 if err != nil {
// bits) or Oakley Group 16 (4096 bits), based on the requested max size. return nil, err
if kexDHGexRequest.MaxBits < 3072 {
p, _ = new(big.Int).SetString(oakleyGroup14, 16)
} else if kexDHGexRequest.MaxBits < 4096 {
p, _ = new(big.Int).SetString(oakleyGroup15, 16)
} else {
p, _ = new(big.Int).SetString(oakleyGroup16, 16)
} }
g := big.NewInt(2) g := big.NewInt(2)
@@ -805,3 +800,65 @@ func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshak
Hash: gex.hashFunc, Hash: gex.hashFunc,
}, err }, err
} }
type dhKEXGroup struct {
size int
p *big.Int
}
// supportedDHKEXGroups returns the DH groups the server is willing to offer
// for diffie-hellman-group-exchange-* key exchanges. The list is built lazily
// on first use to keep the hex-to-big.Int parse out of package initialization.
var supportedDHKEXGroups = sync.OnceValue(func() []dhKEXGroup {
specs := []struct {
size int
hex string
}{
{2048, oakleyGroup14},
{3072, oakleyGroup15},
{4096, oakleyGroup16},
}
out := make([]dhKEXGroup, 0, len(specs))
for _, s := range specs {
p, _ := new(big.Int).SetString(s.hex, 16)
out = append(out, dhKEXGroup{size: s.size, p: p})
}
return out
})
// chooseDH picks a DH group for the given client request, mirroring the
// algorithm used by OpenSSH's choose_dh in dh.c: prefer the smallest known
// group larger than or equal to the client's PreferredBits, and otherwise pick
// the largest group within the accepted [MinBits, MaxBits] range.
func chooseDH(req kexDHGexRequestMsg) (*big.Int, error) {
var best *big.Int
bestSize := 0
wantBits := int(req.PreferredBits)
for _, group := range supportedDHKEXGroups() {
if uint32(group.size) < req.MinBits || uint32(group.size) > req.MaxBits {
continue
}
if bestSize == 0 {
best = group.p
bestSize = group.size
continue
}
closerFromAbove := group.size >= wantBits && group.size < bestSize
closerFromBelow := group.size > bestSize && bestSize < wantBits
if closerFromAbove || closerFromBelow {
best = group.p
bestSize = group.size
}
}
if bestSize == 0 {
return nil, fmt.Errorf("ssh: no suitable DH group found for request min: %d, preferred: %d, max: %d",
req.MinBits, req.PreferredBits, req.MaxBits)
}
return best, nil
}
+38 -3
View File
@@ -76,7 +76,7 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
case InsecureKeyAlgoDSA: case InsecureKeyAlgoDSA:
return parseDSA(in) return parseDSA(in)
case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
return parseECDSA(in) return parseECDSA(in, algo)
case KeyAlgoSKECDSA256: case KeyAlgoSKECDSA256:
return parseSKECDSA(in) return parseSKECDSA(in)
case KeyAlgoED25519: case KeyAlgoED25519:
@@ -806,7 +806,7 @@ func supportedEllipticCurve(curve elliptic.Curve) bool {
} }
// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { func parseECDSA(in []byte, expectedType string) (out PublicKey, rest []byte, err error) {
var w struct { var w struct {
Curve string Curve string
KeyBytes []byte KeyBytes []byte
@@ -817,6 +817,12 @@ func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
return nil, nil, err return nil, nil, err
} }
actualType := "ecdsa-sha2-" + w.Curve
if expectedType != actualType {
return nil, nil, fmt.Errorf("ssh: algorithm type mismatch: expected %q, found curve %q (type %q)",
expectedType, w.Curve, actualType)
}
key := new(ecdsa.PublicKey) key := new(ecdsa.PublicKey)
switch w.Curve { switch w.Curve {
@@ -1466,6 +1472,17 @@ func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc {
return nil, err return nil, err
} }
// OpenSSH does not impose an upper bound on the bcrypt round count
// stored in the key file, but bcrypt_pbkdf cost is linear in rounds:
// the default is 16, ssh-keygen lets users pick anything up to
// INT_MAX. Cap at 2048 (128x the default, a few seconds of CPU) so
// that an oversized value in the file cannot tie up the caller for
// months.
const maxRounds = 1 << 11
if opts.Rounds > maxRounds {
return nil, fmt.Errorf("ssh: bcrypt KDF rounds %d exceed maximum %d", opts.Rounds, maxRounds)
}
k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16) k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -1635,10 +1652,28 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
return nil, err return nil, err
} }
// Mirror the validation done in parseRSA for public keys: cap the
// modulus at the same limit enforced by crypto/tls, reject oversized
// or invalid exponents, and additionally bound the prime factors to
// avoid the expensive CRT coefficient recomputation in pk.Precompute.
if key.N.BitLen() > 8192 {
return nil, errors.New("ssh: rsa modulus too large")
}
if key.P.BitLen() > 4096 || key.Q.BitLen() > 4096 {
return nil, errors.New("ssh: rsa prime too large")
}
if key.E.BitLen() > 24 {
return nil, errors.New("ssh: exponent too large")
}
e := key.E.Int64()
if e < 3 || e&1 == 0 {
return nil, errors.New("ssh: incorrect exponent")
}
pk := &rsa.PrivateKey{ pk := &rsa.PrivateKey{
PublicKey: rsa.PublicKey{ PublicKey: rsa.PublicKey{
N: key.N, N: key.N,
E: int(key.E.Int64()), E: int(e),
}, },
D: key.D, D: key.D,
Primes: []*big.Int{key.P, key.Q}, Primes: []*big.Int{key.P, key.Q},
+4 -1
View File
@@ -155,7 +155,10 @@ func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []
drain: drain:
for { for {
select { select {
case <-m.globalResponses: case _, ok := <-m.globalResponses:
if !ok {
break drain
}
default: default:
break drain break drain
} }
+33 -5
View File
@@ -54,6 +54,9 @@ type Permissions struct {
ExtraData map[any]any ExtraData map[any]any
} }
// GSSAPIWithMICConfig includes the server callbacks for gssapi-with-mic
// authentication. If either field is nil, gssapi-with-mic is considered not
// configured.
type GSSAPIWithMICConfig struct { type GSSAPIWithMICConfig struct {
// AllowLogin, must be set, is called when gssapi-with-mic // AllowLogin, must be set, is called when gssapi-with-mic
// authentication is selected (RFC 4462 section 3). The srcName is from the // authentication is selected (RFC 4462 section 3). The srcName is from the
@@ -68,6 +71,10 @@ type GSSAPIWithMICConfig struct {
Server GSSAPIServer Server GSSAPIServer
} }
func gssapiWithMICConfigured(config *GSSAPIWithMICConfig) bool {
return config != nil && config.AllowLogin != nil && config.Server != nil
}
// SendAuthBanner implements [ServerPreAuthConn]. // SendAuthBanner implements [ServerPreAuthConn].
func (s *connection) SendAuthBanner(msg string) error { func (s *connection) SendAuthBanner(msg string) error {
return s.transport.writePacket(Marshal(&userAuthBannerMsg{ return s.transport.writePacket(Marshal(&userAuthBannerMsg{
@@ -382,8 +389,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
} }
if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil &&
config.KeyboardInteractiveCallback == nil && (config.GSSAPIWithMICConfig == nil || config.KeyboardInteractiveCallback == nil && !gssapiWithMICConfigured(config.GSSAPIWithMICConfig) {
config.GSSAPIWithMICConfig.AllowLogin == nil || config.GSSAPIWithMICConfig.Server == nil) {
return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
} }
@@ -607,6 +613,15 @@ func (b *BannerError) Error() string {
return b.Err.Error() return b.Err.Error()
} }
// maxAuthServerAttempts caps the total number of SSH_MSG_USERAUTH_REQUEST
// messages the server will process on a single connection, regardless of
// outcome (failure, partial success, public key query, or none). It is a
// backstop against clients that drive the authentication loop indefinitely
// without ever incurring a real failure — for example by repeatedly
// triggering PartialSuccessError or by spamming public key offer queries —
// neither of which increment the MaxAuthTries failure counter.
const maxAuthServerAttempts = 128
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
if config.PreAuthConnCallback != nil { if config.PreAuthConnCallback != nil {
config.PreAuthConnCallback(s) config.PreAuthConnCallback(s)
@@ -617,6 +632,7 @@ func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, err
var perms *Permissions var perms *Permissions
authFailures := 0 authFailures := 0
authAttempts := 0
noneAuthCount := 0 noneAuthCount := 0
var authErrs []error var authErrs []error
var calledBannerCallback bool var calledBannerCallback bool
@@ -645,6 +661,19 @@ userAuthLoop:
return nil, &ServerAuthError{Errors: authErrs} return nil, &ServerAuthError{Errors: authErrs}
} }
if authAttempts >= maxAuthServerAttempts {
discMsg := &disconnectMsg{
Reason: 2,
Message: "too many authentication attempts",
}
if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
return nil, err
}
authErrs = append(authErrs, discMsg)
return nil, &ServerAuthError{Errors: authErrs}
}
authAttempts++
var userAuthReq userAuthRequestMsg var userAuthReq userAuthRequestMsg
if packet, err := s.transport.readPacket(); err != nil { if packet, err := s.transport.readPacket(); err != nil {
if err == io.EOF { if err == io.EOF {
@@ -846,7 +875,7 @@ userAuthLoop:
} }
} }
case "gssapi-with-mic": case "gssapi-with-mic":
if authConfig.GSSAPIWithMICConfig == nil { if !gssapiWithMICConfigured(authConfig.GSSAPIWithMICConfig) {
authErr = errors.New("ssh: gssapi-with-mic auth not configured") authErr = errors.New("ssh: gssapi-with-mic auth not configured")
break break
} }
@@ -979,8 +1008,7 @@ userAuthLoop:
if authConfig.KeyboardInteractiveCallback != nil { if authConfig.KeyboardInteractiveCallback != nil {
failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
} }
if authConfig.GSSAPIWithMICConfig != nil && authConfig.GSSAPIWithMICConfig.Server != nil && if gssapiWithMICConfigured(authConfig.GSSAPIWithMICConfig) {
authConfig.GSSAPIWithMICConfig.AllowLogin != nil {
failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic") failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic")
} }
+3
View File
@@ -423,6 +423,9 @@ func (s *Session) wait(reqs <-chan *Request) error {
for msg := range reqs { for msg := range reqs {
switch msg.Type { switch msg.Type {
case "exit-status": case "exit-status":
if len(msg.Payload) < 4 {
return errors.New("ssh: malformed exit-status request")
}
wm.status = int(binary.BigEndian.Uint32(msg.Payload)) wm.status = int(binary.BigEndian.Uint32(msg.Payload))
case "exit-signal": case "exit-signal":
var sigval struct { var sigval struct {
+3 -5
View File
@@ -9,6 +9,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"slices"
"strconv" "strconv"
"strings" "strings"
"unicode" "unicode"
@@ -105,8 +106,7 @@ func (x *FileSyntax) addLine(hint Expr, tokens ...string) *Line {
if hint == nil { if hint == nil {
// If no hint given, add to the last statement of the given type. // If no hint given, add to the last statement of the given type.
Loop: Loop:
for i := len(x.Stmt) - 1; i >= 0; i-- { for _, stmt := range slices.Backward(x.Stmt) {
stmt := x.Stmt[i]
switch stmt := stmt.(type) { switch stmt := stmt.(type) {
case *Line: case *Line:
if stmt.Token != nil && stmt.Token[0] == tokens[0] { if stmt.Token != nil && stmt.Token[0] == tokens[0] {
@@ -718,9 +718,7 @@ func (in *input) assignComments() {
} }
// Assign suffix comments to syntax immediately before. // Assign suffix comments to syntax immediately before.
for i := len(in.post) - 1; i >= 0; i-- { for _, x := range slices.Backward(in.post) {
x := in.post[i]
start, end := x.Span() start, end := x.Span()
if debug { if debug {
fmt.Fprintf(os.Stderr, "post %T :%d:%d #%d :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte, end.Line, end.LineRune, end.Byte) fmt.Fprintf(os.Stderr, "post %T :%d:%d #%d :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte, end.Line, end.LineRune, end.Byte)
+55 -8
View File
@@ -327,6 +327,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parse
} }
var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?([a-z]+[0-9]+)?$`) var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?([a-z]+[0-9]+)?$`)
var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`) var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`)
// Toolchains must be named beginning with `go1`, // Toolchains must be named beginning with `go1`,
@@ -1272,6 +1273,17 @@ func (f *File) SetRequire(req []*Require) {
// SetRequireSeparateIndirect will split it into a direct-only and indirect-only // SetRequireSeparateIndirect will split it into a direct-only and indirect-only
// block. This aids in the transition to separate blocks. // block. This aids in the transition to separate blocks.
func (f *File) SetRequireSeparateIndirect(req []*Require) { func (f *File) SetRequireSeparateIndirect(req []*Require) {
f.setRequireSeparateIndirect(req, false)
}
// SetRequireAtMostTwo is like SetRequireSeparateIndirect but it aggressively
// consolidates all requirements into at most two blocks (one direct, one indirect).
// It ignores existing blocks and comments when deciding where to place requirements.
func (f *File) SetRequireAtMostTwo(req []*Require) {
f.setRequireSeparateIndirect(req, true)
}
func (f *File) setRequireSeparateIndirect(req []*Require, simplify bool) {
// hasComments returns whether a line or block has comments // hasComments returns whether a line or block has comments
// other than "indirect". // other than "indirect".
hasComments := func(c Comments) bool { hasComments := func(c Comments) bool {
@@ -1304,6 +1316,17 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
} }
// Examine existing require lines and blocks. // Examine existing require lines and blocks.
need := make(map[string]*Require)
for _, r := range req {
need[r.Mod.Path] = r
}
lineIndirect := make(map[*Line]bool)
for _, r := range f.Require {
if n := need[r.Mod.Path]; n != nil {
lineIndirect[r.Syntax] = n.Indirect
}
}
var ( var (
// We may insert new requirements into the last uncommented // We may insert new requirements into the last uncommented
// direct-only and indirect-only blocks. We may also move requirements // direct-only and indirect-only blocks. We may also move requirements
@@ -1322,6 +1345,8 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
// Track the block each requirement belongs to (if any) so we can // Track the block each requirement belongs to (if any) so we can
// move them later. // move them later.
lineToBlock = make(map[*Line]*LineBlock) lineToBlock = make(map[*Line]*LineBlock)
directBlockComments []Comment
indirectBlockComments []Comment
) )
for i, stmt := range f.Syntax.Stmt { for i, stmt := range f.Syntax.Stmt {
switch stmt := stmt.(type) { switch stmt := stmt.(type) {
@@ -1364,6 +1389,24 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
if allIndirect { if allIndirect {
lastIndirectIndex = i lastIndirectIndex = i
} }
if simplify {
anyDirect := false
for _, line := range stmt.Line {
if ind, ok := lineIndirect[line]; ok && !ind {
anyDirect = true
break
}
}
target := &directBlockComments
if !anyDirect && len(stmt.Line) > 0 {
target = &indirectBlockComments
}
if len(*target) > 0 && len(stmt.Comments.Before) > 0 {
*target = append(*target, Comment{Token: "//"})
}
*target = append(*target, stmt.Comments.Before...)
stmt.Comments.Before = nil
}
} }
} }
@@ -1422,6 +1465,15 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
lastIndirectBlock = ensureBlock(lastIndirectIndex) lastIndirectBlock = ensureBlock(lastIndirectIndex)
} }
if simplify {
if len(directBlockComments) > 0 {
lastDirectBlock.Comments.Before = append(lastDirectBlock.Comments.Before, directBlockComments...)
}
if len(indirectBlockComments) > 0 {
lastIndirectBlock.Comments.Before = append(lastIndirectBlock.Comments.Before, indirectBlockComments...)
}
}
// Delete requirements we don't want anymore. // Delete requirements we don't want anymore.
// Update versions and indirect comments on requirements we want to keep. // Update versions and indirect comments on requirements we want to keep.
// If a requirement is in last{Direct,Indirect}Block with the wrong // If a requirement is in last{Direct,Indirect}Block with the wrong
@@ -1430,10 +1482,6 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
// correct block. // correct block.
// //
// Some blocks may be empty after this. Cleanup will remove them. // Some blocks may be empty after this. Cleanup will remove them.
need := make(map[string]*Require)
for _, r := range req {
need[r.Mod.Path] = r
}
have := make(map[string]*Require) have := make(map[string]*Require)
for _, r := range f.Require { for _, r := range f.Require {
path := r.Mod.Path path := r.Mod.Path
@@ -1446,10 +1494,10 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
r.setVersion(need[path].Mod.Version) r.setVersion(need[path].Mod.Version)
r.setIndirect(need[path].Indirect) r.setIndirect(need[path].Indirect)
if need[path].Indirect && if need[path].Indirect &&
(oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastDirectBlock) { (simplify || oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastDirectBlock) {
moveReq(r, lastIndirectBlock) moveReq(r, lastIndirectBlock)
} else if !need[path].Indirect && } else if !need[path].Indirect &&
(oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastIndirectBlock) { (simplify || oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastIndirectBlock) {
moveReq(r, lastDirectBlock) moveReq(r, lastDirectBlock)
} }
} }
@@ -1736,8 +1784,7 @@ func removeDups(syntax *FileSyntax, exclude *[]*Exclude, replace *[]*Replace, to
// Remove duplicate replacements. // Remove duplicate replacements.
// Later replacements take priority over earlier ones. // Later replacements take priority over earlier ones.
haveReplace := make(map[module.Version]bool) haveReplace := make(map[module.Version]bool)
for i := len(*replace) - 1; i >= 0; i-- { for _, x := range slices.Backward(*replace) {
x := (*replace)[i]
if haveReplace[x.Old] { if haveReplace[x.Old] {
kill[x.Syntax] = true kill[x.Syntax] = true
continue continue
+16
View File
@@ -10,9 +10,11 @@ package http2
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"net" "net"
"net/http" "net/http"
"slices"
"sync" "sync"
"time" "time"
) )
@@ -44,6 +46,20 @@ func configureServer(s *http.Server, conf *Server) error {
h2.IdleTimeout = h1.ReadTimeout h2.IdleTimeout = h1.ReadTimeout
} }
} }
// Register h2 and http/1.1 ALPN protocols on s.TLSConfig, matching
// the pre-wrapping implementation in server.go, so that TLS listeners
// built from s.TLSConfig still negotiate HTTP/2.
if s.TLSConfig == nil {
s.TLSConfig = new(tls.Config)
}
if !slices.Contains(s.TLSConfig.NextProtos, NextProtoTLS) {
s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS)
}
if !slices.Contains(s.TLSConfig.NextProtos, "http/1.1") {
s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, "http/1.1")
}
conf.state = &serverInternalState{ conf.state = &serverInternalState{
s1: s, s1: s,
} }
+13 -2
View File
@@ -22,8 +22,8 @@ import (
) )
func configureTransport(t1 *http.Transport) error { func configureTransport(t1 *http.Transport) error {
// ConfigureTransport is a no-op: The http.Transport already supports HTTP/2. _, err := configureTransports(t1)
return nil return err
} }
func configureTransports(t1 *http.Transport) (*Transport, error) { func configureTransports(t1 *http.Transport) (*Transport, error) {
@@ -31,6 +31,17 @@ func configureTransports(t1 *http.Transport) (*Transport, error) {
// linked to the http.Transport's. // linked to the http.Transport's.
tr2 := &Transport{} tr2 := &Transport{}
tr2.configure(t1) tr2.configure(t1)
// Enable HTTP/2 on the transport, as the pre-wrapping implementation did:
// net/http does not auto-enable it for a transport with a custom
// TLSClientConfig or dialer.
if t1.TLSClientConfig == nil {
t1.TLSClientConfig = &tls.Config{}
}
if t1.Protocols == nil {
t1.Protocols = new(http.Protocols)
t1.Protocols.SetHTTP1(true)
}
t1.Protocols.SetHTTP2(true)
return tr2, nil return tr2, nil
} }
+1 -1
View File
@@ -109,7 +109,7 @@ func (g *Group) TryGo(f func() error) bool {
if g.sem != nil { if g.sem != nil {
select { select {
case g.sem <- token{}: case g.sem <- token{}:
// Note: this allows barging iff channels in general allow barging. // Note: this allows barging if and only if channels in general allow barging.
default: default:
return false return false
} }
+76
View File
@@ -6397,3 +6397,79 @@ const (
MPOL_PREFERRED_MANY = 0x5 MPOL_PREFERRED_MANY = 0x5
MPOL_WEIGHTED_INTERLEAVE = 0x6 MPOL_WEIGHTED_INTERLEAVE = 0x6
) )
const (
GPIO_V2_GET_LINEINFO_IOCTL = 0xc100b405
GPIO_V2_GET_LINE_IOCTL = 0xc250b407
GPIO_V2_LINE_GET_VALUES_IOCTL = 0xc010b40e
GPIO_V2_LINE_SET_VALUES_IOCTL = 0xc010b40f
GPIO_V2_GET_LINEINFO_WATCH_IOCTL = 0xc100b406
GPIO_GET_LINEINFO_UNWATCH_IOCTL = 0xc004b40c
)
const (
GPIO_V2_LINE_ATTR_ID_FLAGS = 0x1
GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES = 0x2
GPIO_V2_LINE_ATTR_ID_DEBOUNCE = 0x3
GPIO_V2_LINE_CHANGED_REQUESTED = 0x1
GPIO_V2_LINE_CHANGED_RELEASED = 0x2
GPIO_V2_LINE_CHANGED_CONFIG = 0x3
GPIO_V2_LINE_EVENT_RISING_EDGE = 0x1
GPIO_V2_LINE_EVENT_FALLING_EDGE = 0x2
)
type GPIOChipInfo struct {
Name [32]byte
Label [32]byte
Lines uint32
}
type GPIOV2LineValues struct {
Bits uint64
Mask uint64
}
type GPIOV2LineAttribute struct {
Id uint32
_ uint32
Flags uint64
}
type GPIOV2LineConfigAttribute struct {
Attr GPIOV2LineAttribute
Mask uint64
}
type GPIOV2LineConfig struct {
Flags uint64
Num_attrs uint32
_ [5]uint32
Attrs [10]GPIOV2LineConfigAttribute
}
type GPIOV2LineRequest struct {
Offsets [64]uint32
Consumer [32]byte
Config GPIOV2LineConfig
Num_lines uint32
Event_buffer_size uint32
_ [5]uint32
Fd int32
}
type GPIOV2LineInfo struct {
Name [32]byte
Consumer [32]byte
Offset uint32
Num_attrs uint32
Flags uint64
Attrs [10]GPIOV2LineAttribute
_ [4]uint32
}
type GPIOV2LineInfoChanged struct {
Info GPIOV2LineInfo
Timestamp_ns uint64
Event_type uint32
_ [5]uint32
}
type GPIOV2LineEvent struct {
Timestamp_ns uint64
Id uint32
Offset uint32
Seqno uint32
Line_seqno uint32
_ [6]uint32
}
+4
View File
@@ -711,3 +711,7 @@ type SysvShmDesc struct {
_ uint32 _ uint32
_ uint32 _ uint32
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
)
+4
View File
@@ -725,3 +725,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
)
+4
View File
@@ -705,3 +705,7 @@ type SysvShmDesc struct {
_ uint32 _ uint32
_ uint32 _ uint32
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
)
+4
View File
@@ -704,3 +704,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
)
+4
View File
@@ -705,3 +705,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
)
+4
View File
@@ -710,3 +710,7 @@ type SysvShmDesc struct {
Ctime_high uint16 Ctime_high uint16
_ uint16 _ uint16
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
)
+4
View File
@@ -707,3 +707,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
)
+4
View File
@@ -707,3 +707,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
)
+4
View File
@@ -710,3 +710,7 @@ type SysvShmDesc struct {
Ctime_high uint16 Ctime_high uint16
_ uint16 _ uint16
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
)
+4
View File
@@ -718,3 +718,7 @@ type SysvShmDesc struct {
_ uint32 _ uint32
_ [4]byte _ [4]byte
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
)
+4
View File
@@ -713,3 +713,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
)
+4
View File
@@ -713,3 +713,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
)
+4
View File
@@ -792,3 +792,7 @@ const (
RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE = 0x6 RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE = 0x6
RISCV_HWPROBE_WHICH_CPUS = 0x1 RISCV_HWPROBE_WHICH_CPUS = 0x1
) )
const (
GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
)
+4
View File
@@ -727,3 +727,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
)
+4
View File
@@ -708,3 +708,7 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
const (
GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
)
+1 -1
View File
@@ -249,7 +249,7 @@ func upper(c *context) bool {
return c.copy() return c.copy()
} }
// isUpper writes the isUppercase version of the current rune to dst. // isUpper reports whether the current rune is in upper case.
func isUpper(c *context) bool { func isUpper(c *context) bool {
ct := c.caseType() ct := c.caseType()
if c.info&hasMappingMask == 0 || ct == cUpper { if c.info&hasMappingMask == 0 || ct == cUpper {
+2 -2
View File
@@ -774,7 +774,7 @@ func nlTitle(c *context) bool {
// From CLDR: // From CLDR:
// # Special titlecasing for Dutch initial "ij". // # Special titlecasing for Dutch initial "ij".
// ::Any-Title(); // ::Any-Title();
// # Fix up Ij at the beginning of a "word" (per Any-Title, notUAX #29) // # Fix up Ij at the beginning of a "word" (per Any-Title, not UAX #29)
// [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ; // [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ;
if c.src[c.pSrc] != 'I' && c.src[c.pSrc] != 'i' { if c.src[c.pSrc] != 'I' && c.src[c.pSrc] != 'i' {
return title(c) return title(c)
@@ -794,7 +794,7 @@ func nlTitleSpan(c *context) bool {
// From CLDR: // From CLDR:
// # Special titlecasing for Dutch initial "ij". // # Special titlecasing for Dutch initial "ij".
// ::Any-Title(); // ::Any-Title();
// # Fix up Ij at the beginning of a "word" (per Any-Title, notUAX #29) // # Fix up Ij at the beginning of a "word" (per Any-Title, not UAX #29)
// [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ; // [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ;
if c.src[c.pSrc] != 'I' { if c.src[c.pSrc] != 'I' {
return isTitle(c) return isTitle(c)
+8 -1
View File
@@ -121,8 +121,12 @@ func (p Properties) BoundaryAfter() bool {
// //
// When all 6 bits are zero, the character is inert, meaning it is never // When all 6 bits are zero, the character is inert, meaning it is never
// influenced by normalization. // influenced by normalization.
//
// We set flags to 0x80 (high bit 7 unused in quick check data) to indicate an invalid rune.
type qcInfo uint8 type qcInfo uint8
func (p Properties) isInvalid() bool { return p.flags == 0x80 }
func (p Properties) isYesC() bool { return p.flags&0x10 == 0 } func (p Properties) isYesC() bool { return p.flags&0x10 == 0 }
func (p Properties) isYesD() bool { return p.flags&0x4 == 0 } func (p Properties) isYesD() bool { return p.flags&0x4 == 0 }
@@ -247,6 +251,9 @@ func (f Form) PropertiesString(s string) Properties {
// to a Properties. See the comment at the top of the file // to a Properties. See the comment at the top of the file
// for more information on the format. // for more information on the format.
func compInfo(v uint16, sz int) Properties { func compInfo(v uint16, sz int) Properties {
if sz == 0 {
return Properties{flags: 0x80, size: 1}
}
if v == 0 { if v == 0 {
return Properties{size: uint8(sz)} return Properties{size: uint8(sz)}
} else if v >= 0x8000 { } else if v >= 0x8000 {
@@ -254,7 +261,7 @@ func compInfo(v uint16, sz int) Properties {
size: uint8(sz), size: uint8(sz),
ccc: uint8(v), ccc: uint8(v),
tccc: uint8(v), tccc: uint8(v),
flags: qcInfo(v >> 8), flags: qcInfo(v>>8) & 0x3f,
} }
if p.ccc > 0 || p.combinesBackward() { if p.ccc > 0 || p.combinesBackward() {
p.nLead = uint8(p.flags & 0x3) p.nLead = uint8(p.flags & 0x3)
+2 -6
View File
@@ -376,16 +376,12 @@ func nextComposed(i *Iter) []byte {
goto doNorm goto doNorm
} }
prevCC = i.info.tccc prevCC = i.info.tccc
sz := int(i.info.size) p := outp + int(i.info.size)
if sz == 0 {
sz = 1 // illegal rune: copy byte-by-byte
}
p := outp + sz
if p > len(i.buf) { if p > len(i.buf) {
break break
} }
outp = p outp = p
i.p += sz i.p += int(i.info.size)
if i.p >= i.rb.nsrc { if i.p >= i.rb.nsrc {
i.setDone() i.setDone()
break break
+10 -10
View File
@@ -148,7 +148,7 @@ func (f Form) IsNormalString(s string) bool {
// patched buffer and whether the decomposition is still in progress. // patched buffer and whether the decomposition is still in progress.
func patchTail(rb *reorderBuffer) bool { func patchTail(rb *reorderBuffer) bool {
info, p := lastRuneStart(&rb.f, rb.out) info, p := lastRuneStart(&rb.f, rb.out)
if p == -1 || info.size == 0 { if p == -1 || info.isInvalid() {
return true return true
} }
end := p + int(info.size) end := p + int(info.size)
@@ -225,7 +225,7 @@ func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
} }
fd := &rb.f fd := &rb.f
if doMerge { if doMerge {
var info Properties info := Properties{flags: 0x80, size: 1} // invalid rune
if p < n { if p < n {
info = fd.info(src, p) info = fd.info(src, p)
if !info.BoundaryBefore() || info.nLeadingNonStarters() > 0 { if !info.BoundaryBefore() || info.nLeadingNonStarters() > 0 {
@@ -235,7 +235,7 @@ func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
p = decomposeSegment(rb, p, true) p = decomposeSegment(rb, p, true)
} }
} }
if info.size == 0 { if info.isInvalid() {
rb.doFlush() rb.doFlush()
// Append incomplete UTF-8 encoding. // Append incomplete UTF-8 encoding.
return src.appendSlice(rb.out, p, n) return src.appendSlice(rb.out, p, n)
@@ -314,7 +314,7 @@ func (f *formInfo) quickSpan(src input, i, end int, atEOF bool) (n int, ok bool)
continue continue
} }
info := f.info(src, i) info := f.info(src, i)
if info.size == 0 { if info.isInvalid() {
if atEOF { if atEOF {
// include incomplete runes // include incomplete runes
return n, true return n, true
@@ -379,7 +379,7 @@ func (f Form) firstBoundary(src input, nsrc int) int {
// CGJ insertion points correctly. Luckily it doesn't have to. // CGJ insertion points correctly. Luckily it doesn't have to.
for { for {
info := fd.info(src, i) info := fd.info(src, i)
if info.size == 0 { if info.isInvalid() {
return -1 return -1
} }
if s := ss.next(info); s != ssSuccess { if s := ss.next(info); s != ssSuccess {
@@ -424,7 +424,7 @@ func (f Form) nextBoundary(src input, nsrc int, atEOF bool) int {
} }
fd := formTable[f] fd := formTable[f]
info := fd.info(src, 0) info := fd.info(src, 0)
if info.size == 0 { if info.isInvalid() {
if atEOF { if atEOF {
return 1 return 1
} }
@@ -435,7 +435,7 @@ func (f Form) nextBoundary(src input, nsrc int, atEOF bool) int {
for i := int(info.size); i < nsrc; i += int(info.size) { for i := int(info.size); i < nsrc; i += int(info.size) {
info = fd.info(src, i) info = fd.info(src, i)
if info.size == 0 { if info.isInvalid() {
if atEOF { if atEOF {
return i return i
} }
@@ -465,7 +465,7 @@ func lastBoundary(fd *formInfo, b []byte) int {
if p == -1 { if p == -1 {
return -1 return -1
} }
if info.size == 0 { // ends with incomplete rune if info.isInvalid() { // ends with incomplete rune
if p == 0 { // starts with incomplete rune if p == 0 { // starts with incomplete rune
return -1 return -1
} }
@@ -504,7 +504,7 @@ func lastBoundary(fd *formInfo, b []byte) int {
func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int { func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
// Force one character to be consumed. // Force one character to be consumed.
info := rb.f.info(rb.src, sp) info := rb.f.info(rb.src, sp)
if info.size == 0 { if info.isInvalid() {
return 0 return 0
} }
if s := rb.ss.next(info); s == ssStarter { if s := rb.ss.next(info); s == ssStarter {
@@ -528,7 +528,7 @@ func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
break break
} }
info = rb.f.info(rb.src, sp) info = rb.f.info(rb.src, sp)
if info.size == 0 { if info.isInvalid() {
if !atEOF { if !atEOF {
return int(iShortSrc) return int(iShortSrc)
} }
+14 -10
View File
@@ -12,7 +12,7 @@ import (
"reflect" "reflect"
) )
// A Kind describes a field of an ast.Node struct. // A Kind describes a field of an [ast.Node] struct.
type Kind uint8 type Kind uint8
// String returns a description of the edge kind. // String returns a description of the edge kind.
@@ -41,21 +41,25 @@ func (k Kind) Get(n ast.Node, idx int) ast.Node {
panic(fmt.Sprintf("%v.Get(%T): invalid node type", k, n)) panic(fmt.Sprintf("%v.Get(%T): invalid node type", k, n))
} }
v := reflect.ValueOf(n).Elem().Field(fieldInfos[k].index) v := reflect.ValueOf(n).Elem().Field(fieldInfos[k].index)
if idx != -1 {
v = v.Index(idx) // asserts valid index if v.Kind() == reflect.Slice {
} else { v = v.Index(idx) // asserts valid idx
// (The type assertion below asserts that v is not a slice.) } else if idx != -1 {
panic(fmt.Sprintf("%v, Get(%T, %d): cannot index non-slice", v, n, idx))
} }
return v.Interface().(ast.Node) // may be nil
out, _ := v.Interface().(ast.Node) // may be nil
return out
} }
// Each [Kind] is named Type_Field, where Type is the
// [ast.Node] struct type and Field is the name of the field
const ( const (
Invalid Kind = iota // for nodes at the root of the traversal Invalid Kind = iota // for nodes at the root of the traversal
// Kinds are sorted alphabetically. // As of Go1.26 these kinds are sorted alphabetically, but
// Numbering is not stable. // numbering must be stable, so any new addition of const should
// Each is named Type_Field, where Type is the // use a new value (be added at the end of the list).
// ast.Node struct type and Field is the name of the field
ArrayType_Elt ArrayType_Elt
ArrayType_Len ArrayType_Len
+13 -4
View File
@@ -207,11 +207,10 @@ func goListDriver(cfg *Config, runner *gocommand.Runner, overlay string, pattern
// doesn't exist. // doesn't exist.
extractQueries: extractQueries:
for _, pattern := range patterns { for _, pattern := range patterns {
eqidx := strings.Index(pattern, "=") query, value, ok := strings.Cut(pattern, "=")
if eqidx < 0 { if !ok {
restPatterns = append(restPatterns, pattern) restPatterns = append(restPatterns, pattern)
} else { } else {
query, value := pattern[:eqidx], pattern[eqidx+len("="):]
switch query { switch query {
case "file": case "file":
containFiles = append(containFiles, value) containFiles = append(containFiles, value)
@@ -563,8 +562,18 @@ func (state *golistState) createDriverResponse(words ...string) (*DriverResponse
} else { } else {
// golang/go#38990: go list silently fails to do cgo processing // golang/go#38990: go list silently fails to do cgo processing
pkg.CompiledGoFiles = nil pkg.CompiledGoFiles = nil
var msg strings.Builder
fmt.Fprintf(&msg, "go list failed to return CompiledGoFiles for %q.\n", p.Name)
for _, err := range p.DepsErrors {
msg.WriteString(strings.TrimSpace(err.Err))
msg.WriteByte('\n')
}
msg.WriteString("This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990.")
pkg.Errors = append(pkg.Errors, Error{ pkg.Errors = append(pkg.Errors, Error{
Msg: "go list failed to return CompiledGoFiles. This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990.", Msg: msg.String(),
Kind: ListError, Kind: ListError,
}) })
} }
+28 -2
View File
@@ -539,6 +539,11 @@ type Package struct {
// depsErrors is the DepsErrors field from the go list response, if any. // depsErrors is the DepsErrors field from the go list response, if any.
depsErrors []*packagesinternal.PackageError depsErrors []*packagesinternal.PackageError
// exportDataError is the error encountered reading export data, if any.
// Decoding export data should ordinarily be infallible, so this typically
// indicates a producer/consumer version skew.
exportDataError error
} }
// Module provides module information for a package. // Module provides module information for a package.
@@ -810,6 +815,12 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) {
needsrc: needsrc, needsrc: needsrc,
goVersion: response.GoVersion, goVersion: response.GoVersion,
} }
// Don't trust the driver to respond with duplicate-free
// package names (go.dev/issue/63822).
if _, ok := ld.pkgs[lpkg.ID]; ok {
return nil, fmt.Errorf("%s response contained duplicate packages for ID %q",
cond(ld.externalDriver, "go/packages driver", "go list"), lpkg.ID)
}
ld.pkgs[lpkg.ID] = lpkg ld.pkgs[lpkg.ID] = lpkg
if rootIndex >= 0 { if rootIndex >= 0 {
initial[rootIndex] = lpkg initial[rootIndex] = lpkg
@@ -1073,10 +1084,11 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
} }
// TODO(adonovan): this condition looks wrong: // TODO(adonovan): this condition looks wrong:
// I think it should be lpkg.needtypes && !lpg.needsrc, // I think it should be lpkg.needtypes && !lpkg.needsrc,
// so that NeedSyntax without NeedTypes can be satisfied by export data. // so that NeedSyntax without NeedTypes can be satisfied by export data.
if !lpkg.needsrc { if !lpkg.needsrc {
if err := ld.loadFromExportData(lpkg); err != nil { if err := ld.loadFromExportData(lpkg); err != nil {
lpkg.exportDataError = err
lpkg.Errors = append(lpkg.Errors, Error{ lpkg.Errors = append(lpkg.Errors, Error{
Pos: "-", Pos: "-",
Msg: err.Error(), Msg: err.Error(),
@@ -1215,7 +1227,13 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
if ipkg.Types != nil && ipkg.Types.Complete() { if ipkg.Types != nil && ipkg.Types.Complete() {
return ipkg.Types, nil return ipkg.Types, nil
} }
log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg)
// If types are unavailable, there must be an export data error.
if ipkg.exportDataError != nil {
return nil, ipkg.exportDataError
}
log.Fatalf("internal error: expected complete types for package %q", path)
panic("unreachable") panic("unreachable")
}) })
@@ -1577,3 +1595,11 @@ func usesExportData(cfg *Config) bool {
} }
type unit struct{} type unit struct{}
func cond[T any](cond bool, t, f T) T {
if cond {
return t
} else {
return f
}
}
+366 -237
View File
@@ -24,8 +24,10 @@
package objectpath package objectpath
import ( import (
"encoding/binary"
"fmt" "fmt"
"go/types" "go/types"
"slices"
"strconv" "strconv"
"strings" "strings"
@@ -124,7 +126,66 @@ func For(obj types.Object) (Path, error) {
// An Encoder amortizes the cost of encoding the paths of multiple objects. // An Encoder amortizes the cost of encoding the paths of multiple objects.
// The zero value of an Encoder is ready to use. // The zero value of an Encoder is ready to use.
type Encoder struct { type Encoder struct {
scopeMemo map[*types.Scope][]types.Object // memoization of scopeObjects pkgIndex map[*types.Package]*pkgIndex
}
// A traversal encapsulates the state of a single traversal of the object/type graph.
type traversal struct {
pkg *types.Package
ix *pkgIndex // non-nil if we are building the index
target types.Object // the sought symbol (if ix == nil)
found Path // the found path (if ix == nil)
// These maps are used to short circuit cycles through
// interface methods, such as occur in the following example:
//
// type I interface { f() interface{I} }
//
// See golang/go#68046 for details.
seenTParamNames map[*types.TypeName]bool // global cycle breaking through type parameters
seenMethods map[*types.Func]bool // global cycle breaking through recursive interfaces
}
// A pkgIndex holds a compressed index of objectpaths of all symbols
// (fields, methods, params) requiring search for an entire package.
//
// The first time a search for a given package is requested, we simply
// traverse the type graph for the target object, maintaining the
// current object path as a stack. If we find the target object, we
// save the path and terminate the main loop (but it's not worth
// breaking out of the current recursion).
//
// On the second search (a pkgIndex exists but its data is nil), we
// build an index of the traversal, which we use for all subsequent
// searches.
//
// The traversal index is encoded in the data field as a list of records,
// one per node, in preorder. Records are of two types:
//
// - A record for a package-level object consists of a pair
// (parent, nameIndex uvarint), where parent is zero and
// nameIndex is the index of the object's name in the sorted
// pkg.Scope().Names() slice.
//
// - A record for a nested node (a segment of an object path)
// consists of (parent uvarint, op byte, index uvarint), where
// parent is the index of the record for the parent node,
// op is the destructuring operator, and index (if op = [AFMTr])
// is its integer operand.
//
// Since data[0] = 0 all nodes have positive offsets. In effect the
// encoding is a trie in which each node stores one path segment
// and points to the node for its prefix.
//
// TODO(adonovan): opt: evaluate an only 2-level tree with nodes for
// package-level objects and the-rest-of-the-path. One calculation
// suggested that it might be similar speed but 30% more compact.
type pkgIndex struct {
pkg *types.Package
data []byte // encoding of traversal; nil if not yet constructed
scopeNames []string // memo of pkg.Scope().Names() to avoid O(n) alloc/sort at lookup
offsets map[types.Object]uint32 // each object's node offset within encoded traversal data
} }
// For returns the path to an object relative to its package, // For returns the path to an object relative to its package,
@@ -211,10 +272,9 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
if pkg == nil { if pkg == nil {
return "", fmt.Errorf("predeclared %s has no path", obj) return "", fmt.Errorf("predeclared %s has no path", obj)
} }
scope := pkg.Scope()
// 2. package-level object? // 2. package-level object?
if scope.Lookup(obj.Name()) == obj { if pkg.Scope().Lookup(obj.Name()) == obj {
// Only exported objects (and non-exported types) have a path. // Only exported objects (and non-exported types) have a path.
// Non-exported types may be referenced by other objects. // Non-exported types may be referenced by other objects.
if _, ok := obj.(*types.TypeName); !ok && !obj.Exported() { if _, ok := obj.(*types.TypeName); !ok && !obj.Exported() {
@@ -232,19 +292,18 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
// have a path. // have a path.
return "", fmt.Errorf("no path for %v", obj) return "", fmt.Errorf("no path for %v", obj)
} }
case *types.Const, // Only package-level constants have a path. case *types.Const, // Only package-level constants have a path.
*types.Label, // Labels are function-local. *types.Label, // Labels are function-local.
*types.PkgName: // PkgNames are file-local. *types.PkgName: // PkgNames are file-local.
return "", fmt.Errorf("no path for %v", obj) return "", fmt.Errorf("no path for %v", obj)
case *types.Var: case *types.Var:
// Could be: // A var, if not package-level, must be a
// - a field (obj.IsField()) // parameter (incl. receiver) or result, or a struct field.
// - a func parameter or result if obj.Kind() == types.LocalVar {
// - a local var. return "", fmt.Errorf("no path for local %v", obj)
// Sadly there is no way to distinguish }
// a param/result from a local
// so we must proceed to the find.
case *types.Func: case *types.Func:
// A func, if not package-level, must be a method. // A func, if not package-level, must be a method.
@@ -261,89 +320,311 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
panic(obj) panic(obj)
} }
// 4. Search the API for the path to the var (field/param/result) or method. // 4. Search the object/type graph for the path to
// the var (field/param/result) or method.
// First inspect package-level named types. ix, ok := enc.pkgIndex[pkg]
// In the presence of path aliases, these give
// the best paths because non-types may
// refer to types, but not the reverse.
empty := make([]byte, 0, 48) // initial space
objs := enc.scopeObjects(scope)
for _, o := range objs {
tname, ok := o.(*types.TypeName)
if !ok { if !ok {
continue // handle non-types in second pass // First search: don't build an index, just traverse.
// This avoids allocation in [For], whose Encoder
// lives for a single call.
ix = &pkgIndex{pkg: pkg}
if enc.pkgIndex == nil {
enc.pkgIndex = make(map[*types.Package]*pkgIndex)
}
enc.pkgIndex[pkg] = ix // build the index next time
f := traversal{pkg: pkg, target: obj}
f.traverse()
if f.found != "" {
return f.found, nil
}
} else {
// Second search: build an index while traversing.
if ix.data == nil {
ix.offsets = make(map[types.Object]uint32)
ix.data = []byte{0} // offset 0 is sentinel
(&traversal{pkg: pkg, ix: ix}).traverse()
} }
path := append(empty, o.Name()...) // Second and later searches: consult the index.
path = append(path, opType) if offset, ok := ix.offsets[obj]; ok {
return ix.path(offset), nil
T := o.Type()
if alias, ok := T.(*types.Alias); ok {
if r := findTypeParam(obj, alias.TypeParams(), path, opTypeParam); r != nil {
return Path(r), nil
}
if r := find(obj, alias.Rhs(), append(path, opRhs)); r != nil {
return Path(r), nil
}
} else if tname.IsAlias() {
// legacy alias
if r := find(obj, T, path); r != nil {
return Path(r), nil
}
} else if named, ok := T.(*types.Named); ok {
// defined (named) type
if r := findTypeParam(obj, named.TypeParams(), path, opTypeParam); r != nil {
return Path(r), nil
}
if r := find(obj, named.Underlying(), append(path, opUnderlying)); r != nil {
return Path(r), nil
}
}
}
// Then inspect everything else:
// non-types, and declared methods of defined types.
for _, o := range objs {
path := append(empty, o.Name()...)
if _, ok := o.(*types.TypeName); !ok {
if o.Exported() {
// exported non-type (const, var, func)
if r := find(obj, o.Type(), append(path, opType)); r != nil {
return Path(r), nil
}
}
continue
}
// Inspect declared methods of defined types.
if T, ok := types.Unalias(o.Type()).(*types.Named); ok {
path = append(path, opType)
// The method index here is always with respect
// to the underlying go/types data structures,
// which ultimately derives from source order
// and must be preserved by export data.
for i := 0; i < T.NumMethods(); i++ {
m := T.Method(i)
path2 := appendOpArg(path, opMethod, i)
if m == obj {
return Path(path2), nil // found declared method
}
if r := find(obj, m.Type(), append(path2, opType)); r != nil {
return Path(r), nil
}
}
} }
} }
return "", fmt.Errorf("can't find path for %v in %s", obj, pkg.Path()) return "", fmt.Errorf("can't find path for %v in %s", obj, pkg.Path())
} }
func appendOpArg(path []byte, op byte, arg int) []byte { // traverse performs a complete traversal of all symbols reachable from the package.
func (tr *traversal) traverse() {
scope := tr.pkg.Scope()
names := scope.Names()
if tr.ix != nil {
tr.ix.scopeNames = names
}
empty := make([]byte, 0, 48) // initial space for stack (ix == nil)
// First inspect package-level type names.
// In the presence of path aliases, these give
// the best paths because non-types may
// refer to types, but not the reverse.
for i, name := range names {
if tr.found != "" {
return // found (ix == nil)
}
obj := scope.Lookup(name)
if _, ok := obj.(*types.TypeName); !ok {
continue // handle non-types in second pass
}
// emit (name, opType)
var path []byte
var offset uint32
if tr.ix == nil {
path = append(empty, name...)
path = append(path, opType)
} else {
offset = tr.ix.emitPackageLevel(i)
tr.ix.offsets[obj] = offset
offset = tr.ix.emitPathSegment(offset, opType, -1)
}
// A TypeName (for Named or Alias) may have type parameters.
switch t := obj.Type().(type) {
case *types.Alias:
tr.tparams(t.TypeParams(), path, offset, opTypeParam)
tr.typ(path, offset, opRhs, -1, t.Rhs())
case *types.Named:
tr.tparams(t.TypeParams(), path, offset, opTypeParam)
tr.typ(path, offset, opUnderlying, -1, t.Underlying())
}
}
// Then inspect everything else:
// exported non-types, and declared methods of defined types.
for i, name := range names {
if tr.found != "" {
return // found (ix == nil)
}
obj := scope.Lookup(name)
if tname, ok := obj.(*types.TypeName); !ok {
if obj.Exported() {
// exported non-type (const, var, func)
var path []byte
var offset uint32
if tr.ix == nil {
path = append(empty, name...)
} else {
offset = tr.ix.emitPackageLevel(i)
tr.ix.offsets[obj] = offset
}
tr.typ(path, offset, opType, -1, obj.Type())
}
} else if T, ok := types.Unalias(tname.Type()).(*types.Named); ok {
// defined type
var path []byte
var offset uint32
if tr.ix == nil {
path = append(empty, name...)
path = append(path, opType)
} else {
// Inv: map entry for obj was populated in first pass.
offset = tr.ix.emitPathSegment(tr.ix.offsets[obj], opType, -1)
}
// Inspect declared methods of defined types.
//
// The method index here is always with respect
// to the underlying go/types data structures,
// which ultimately derives from source order
// and must be preserved by export data.
for i := 0; i < T.NumMethods(); i++ {
m := T.Method(i)
tr.object(path, offset, opMethod, i, m)
}
}
}
}
func (tr *traversal) visitType(path []byte, offset uint32, T types.Type) {
switch T := T.(type) {
case *types.Alias:
tr.typ(path, offset, opRhs, -1, T.Rhs())
case *types.Basic, *types.Named:
// Named types belonging to pkg were handled already,
// so T must belong to another package. No path.
return
case *types.Pointer, *types.Slice, *types.Array, *types.Chan:
type hasElem interface{ Elem() types.Type } // note: includes Map
tr.typ(path, offset, opElem, -1, T.(hasElem).Elem())
case *types.Map:
tr.typ(path, offset, opKey, -1, T.Key())
tr.typ(path, offset, opElem, -1, T.Elem())
case *types.Signature:
tr.tparams(T.RecvTypeParams(), path, offset, opRecvTypeParam)
tr.tparams(T.TypeParams(), path, offset, opTypeParam)
tr.typ(path, offset, opParams, -1, T.Params())
tr.typ(path, offset, opResults, -1, T.Results())
case *types.Struct:
for i := 0; i < T.NumFields(); i++ {
tr.object(path, offset, opField, i, T.Field(i))
}
case *types.Tuple:
for i := 0; i < T.Len(); i++ {
tr.object(path, offset, opAt, i, T.At(i))
}
case *types.Interface:
for i := 0; i < T.NumMethods(); i++ {
m := T.Method(i)
if m.Pkg() != nil && m.Pkg() != tr.pkg {
continue // embedded method from another package
}
if !tr.seenMethods[m] {
if tr.seenMethods == nil {
tr.seenMethods = make(map[*types.Func]bool)
}
tr.seenMethods[m] = true
tr.object(path, offset, opMethod, i, m)
}
}
case *types.TypeParam:
tname := T.Obj()
if tname.Pkg() != nil && tname.Pkg() != tr.pkg {
return // type parameter from another package
}
if !tr.seenTParamNames[tname] {
if tr.seenTParamNames == nil {
tr.seenTParamNames = make(map[*types.TypeName]bool)
}
tr.seenTParamNames[tname] = true
tr.object(path, offset, opObj, -1, tname)
tr.typ(path, offset, opConstraint, -1, T.Constraint())
}
}
}
func (tr *traversal) tparams(list *types.TypeParamList, path []byte, offset uint32, op byte) {
for i := 0; i < list.Len(); i++ {
tr.typ(path, offset, op, i, list.At(i))
}
}
// typ descends the type graph edge (op, index), then proceeds to traverse type t.
func (tr *traversal) typ(path []byte, offset uint32, op byte, index int, t types.Type) {
if tr.ix == nil {
path = appendOpArg(path, op, index)
} else {
offset = tr.ix.emitPathSegment(offset, op, index)
}
tr.visitType(path, offset, t)
}
// object descends the type graph edge (op, index), records object
// obj, then proceeds to traverse its type.
func (tr *traversal) object(path []byte, offset uint32, op byte, index int, obj types.Object) {
if tr.ix == nil {
path = appendOpArg(path, op, index)
if obj == tr.target && tr.found == "" {
tr.found = Path(path)
}
path = append(path, opType)
} else {
offset = tr.ix.emitPathSegment(offset, op, index)
if _, ok := tr.ix.offsets[obj]; !ok {
tr.ix.offsets[obj] = offset
}
offset = tr.ix.emitPathSegment(offset, opType, -1)
}
tr.visitType(path, offset, obj.Type())
}
// emitPackageLevel encodes a record for a package-level symbol,
// identified by its index in ix.scopeNames.
func (p *pkgIndex) emitPackageLevel(index int) uint32 {
off := uint32(len(p.data))
p.data = append(p.data, 0) // zero varint => no parent
p.data = binary.AppendUvarint(p.data, uint64(index))
return off
}
// emitPathSegment emits a record for a non-initial object path segment.
func (p *pkgIndex) emitPathSegment(parent uint32, op byte, index int) uint32 {
off := uint32(len(p.data))
p.data = binary.AppendUvarint(p.data, uint64(parent))
p.data = append(p.data, op)
switch op {
case opAt, opField, opMethod, opTypeParam, opRecvTypeParam:
p.data = binary.AppendUvarint(p.data, uint64(index))
}
return off
}
// path returns the Path for the encoded node at the specified offset.
func (p *pkgIndex) path(offset uint32) Path {
var elems []string // path elements in reverse
for {
// Read parent index.
parent, n := binary.Uvarint(p.data[offset:])
offset += uint32(n)
if parent == 0 {
break // root (end of path)
}
op := p.data[offset]
offset++
// The [AFMTr] operators have a numeric operand.
switch op {
case opAt, opField, opMethod, opTypeParam, opRecvTypeParam:
val, n := binary.Uvarint(p.data[offset:])
offset += uint32(n)
elems = append(elems, strconv.Itoa(int(val)))
}
elems = append(elems, string([]byte{op}))
offset = uint32(parent)
}
idx, _ := binary.Uvarint(p.data[offset:])
// Convert index to Path string.
name := p.scopeNames[idx]
sz := len(name)
for _, elem := range elems {
sz += len(elem)
}
var buf strings.Builder
buf.Grow(sz)
buf.WriteString(name)
for _, elem := range slices.Backward(elems) {
buf.WriteString(elem)
}
return Path(buf.String())
}
// appendOpArg appends (op, index) to the object path.
// A negative index is ignored.
func appendOpArg(path []byte, op byte, index int) []byte {
path = append(path, op) path = append(path, op)
path = strconv.AppendInt(path, int64(arg), 10) if index >= 0 {
path = strconv.AppendInt(path, int64(index), 10)
}
return path return path
} }
@@ -442,138 +723,6 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
// panic(fmt.Sprintf("couldn't find method %s on type %s; methods: %#v", meth, named, enc.namedMethods(named))) // panic(fmt.Sprintf("couldn't find method %s on type %s; methods: %#v", meth, named, enc.namedMethods(named)))
} }
// find finds obj within type T, returning the path to it, or nil if not found.
//
// The seen map is used to short circuit cycles through type parameters. If
// nil, it will be allocated as necessary.
//
// The seenMethods map is used internally to short circuit cycles through
// interface methods, such as occur in the following example:
//
// type I interface { f() interface{I} }
//
// See golang/go#68046 for details.
func find(obj types.Object, T types.Type, path []byte) []byte {
return (&finder{obj: obj}).find(T, path)
}
// finder closes over search state for a call to find.
type finder struct {
obj types.Object // the sought object
seenTParamNames map[*types.TypeName]bool // for cycle breaking through type parameters
seenMethods map[*types.Func]bool // for cycle breaking through recursive interfaces
}
func (f *finder) find(T types.Type, path []byte) []byte {
switch T := T.(type) {
case *types.Alias:
return f.find(types.Unalias(T), path)
case *types.Basic, *types.Named:
// Named types belonging to pkg were handled already,
// so T must belong to another package. No path.
return nil
case *types.Pointer:
return f.find(T.Elem(), append(path, opElem))
case *types.Slice:
return f.find(T.Elem(), append(path, opElem))
case *types.Array:
return f.find(T.Elem(), append(path, opElem))
case *types.Chan:
return f.find(T.Elem(), append(path, opElem))
case *types.Map:
if r := f.find(T.Key(), append(path, opKey)); r != nil {
return r
}
return f.find(T.Elem(), append(path, opElem))
case *types.Signature:
if r := f.findTypeParam(T.RecvTypeParams(), path, opRecvTypeParam); r != nil {
return r
}
if r := f.findTypeParam(T.TypeParams(), path, opTypeParam); r != nil {
return r
}
if r := f.find(T.Params(), append(path, opParams)); r != nil {
return r
}
return f.find(T.Results(), append(path, opResults))
case *types.Struct:
for i := 0; i < T.NumFields(); i++ {
fld := T.Field(i)
path2 := appendOpArg(path, opField, i)
if fld == f.obj {
return path2 // found field var
}
if r := f.find(fld.Type(), append(path2, opType)); r != nil {
return r
}
}
return nil
case *types.Tuple:
for i := 0; i < T.Len(); i++ {
v := T.At(i)
path2 := appendOpArg(path, opAt, i)
if v == f.obj {
return path2 // found param/result var
}
if r := f.find(v.Type(), append(path2, opType)); r != nil {
return r
}
}
return nil
case *types.Interface:
for i := 0; i < T.NumMethods(); i++ {
m := T.Method(i)
if f.seenMethods[m] {
continue // break cycles (see TestIssue70418)
}
path2 := appendOpArg(path, opMethod, i)
if m == f.obj {
return path2 // found interface method
}
if f.seenMethods == nil {
f.seenMethods = make(map[*types.Func]bool)
}
f.seenMethods[m] = true
if r := f.find(m.Type(), append(path2, opType)); r != nil {
return r
}
}
return nil
case *types.TypeParam:
name := T.Obj()
if f.seenTParamNames[name] {
return nil
}
if name == f.obj {
return append(path, opObj)
}
if f.seenTParamNames == nil {
f.seenTParamNames = make(map[*types.TypeName]bool)
}
f.seenTParamNames[name] = true
if r := f.find(T.Constraint(), append(path, opConstraint)); r != nil {
return r
}
return nil
}
panic(T)
}
func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte) []byte {
return (&finder{obj: obj}).findTypeParam(list, path, op)
}
func (f *finder) findTypeParam(list *types.TypeParamList, path []byte, op byte) []byte {
for i := 0; i < list.Len(); i++ {
tparam := list.At(i)
path2 := appendOpArg(path, op, i)
if r := f.find(tparam, path2); r != nil {
return r
}
}
return nil
}
// Object returns the object denoted by path p within the package pkg. // Object returns the object denoted by path p within the package pkg.
func Object(pkg *types.Package, p Path) (types.Object, error) { func Object(pkg *types.Package, p Path) (types.Object, error) {
pathstr := string(p) pathstr := string(p)
@@ -708,7 +857,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
} }
tparams := hasTypeParams.TypeParams() tparams := hasTypeParams.TypeParams()
if n := tparams.Len(); index >= n { if n := tparams.Len(); index >= n {
return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n) return nil, fmt.Errorf("type parameter index %d out of range [0-%d)", index, n)
} }
t = tparams.At(index) t = tparams.At(index)
@@ -719,7 +868,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
} }
rtparams := sig.RecvTypeParams() rtparams := sig.RecvTypeParams()
if n := rtparams.Len(); index >= n { if n := rtparams.Len(); index >= n {
return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n) return nil, fmt.Errorf("receiver type parameter index %d out of range [0-%d)", index, n)
} }
t = rtparams.At(index) t = rtparams.At(index)
@@ -794,23 +943,3 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
return obj, nil // success return obj, nil // success
} }
// scopeObjects is a memoization of scope objects.
// Callers must not modify the result.
func (enc *Encoder) scopeObjects(scope *types.Scope) []types.Object {
m := enc.scopeMemo
if m == nil {
m = make(map[*types.Scope][]types.Object)
enc.scopeMemo = m
}
objs, ok := m[scope]
if !ok {
names := scope.Names() // allocates and sorts
objs = make([]types.Object, len(names))
for i, name := range names {
objs[i] = scope.Lookup(name)
}
m[scope] = objs
}
return objs
}
+3
View File
@@ -823,6 +823,9 @@ func (p *iexporter) doDecl(obj types.Object) {
w.pos(m.Pos()) w.pos(m.Pos())
w.string(m.Name()) w.string(m.Name())
sig, _ := m.Type().(*types.Signature) sig, _ := m.Type().(*types.Signature)
if w.p.version >= iexportVersionGenericMethods && w.bool(sig.TypeParams().Len() > 0) {
w.tparamList(obj.Name()+"."+m.Name(), sig.TypeParams(), obj.Pkg())
}
// Receiver type parameters are type arguments of the receiver type, so // Receiver type parameters are type arguments of the receiver type, so
// their name must be qualified before exporting recv. // their name must be qualified before exporting recv.
+10 -6
View File
@@ -52,9 +52,10 @@ const (
iexportVersionPosCol = 1 iexportVersionPosCol = 1
iexportVersionGo1_18 = 2 iexportVersionGo1_18 = 2
iexportVersionGenerics = 2 iexportVersionGenerics = 2
iexportVersion = iexportVersionGenerics iexportVersionGenericMethods = 3
iexportVersion = iexportVersionGenericMethods
iexportVersionCurrent = 2 iexportVersionCurrent = 3
) )
type ident struct { type ident struct {
@@ -179,9 +180,9 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
version = int64(r.uint64()) version = int64(r.uint64())
switch version { switch version {
case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: case iexportVersionGenericMethods, iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
default: default:
if version > iexportVersionGo1_18 { if version > iexportVersionGenericMethods {
errorf("unstable iexport format version %d, just rebuild compiler and std library", version) errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
} else { } else {
errorf("unknown iexport format version %d", version) errorf("unknown iexport format version %d", version)
@@ -614,6 +615,10 @@ func (r *importReader) obj(pkg *types.Package, name string) {
for n := r.uint64(); n > 0; n-- { for n := r.uint64(); n > 0; n-- {
mpos := r.pos() mpos := r.pos()
mname := r.ident() mname := r.ident()
var tpars []*types.TypeParam
if r.p.version >= iexportVersionGenericMethods && r.bool() {
tpars = r.tparamList()
}
recv := r.param(pkg) recv := r.param(pkg)
// If the receiver has any targs, set those as the // If the receiver has any targs, set those as the
@@ -628,8 +633,7 @@ func (r *importReader) obj(pkg *types.Package, name string) {
rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam) rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam)
} }
} }
msig := r.signature(pkg, recv, rparams, nil) msig := r.signature(pkg, recv, rparams, tpars)
named.AddMethod(types.NewFunc(mpos, pkg, mname, msig)) named.AddMethod(types.NewFunc(mpos, pkg, mname, msig))
} }
} }
+34 -8
View File
@@ -11,6 +11,7 @@ import (
"go/token" "go/token"
"go/types" "go/types"
"sort" "sort"
"strings"
"golang.org/x/tools/internal/aliases" "golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/pkgbits" "golang.org/x/tools/internal/pkgbits"
@@ -523,6 +524,12 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
return objPkg, objName return objPkg, objName
} }
// TODO(mark): This, like the above splitVargenSuffix, is not ideal.
// Ignore generic methods promoted to global scope.
if strings.Contains(objName, ".") {
return objPkg, objName
}
if objPkg.Scope().Lookup(objName) == nil { if objPkg.Scope().Lookup(objName) == nil {
dict := pr.objDictIdx(idx) dict := pr.objDictIdx(idx)
@@ -554,15 +561,11 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
case pkgbits.ObjFunc: case pkgbits.ObjFunc:
pos := r.pos() pos := r.pos()
var rtparams []*types.TypeParam if r.Version().Has(pkgbits.GenericMethods) {
var recv *types.Var assert(!r.Bool()) // generic methods are read in their defining type
if r.Version().Has(pkgbits.GenericMethods) && r.Bool() {
r.selector()
rtparams = r.typeParamNames(true)
recv = r.param()
} }
tparams := r.typeParamNames(false) tparams := r.typeParamNames(false)
sig := r.signature(recv, rtparams, tparams) sig := r.signature(nil, nil, tparams)
declare(types.NewFunc(pos, objPkg, objName, sig)) declare(types.NewFunc(pos, objPkg, objName, sig))
case pkgbits.ObjType: case pkgbits.ObjType:
@@ -630,6 +633,29 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
named.AddMethod(r.method()) named.AddMethod(r.method())
} }
if r.Version().Has(pkgbits.GenericMethods) {
for range r.Len() {
// Careful: objIdx is used to read in package-scoped declarations, which
// methods are not. Instead, decode it here. This makes it easier to
// associate it with the type and avoids the main objIdx loop.
idx := r.Reloc(pkgbits.RelocObj)
r := pr.tempReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1)
r.dict = pr.objDictIdx(idx)
pos := r.pos()
assert(r.Bool()) // generic method
pkg, name := r.selector()
rtparams := r.typeParamNames(true)
recv := r.param()
tparams := r.typeParamNames(false)
sig := r.signature(recv, rtparams, tparams)
pr.retireReader(r)
named.AddMethod(types.NewFunc(pos, pkg, name, sig))
}
}
case pkgbits.ObjVar: case pkgbits.ObjVar:
pos := r.pos() pos := r.pos()
typ := r.typ() typ := r.typ()
@@ -653,7 +679,7 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
} }
nreceivers := 0 nreceivers := 0
if r.Version().Has(pkgbits.GenericMethods) && r.Bool() { if r.Version().Has(pkgbits.GenericMethods) {
nreceivers = r.Len() nreceivers = r.Len()
} }
nexplicits := r.Len() nexplicits := r.Len()
+3 -2
View File
@@ -8,6 +8,7 @@ import (
"context" "context"
"fmt" "fmt"
"regexp" "regexp"
"slices"
"strings" "strings"
) )
@@ -41,9 +42,9 @@ func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) {
} }
// Split up "[go1.1 go1.15]" and return highest go1.X value. // Split up "[go1.1 go1.15]" and return highest go1.X value.
tags := strings.Fields(stdout[1 : len(stdout)-2]) tags := strings.Fields(stdout[1 : len(stdout)-2])
for i := len(tags) - 1; i >= 0; i-- { for _, tag := range slices.Backward(tags) {
var version int var version int
if _, err := fmt.Sscanf(tags[i], "go1.%d", &version); err != nil { if _, err := fmt.Sscanf(tag, "go1.%d", &version); err != nil {
continue continue
} }
return version, nil return version, nil
+2 -5
View File
@@ -273,7 +273,6 @@ func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) erro
} }
unknown = append(unknown, imp.ImportPath) unknown = append(unknown, imp.ImportPath)
} }
names, err := p.source.LoadPackageNames(ctx, p.srcDir, unknown) names, err := p.source.LoadPackageNames(ctx, p.srcDir, unknown)
if err != nil { if err != nil {
return err return err
@@ -1650,9 +1649,7 @@ func (s *symbolSearcher) search(ctx context.Context, candidates []pkgDistance, p
}() }()
// Start the search. // Start the search.
wg.Add(1) wg.Go(func() {
go func() {
defer wg.Done()
for i, c := range candidates { for i, c := range candidates {
select { select {
case loadExportsSem <- struct{}{}: case loadExportsSem <- struct{}{}:
@@ -1681,7 +1678,7 @@ func (s *symbolSearcher) search(ctx context.Context, candidates []pkgDistance, p
rescv[i] <- pkg // may be nil rescv[i] <- pkg // may be nil
}() }()
} }
}() })
// Await the first (best) result. // Await the first (best) result.
for _, resc := range rescv { for _, resc := range rescv {
+4
View File
@@ -74,6 +74,10 @@ func Process(filename string, src []byte, opt *Options) (formatted []byte, err e
// Note that filename's directory influences which imports can be chosen, // Note that filename's directory influences which imports can be chosen,
// so it is important that filename be accurate. // so it is important that filename be accurate.
func FixImports(ctx context.Context, filename string, src []byte, goroot string, logf func(string, ...any), source Source) (fixes []*ImportFix, err error) { func FixImports(ctx context.Context, filename string, src []byte, goroot string, logf func(string, ...any), source Source) (fixes []*ImportFix, err error) {
if source == nil {
// In case someone adds a defective call from a new place
panic("source is nil")
}
ctx, done := event.Start(ctx, "imports.FixImports") ctx, done := event.Start(ctx, "imports.FixImports")
defer done() defer done()
+3 -3
View File
@@ -679,11 +679,11 @@ func modRelevance(mod *gocommand.ModuleJSON) float64 {
_, versionString, ok := module.SplitPathVersion(mod.Path) _, versionString, ok := module.SplitPathVersion(mod.Path)
if ok { if ok {
index := strings.Index(versionString, "v") _, after, ok := strings.Cut(versionString, "v")
if index == -1 { if !ok {
return relevance return relevance
} }
if versionNumber, err := strconv.ParseFloat(versionString[index+1:], 64); err == nil { if versionNumber, err := strconv.ParseFloat(after, 64); err == nil {
relevance += versionNumber / 1000 relevance += versionNumber / 1000
} }
} }
+338 -316
View File
@@ -12,366 +12,386 @@ type pkginfo struct {
} }
var deps = [...]pkginfo{ var deps = [...]pkginfo{
{"archive/tar", "\x03q\x03F=\x01\n\x01$\x01\x01\x02\x05\b\x02\x01\x02\x02\r"}, {"archive/tar", "\x03{\x03F>\x01\n\x01&\x01\x01\x02\x05\b\x02\x01\x02\x02\r"},
{"archive/zip", "\x02\x04g\a\x03\x13\x021=\x01+\x05\x01\x0f\x03\x02\x0f\x04"}, {"archive/zip", "\x02\x04j\x0e\x03\x12\x022>\x01-\x05\x01\x0f\x03\x02\x0f\x04"},
{"bufio", "\x03q\x86\x01D\x15"}, {"bufio", "\x03{\x87\x01F\x15"},
{"bytes", "t+[\x03\fH\x02\x02"}, {"bytes", "~*]\x03\fJ\x02\x02"},
{"cmp", ""}, {"cmp", ""},
{"compress/bzip2", "\x02\x02\xf6\x01A"}, {"compress/bzip2", "\x02\x02\x81\x02C"},
{"compress/flate", "\x02r\x03\x83\x01\f\x033\x01\x03"}, {"compress/flate", "\x02|\x03\x84\x01\f\x034\x02\x03"},
{"compress/gzip", "\x02\x04g\a\x03\x15nU"}, {"compress/gzip", "\x02\x04j\x0e\x03\x14pW"},
{"compress/lzw", "\x02r\x03\x83\x01"}, {"compress/lzw", "\x02|\x03\x84\x01"},
{"compress/zlib", "\x02\x04g\a\x03\x13\x01o"}, {"compress/zlib", "\x02\x04j\x0e\x03\x12\x01q"},
{"container/heap", "\xbc\x02"}, {"container/heap", "\xc9\x02"},
{"container/list", ""}, {"container/list", ""},
{"container/ring", ""}, {"container/ring", ""},
{"context", "t\\p\x01\x0e"}, {"context", "~]r\x01\x0e"},
{"crypto", "\x8a\x01pC"}, {"crypto", "\x93\x01rE"},
{"crypto/aes", "\x10\v\t\x99\x02"}, {"crypto/aes", "\x10\v\n\xa5\x02"},
{"crypto/cipher", "\x03!\x01\x01 \x12\x1c,Z"}, {"crypto/cipher", "\x03\"\x01\x01 \x13$+\\"},
{"crypto/des", "\x10\x16 .,\x9d\x01\x03"}, {"crypto/des", "\x10\x17 7+\xa1\x01\x03"},
{"crypto/dsa", "F\x03+\x86\x01\r"}, {"crypto/dsa", "G\x034\x87\x01\r"},
{"crypto/ecdh", "\x03\v\r\x10\x04\x17\x03\x0f\x1c\x86\x01"}, {"crypto/ecdh", "\x03\v\r\x11\x04\x17\x03\x10$\x87\x01"},
{"crypto/ecdsa", "\x0e\x05\x03\x05\x01\x10\b\v\x06\x01\x03\x0e\x01\x1c\x86\x01\r\x05L\x01"}, {"crypto/ecdsa", "\x0e\x05\x03\x05\x01\x11\b\v\x06\x01\x03\x0f\x01$\x87\x01\r\x05O\x01"},
{"crypto/ed25519", "\x0e\x1f\x12\a\x03\b\a\x1cI=C"}, {"crypto/ed25519", "\x0e \x12\a\x03\t\a$I>E"},
{"crypto/elliptic", "4@\x86\x01\r9"}, {"crypto/elliptic", "5I\x87\x01\r;"},
{"crypto/fips140", "#\x05\x95\x01\x98\x01"}, {"crypto/fips140", "$\x05\x9e\x01\x9b\x01"},
{"crypto/hkdf", "0\x15\x01.\x16"}, {"crypto/hkdf", "1\x15\x017\x15"},
{"crypto/hmac", "\x1b\x16\x14\x01\x122"}, {"crypto/hmac", "\x1b\x17\x14\x01\x139"},
{"crypto/hpke", "\x03\v\x02\x03\x04\x01\f\x01\x05\x1f\x05\a\x01\x01\x1d\x03\x13\x16\x9b\x01\x1c"}, {"crypto/hpke", "\x03\v\x02\x03\x04\x01\r\x01\x05\x1f\x06\a\x01\x01%\x03\x12\x16\x9f\x01\x1d"},
{"crypto/internal/boring", "\x0e\x02\x0el"}, {"crypto/internal/boring", "\x0e\x02\x0eu"},
{"crypto/internal/boring/bbig", "\x1b\xec\x01N"}, {"crypto/internal/boring/bbig", "\x1b\xf7\x01P"},
{"crypto/internal/boring/bcache", "\xc1\x02\x14"}, {"crypto/internal/boring/bcache", "\xce\x02\x14"},
{"crypto/internal/boring/sig", ""}, {"crypto/internal/boring/sig", ""},
{"crypto/internal/constanttime", ""}, {"crypto/internal/constanttime", ""},
{"crypto/internal/cryptotest", "\x03\r\v\b%\x10\x19\x06\x13\x12 \x04\x06\t\x19\x01\x11\x11\x1b\x01\a\x05\b\x03\x05\f"}, {"crypto/internal/cryptotest", "\x03\r\v\t%\x11\x1a\r\x12\x12!\x04\x06\n\x19\x01\x11\x11\x1d\x01\a\x03\x02\b\x02\x01\x05\f"},
{"crypto/internal/entropy", "K"}, {"crypto/internal/cryptotest/wycheproof", "\x0e\x12S\x01\f\x01r@\x05\x03\x15\x10"},
{"crypto/internal/entropy/v1.0.0", "D0\x95\x018\x14"}, {"crypto/internal/entropy", "L"},
{"crypto/internal/fips140", "C1\xbf\x01\v\x17"}, {"crypto/internal/entropy/v1.0.0", "E9\x96\x01:\x14"},
{"crypto/internal/fips140/aes", "\x03 \x03\x02\x14\x05\x01\x01\x05,\x95\x014"}, {"crypto/internal/fips140", "D:\xc2\x01\v\x17"},
{"crypto/internal/fips140/aes/gcm", "#\x01\x02\x02\x02\x12\x05\x01\x06,\x92\x01"}, {"crypto/internal/fips140/aes", "\x03!\x03\x02\x14\x05\x01\x01\x055\x96\x016"},
{"crypto/internal/fips140/alias", "\xd5\x02"}, {"crypto/internal/fips140/aes/gcm", "$\x01\x02\x02\x02\x12\x05\x01\x065\x93\x01"},
{"crypto/internal/fips140/bigmod", "(\x19\x01\x06,\x95\x01"}, {"crypto/internal/fips140/alias", "\xe2\x02"},
{"crypto/internal/fips140/check", "#\x0e\a\t\x02\xb7\x01["}, {"crypto/internal/fips140/bigmod", ")\x19\x01\x065\x96\x01"},
{"crypto/internal/fips140/check/checktest", "(\x8b\x02\""}, {"crypto/internal/fips140/check", "$\x0e\a\t\x02\xc1\x01]"},
{"crypto/internal/fips140/drbg", "\x03\x1f\x01\x01\x04\x14\x05\n)\x86\x01\x0f7\x01"}, {"crypto/internal/fips140/check/checktest", ")\x97\x02\""},
{"crypto/internal/fips140/ecdh", "\x03 \x05\x02\n\r3\x86\x01\x0f7"}, {"crypto/internal/fips140/drbg", "\x03 \x01\x01\x04\x14\x05\n2\x87\x01\x0f9\x01"},
{"crypto/internal/fips140/ecdsa", "\x03 \x04\x01\x02\a\x03\x06:\x16pF"}, {"crypto/internal/fips140/ecdh", "\x03!\x05\x02\n\r<\x87\x01\x0f9"},
{"crypto/internal/fips140/ed25519", "\x03 \x05\x02\x04\f:\xc9\x01\x03"}, {"crypto/internal/fips140/ecdsa", "\x03!\x04\x01\x02\a\x03\x06C\x15r\x0f9"},
{"crypto/internal/fips140/edwards25519", "\x1f\t\a\x123\x95\x017"}, {"crypto/internal/fips140/ed25519", "\x03!\x05\x02\x04\fC\xcc\x01\x03"},
{"crypto/internal/fips140/edwards25519/field", "(\x14\x053\x95\x01"}, {"crypto/internal/fips140/edwards25519", "\x1f\n\a\x12<\x96\x019"},
{"crypto/internal/fips140/hkdf", "\x03 \x05\t\a<\x16"}, {"crypto/internal/fips140/edwards25519/field", ")\x14\x05<\x96\x01"},
{"crypto/internal/fips140/hmac", "\x03 \x15\x01\x01:\x16"}, {"crypto/internal/fips140/hkdf", "\x03!\x05\t\aE\x15"},
{"crypto/internal/fips140/mldsa", "\x03\x1c\x04\x05\x02\x0e\x01\x03\x053\x95\x017"}, {"crypto/internal/fips140/hmac", "\x03!\x15\x01\x01C\x15"},
{"crypto/internal/fips140/mlkem", "\x03 \x05\x02\x0f\x03\x053\xcc\x01"}, {"crypto/internal/fips140/mldsa", "\x03\x1c\x05\x05\x02\x0e\x01\x03\x05<\x96\x019"},
{"crypto/internal/fips140/nistec", "\x1f\t\r\f3\x95\x01*\r\x15"}, {"crypto/internal/fips140/mlkem", "\x03!\x05\x02\x0f\x03\x05<\xcf\x01"},
{"crypto/internal/fips140/nistec/fiat", "(\x148\x95\x01"}, {"crypto/internal/fips140/nistec", "\x1f\n\r\f<\x96\x01,\r\x15"},
{"crypto/internal/fips140/pbkdf2", "\x03 \x05\t\a<\x16"}, {"crypto/internal/fips140/nistec/fiat", ")\x14A\x96\x01"},
{"crypto/internal/fips140/rsa", "\x03\x1c\x04\x04\x01\x02\x0e\x01\x01\x028\x16pF"}, {"crypto/internal/fips140/pbkdf2", "\x03!\x05\t\aE\x15"},
{"crypto/internal/fips140/sha256", "\x03 \x1e\x01\x06,\x16\x7f"}, {"crypto/internal/fips140/rsa", "\x03\x1c\x05\x04\x01\x02\x0e\x01\x01\x02A\x15rH"},
{"crypto/internal/fips140/sha3", "\x03 \x19\x05\x012\x95\x01L"}, {"crypto/internal/fips140/sha256", "\x03!\x1e\x01\x065\x15\x81\x01"},
{"crypto/internal/fips140/sha512", "\x03 \x1e\x01\x06,\x16\x7f"}, {"crypto/internal/fips140/sha3", "\x03!\x19\x05\x01;\x96\x01N"},
{"crypto/internal/fips140/ssh", "(b"}, {"crypto/internal/fips140/sha512", "\x03!\x1e\x01\x065\x15\x81\x01"},
{"crypto/internal/fips140/subtle", "\x1f\a\x1b\xc8\x01"}, {"crypto/internal/fips140/ssh", ")j"},
{"crypto/internal/fips140/tls12", "\x03 \x05\t\a\x02:\x16"}, {"crypto/internal/fips140/subtle", "\x1f\b\x1b\xd2\x01"},
{"crypto/internal/fips140/tls13", "\x03 \x05\b\b\t3\x16"}, {"crypto/internal/fips140/tls12", "\x03!\x05\t\a\x02C\x15"},
{"crypto/internal/fips140cache", "\xb3\x02\r'"}, {"crypto/internal/fips140/tls13", "\x03!\x05\b\b\t<\x15"},
{"crypto/internal/fips140cache", "\xc0\x02\r."},
{"crypto/internal/fips140deps", ""}, {"crypto/internal/fips140deps", ""},
{"crypto/internal/fips140deps/byteorder", "\xa0\x01"}, {"crypto/internal/fips140deps/byteorder", "\xa9\x01"},
{"crypto/internal/fips140deps/cpu", "\xb5\x01\a"}, {"crypto/internal/fips140deps/cpu", "\xbe\x01\b"},
{"crypto/internal/fips140deps/godebug", "\xbd\x01"}, {"crypto/internal/fips140deps/godebug", "\xc7\x01"},
{"crypto/internal/fips140deps/time", "\xcf\x02"}, {"crypto/internal/fips140deps/time", "\xe2\x02"},
{"crypto/internal/fips140hash", "9\x1d4\xcb\x01"}, {"crypto/internal/fips140hash", ":\x1e;\xcf\x01"},
{"crypto/internal/fips140only", "\x17\x13\x0e\x01\x01Pp"}, {"crypto/internal/fips140only", "\x17\x14\x0e\x01\x01Xr"},
{"crypto/internal/fips140test", ""}, {"crypto/internal/fips140test", ""},
{"crypto/internal/impl", "\xbe\x02"}, {"crypto/internal/impl", "\xcb\x02"},
{"crypto/internal/rand", "\x1b\x0f s=["}, {"crypto/internal/rand", "\x1b\x10 |>]"},
{"crypto/internal/randutil", "\xfa\x01\x12"}, {"crypto/internal/randutil", "\x85\x02\x12"},
{"crypto/internal/sysrand", "tq! \r\r\x01\x01\r\x06"}, {"crypto/internal/sysrand", "~r!\"\r\r\x01\x01\r\x06"},
{"crypto/internal/sysrand/internal/seccomp", "t"}, {"crypto/internal/sysrand/internal/seccomp", "~"},
{"crypto/md5", "\x0e8.\x16\x16i"}, {"crypto/md5", "\x0e97\x15\x16k"},
{"crypto/mlkem", "\x0e%"}, {"crypto/mldsa", "\x0e%K\x87\x01"},
{"crypto/mlkem/mlkemtest", "3\x13\b&"}, {"crypto/mlkem", "\x0e&"},
{"crypto/pbkdf2", "6\x0f\x01.\x16"}, {"crypto/mlkem/mlkemtest", "4\x13\t."},
{"crypto/rand", "\x1b\x0f\x1c\x03+\x86\x01\rN"}, {"crypto/pbkdf2", "7\x0f\x017\x15"},
{"crypto/rc4", "& .\xc9\x01"}, {"crypto/rand", "\x1b\x10\x1c\x034\x87\x01\rP"},
{"crypto/rsa", "\x0e\r\x01\v\x10\x0e\x01\x03\b\a\x1c\x03\x133=\f\x01"}, {"crypto/rc4", "' 7\xcc\x01"},
{"crypto/sha1", "\x0e\r+\x02,\x16\x16\x15T"}, {"crypto/rsa", "\x0e\r\x01\f\x10\x0e\x01\x03\t\a$\x03\x124>\f\x01"},
{"crypto/sha256", "\x0e\r\x1dR"}, {"crypto/sha1", "\x0e\r,\x025\x15\x16\x15V"},
{"crypto/sha3", "\x0e+Q\xcb\x01"}, {"crypto/sha256", "\x0e\r\x1eZ"},
{"crypto/sha512", "\x0e\r\x1fP"}, {"crypto/sha3", "\x0e,Y\xcf\x01"},
{"crypto/subtle", "\x1f\x1d\x9f\x01z"}, {"crypto/sha512", "\x0e\r X"},
{"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x02\x01\x01\x01\t\x01\x18\x01\x0f\x01\x03\x01\x01\x01\x01\x02\x01\x02\x01\x17\x02\x03\x13\x16\x15\b=\x16\x16\r\b\x01\x01\x01\x02\x01\x0e\x06\x02\x01\x0f"}, {"crypto/subtle", "\x1f\x1e\xa9\x01|"},
{"crypto/tls/internal/fips140tls", "\x17\xaa\x02"}, {"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x01\x01\x01\x01\x01\n\x01\x18\x01\x0f\x01\x01\x03\x01\x01\x01\x01\x02\x01\x02\x01\x1f\x02\x03\x12\x16\x15\t>\x16\x18\r\b\x01\x01\x01\x02\x01\x0e\x06\x03\x01\x15"},
{"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x017\x06\x01\x01\x02\x05\x0e\x06\x02\x02\x03F\x03:\x01\x02\b\x01\x01\x02\a\x10\x05\x01\x06\a\b\x02\x01\x02\x0f\x02\x01\x01\x02\x03\x01"}, {"crypto/tls/internal/fips140tls", "\x17\xb7\x02"},
{"crypto/x509/pkix", "j\x06\a\x90\x01H"}, {"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x01\x017\x01\x06\x01\x01\x02\x05\x0f\x06\t\x02\x03F\x03;\x01\x02\b\x01\x01\x02\a\x12\x05\x01\x06\a\b\x02\x01\x02\x0f\x02\x01\x01\x02\x04\x01"},
{"database/sql", "\x03\nQ\x16\x03\x83\x01\v\a\"\x05\b\x02\x03\x01\x0e\x02\x02\x02"}, {"crypto/x509/pkix", "m\x06\x0e\x91\x019\x11"},
{"database/sql/driver", "\rg\x03\xb7\x01\x0f\x12"}, {"database/sql", "\x03\nS\x01\x1d\x03\x84\x01\v\a$\x05\b\x02\x03\x01\x0e\x02\x02\x02\x01"},
{"debug/buildinfo", "\x03^\x02\x01\x01\b\a\x03g\x1a\x02\x01+\x0f "}, {"database/sql/driver", "\rT\x1d\x03\xba\x01\x0f\x12\a"},
{"debug/dwarf", "\x03j\a\x03\x83\x011\x11\x01\x01"}, {"database/sql/internal", ""},
{"debug/elf", "\x03\x06W\r\a\x03g\x1b\x01\f \x17\x01\x17"}, {"debug/buildinfo", "\x03a\x02\x01\x01\b\x0e\x03h\x1a\x02\x01-\x0f "},
{"debug/gosym", "\x03j\n$\xa1\x01\x01\x01\x02"}, {"debug/dwarf", "\x03m\x0e\x03\x84\x013\x11\x01\x01"},
{"debug/macho", "\x03\x06W\r\ng\x1c,\x17\x01"}, {"debug/elf", "\x03\x06Z\r\x0e\x03h\x1b\x01\f\"\x17\x01\x17"},
{"debug/pe", "\x03\x06W\r\a\x03g\x1c,\x17\x01\x17"}, {"debug/gosym", "\x03m\x11#\xa5\x01\x01\x01\x02"},
{"debug/plan9obj", "m\a\x03g\x1c,"}, {"debug/macho", "\x03\x06Z\r\x11h\x1c.\x17\x01"},
{"embed", "t+B\x19\x01T"}, {"debug/pe", "\x03\x06Z\r\x0e\x03h\x1c.\x17\x01\x17"},
{"debug/plan9obj", "p\x0e\x03h\x1c."},
{"embed", "~*D\x19\x01V"},
{"embed/internal/embedtest", ""}, {"embed/internal/embedtest", ""},
{"encoding", ""}, {"encoding", ""},
{"encoding/ascii85", "\xfa\x01C"}, {"encoding/ascii85", "\x85\x02E"},
{"encoding/asn1", "\x03q\x03g(\x01'\r\x02\x01\x11\x03\x01"}, {"encoding/asn1", "\x03{\x03h(\x01)\r\x02\x01\x11\x03\x01"},
{"encoding/base32", "\xfa\x01A\x02"}, {"encoding/base32", "\x85\x02C\x02"},
{"encoding/base64", "\xa0\x01ZA\x02"}, {"encoding/base64", "\xa9\x01\\C\x02"},
{"encoding/binary", "t\x86\x01\f(\r\x05"}, {"encoding/binary", "~\x87\x01\f*\r\x05"},
{"encoding/csv", "\x02\x01q\x03\x83\x01D\x13\x02"}, {"encoding/csv", "\x02\x01{\x03\x84\x01F\x13\x02"},
{"encoding/gob", "\x02f\x05\a\x03g\x1c\v\x01\x03\x1d\b\x12\x01\x10\x02"}, {"encoding/gob", "\x02i\x05\x0e\x03h\x1c\v\x01\x03\x1f\b\x12\x01\x10\x02"},
{"encoding/hex", "t\x03\x83\x01A\x03"}, {"encoding/hex", "~\x03\x84\x01C\x03"},
{"encoding/json", "\x03\x01d\x04\b\x03\x83\x01\f(\r\x02\x01\x02\x11\x01\x01\x02"}, {"encoding/json", "\x03\x01g\n\x01\x01\x02\x01\x01\x03\x03\x84\x016\x0f\x01"},
{"encoding/pem", "\x03i\b\x86\x01A\x03"}, {"encoding/json/internal", "~"},
{"encoding/xml", "\x02\x01e\f\x03\x83\x014\x05\n\x01\x02\x11\x02"}, {"encoding/json/internal/jsonflags", "u"},
{"errors", "\xd0\x01\x85\x01"}, {"encoding/json/internal/jsonopts", "u\x01"},
{"expvar", "qLA\b\v\x15\r\b\x02\x03\x01\x12"}, {"encoding/json/internal/jsontest", "\x03f\x15\x03\x83\x01\x01\x012\b\b\x03\x02\x0f"},
{"flag", "h\f\x03\x83\x01,\b\x05\b\x02\x01\x11"}, {"encoding/json/internal/jsonwire", "\x04r\b\x87\x01\f7\x02\x01\x13\x01\x01"},
{"fmt", "tF'\x19\f \b\r\x02\x03\x13"}, {"encoding/json/jsontext", "\x03r\x01\x01\x02\x05\x87\x01\x03\t\x034\x02\x01\x02\x13"},
{"go/ast", "\x03\x01s\x0f\x01s\x03)\b\r\x02\x01\x13\x02"}, {"encoding/json/v2", "\x03\x01g\x03\x01\x01\x03\x02\x01\x01\x02\x01\x04\x03\x84\x01\f\x03'\r\x02\x01\x02\x0f\x02\x02"},
{"go/build", "\x02\x01q\x03\x01\x02\x02\b\x02\x01\x17\x1f\x04\x02\b\x1c\x13\x01+\x01\x04\x01\a\b\x02\x01\x13\x02\x02"}, {"encoding/pem", "\x03l\x0f\x87\x01C\x03"},
{"go/build/constraint", "t\xc9\x01\x01\x13\x02"}, {"encoding/xml", "\x02\x01h\x13\x03\x84\x016\x05\n\x01\x02\x11\x02"},
{"go/constant", "w\x10\x7f\x01\x024\x01\x02\x13"}, {"errors", "\xdb\x01\x87\x01"},
{"go/doc", "\x04s\x01\x05\n=61\x10\x02\x01\x13\x02"}, {"expvar", "tSB\b\v\x17\r\b\x02\x03\x01\x12"},
{"go/doc/comment", "\x03t\xc4\x01\x01\x01\x01\x13\x02"}, {"flag", "k\x13\x03\x84\x01.\b\x05\b\x02\x01\x11"},
{"go/format", "\x03t\x01\f\x01\x02sD"}, {"fmt", "~E)\x19\f\"\b\r\x02\x03\x13"},
{"go/importer", "y\a\x01\x02\x04\x01r9"}, {"go/ast", "\x03\x01}\x0e\x01u\x03+\b\r\x02\x01\x13\x02"},
{"go/internal/gccgoimporter", "\x02\x01^\x13\x03\x04\f\x01p\x02,\x01\x05\x11\x01\r\b"}, {"go/build", "\x02\x01{\x03\x01\x02\x02\a\x02\x01\x17 \x04\x02\t\x1c\x13\x01-\x01\x04\x01\a\b\x02\x01\x13\x02\x02"},
{"go/internal/gcimporter", "\x02u\x10\x010\x05\r0,\x15\x03\x02"}, {"go/build/constraint", "~\xcc\x01\x01\x13\x02"},
{"go/internal/scannerhooks", "\x87\x01"}, {"go/constant", "\x81\x01\x0f\x81\x01\x01\x026\x01\x02\x13"},
{"go/internal/srcimporter", "w\x01\x01\v\x03\x01r,\x01\x05\x12\x02\x15"}, {"go/doc", "\x04}\x01\x05\t>73\x10\x02\x01\x13\x02"},
{"go/parser", "\x03q\x03\x01\x02\b\x04\x01s\x01+\x06\x12"}, {"go/doc/comment", "\x03~\xc7\x01\x01\x01\x01\x13\x02"},
{"go/printer", "w\x01\x02\x03\ns\f \x15\x02\x01\x02\f\x05\x02"}, {"go/format", "\x03~\x01\v\x01\x02uF"},
{"go/scanner", "\x03t\v\x05s2\x10\x01\x14\x02"}, {"go/importer", "\x83\x01\a\x01\x01\x04\x01t;"},
{"go/token", "\x04s\x86\x01>\x02\x03\x01\x10\x02"}, {"go/internal/gccgoimporter", "\x02\x01a\x1a\x03\x04\v\x01r\x02.\x01\x05\x11\x01\r\b"},
{"go/types", "\x03\x01\x06j\x03\x01\x03\t\x03\x024\x063\x04\x03\t \x06\a\b\x01\x01\x01\x02\x01\x10\x02\x02"}, {"go/internal/gcimporter", "\x02\x7f\x0f\x010\x140.\x15\x03\x02"},
{"go/version", "\xc2\x01|"}, {"go/internal/srcimporter", "\x81\x01\x01\x01\n\x03\x01t.\x01\x05\x12\x02\x15"},
{"hash", "\xfa\x01"}, {"go/parser", "\x03{\x03\x01\x02\v\x01u\x01-\x06\x12"},
{"hash/adler32", "t\x16\x16"}, {"go/printer", "\x81\x01\x01\x02\x03\tu\f\"\x15\x02\x01\x02\f\x05\x02"},
{"hash/crc32", "t\x16\x16\x15\x8b\x01\x01\x14"}, {"go/scanner", "\x03~\x0fu4\x10\x01\x14\x02"},
{"hash/crc64", "t\x16\x16\xa0\x01"}, {"go/token", "\x04}\x87\x01@\x02\x03\x01\x10\x02"},
{"hash/fnv", "t\x16\x16i"}, {"go/types", "\x03\x01\x06t\x03\x01\x03\b\x03\x02\x0654\x04\x03\t\"\x06\a\b\x01\x01\x01\x02\x01\x10\x02\x02"},
{"hash/maphash", "\x8a\x01\x11<~"}, {"go/version", "\xcc\x01\x7f"},
{"html", "\xbe\x02\x02\x13"}, {"hash", "\x85\x02"},
{"html/template", "\x03n\x06\x19-=\x01\n!\x05\x01\x02\x03\f\x01\x02\r\x01\x03\x02"}, {"hash/adler32", "~\x15\x16"},
{"image", "\x02r\x1fg\x0f4\x03\x01"}, {"hash/crc32", "~\x15\x16\x15\x8f\x01\x01\x14"},
{"hash/crc64", "~\x15\x16\xa4\x01"},
{"hash/fnv", "~\x15\x16k"},
{"hash/maphash", "\x93\x01\x11>\x80\x01"},
{"html", "\xcb\x02\x02\x13"},
{"html/template", "\x03q\r\x18.>\x01\n#\x05\x01\x02\x03\n\x02\x01\x02\r\x01\x03\x02"},
{"image", "\x02|\x1ei\x0f6\x03\x01"},
{"image/color", ""}, {"image/color", ""},
{"image/color/palette", "\x93\x01"}, {"image/color/palette", "\x9c\x01"},
{"image/draw", "\x92\x01\x01\x04"}, {"image/draw", "\x9b\x01\x01\x04"},
{"image/gif", "\x02\x01\x05l\x03\x1b\x01\x01\x01\vZ\x0f"}, {"image/gif", "\x02\x01\x05v\x03\x1a\x01\x01\x01\v\\\x0f"},
{"image/internal/imageutil", "\x92\x01"}, {"image/internal/imageutil", "\x9b\x01"},
{"image/jpeg", "\x02r\x1e\x01\x04c"}, {"image/jpeg", "\x02|\x1d\x01\x04e"},
{"image/png", "\x02\ad\n\x13\x02\x06\x01gC"}, {"image/png", "\x02\ag\x11\x12\x02\x06\x01iE"},
{"index/suffixarray", "\x03j\a\x86\x01\f+\n\x01"}, {"index/suffixarray", "\x03m\x0e\x87\x01\f-\n\x01"},
{"internal/abi", "\xbc\x01\x99\x01"}, {"internal/abi", "\xc6\x01\x9c\x01"},
{"internal/asan", "\xd5\x02"}, {"internal/asan", "\xe2\x02"},
{"internal/bisect", "\xb3\x02\r\x01"}, {"internal/bisect", "\xc0\x02\r\x01"},
{"internal/buildcfg", "wHg\x06\x02\x05\n\x01"}, {"internal/buildcfg", "\x81\x01Hj\x06\x02\x05\n\x01"},
{"internal/bytealg", "\xb5\x01\xa0\x01"}, {"internal/bytealg", "\xbe\x01\xa4\x01"},
{"internal/byteorder", ""}, {"internal/byteorder", ""},
{"internal/cfg", ""}, {"internal/cfg", ""},
{"internal/cgrouptest", "w[T\x06\x0f\x02\x01\x04\x01"}, {"internal/cgrouptest", "\x81\x01\\V\x06\x0f\x02\x01\x04\x01"},
{"internal/chacha8rand", "\xa0\x01\x15\a\x99\x01"}, {"internal/chacha8rand", "\xa9\x01\x15\b\x9c\x01"},
{"internal/copyright", ""}, {"internal/copyright", ""},
{"internal/coverage", ""}, {"internal/coverage", ""},
{"internal/coverage/calloc", ""}, {"internal/coverage/calloc", ""},
{"internal/coverage/cfile", "q\x06\x17\x17\x01\x02\x01\x01\x01\x01\x01\x01\x01\"\x02',\x06\a\n\x01\x03\x0e\x06"}, {"internal/coverage/cfile", "t\r\x16\x17\x01\x02\x01\x01\x01\x01\x01\x01\x01$\x02'.\x06\a\n\x01\x03\x0e\x06"},
{"internal/coverage/cformat", "\x04s.\x04Q\v6\x01\x02\x0e"}, {"internal/coverage/cformat", "\x04}-\x04S\v8\x01\x02\x0e"},
{"internal/coverage/cmerge", "w.a"}, {"internal/coverage/cmerge", "\x81\x01-c"},
{"internal/coverage/decodecounter", "m\n.\v\x02H,\x17\x18"}, {"internal/coverage/decodecounter", "p\x11-\v\x02J.\x17\x18"},
{"internal/coverage/decodemeta", "\x02k\n\x17\x17\v\x02H,"}, {"internal/coverage/decodemeta", "\x02n\x11\x16\x17\v\x02J."},
{"internal/coverage/encodecounter", "\x02k\n.\f\x01\x02F\v!\x15"}, {"internal/coverage/encodecounter", "\x02n\x11-\f\x01\x02H\v#\x15"},
{"internal/coverage/encodemeta", "\x02\x01j\n\x13\x04\x17\r\x02F,/"}, {"internal/coverage/encodemeta", "\x02\x01m\x11\x12\x04\x17\r\x02H./"},
{"internal/coverage/pods", "\x04s.\x81\x01\x06\x05\n\x02\x01"}, {"internal/coverage/pods", "\x04}-\x85\x01\x06\x05\n\x02\x01"},
{"internal/coverage/rtcov", "\xd5\x02"}, {"internal/coverage/rtcov", "\xe2\x02"},
{"internal/coverage/slicereader", "m\n\x83\x01["}, {"internal/coverage/slicereader", "p\x11\x84\x01]"},
{"internal/coverage/slicewriter", "w\x83\x01"}, {"internal/coverage/slicewriter", "\x81\x01\x84\x01"},
{"internal/coverage/stringtab", "w9\x04F"}, {"internal/coverage/stringtab", "\x81\x018\x04H"},
{"internal/coverage/test", ""}, {"internal/coverage/test", ""},
{"internal/coverage/uleb128", ""}, {"internal/coverage/uleb128", ""},
{"internal/cpu", "\xd5\x02"}, {"internal/cpu", "\xe2\x02"},
{"internal/dag", "\x04s\xc4\x01\x03"}, {"internal/dag", "\x04}\xc7\x01\x03"},
{"internal/diff", "\x03t\xc5\x01\x02"}, {"internal/diff", "\x03~\xc8\x01\x02"},
{"internal/exportdata", "\x02\x01q\x03\x02e\x1c,\x01\x05\x11\x01\x02"}, {"internal/exportdata", "\x02\x01{\x03\x02f\x1c.\x01\x05\x11\x01\x02"},
{"internal/filepathlite", "t+B\x1a@"}, {"internal/filepathlite", "~*D\x1aB"},
{"internal/fmtsort", "\x04\xaa\x02\r"}, {"internal/fmtsort", "\x04\xb7\x02\r"},
{"internal/fuzz", "\x03\nH\x18\x04\x03\x03\x01\f\x036=\f\x03\x1d\x01\x05\x02\x05\n\x01\x02\x01\x01\r\x04\x02"}, {"internal/fuzz", "\x03\nJ\x19\x04\n\x03\x01\v\x037>\f\x03\x1f\x01\x05\x02\x05\n\x01\x02\x01\x01\r\x04\x02"},
{"internal/gate", "\r"},
{"internal/goarch", ""}, {"internal/goarch", ""},
{"internal/godebug", "\x9d\x01!\x82\x01\x01\x14"}, {"internal/godebug", "\xa6\x01\"\x85\x01\x01\x14"},
{"internal/godebugs", ""}, {"internal/godebugs", ""},
{"internal/goexperiment", ""}, {"internal/goexperiment", ""},
{"internal/goos", ""}, {"internal/goos", ""},
{"internal/goroot", "\xa6\x02\x01\x05\x12\x02"}, {"internal/goroot", "\xb3\x02\x01\x05\x12\x02"},
{"internal/gover", "\x04"}, {"internal/gover", "\x04"},
{"internal/goversion", ""}, {"internal/goversion", ""},
{"internal/lazyregexp", "\xa6\x02\v\r\x02"}, {"internal/lazyregexp", "\xb3\x02\v\r\x02"},
{"internal/lazytemplate", "\xfa\x01,\x18\x02\r"}, {"internal/lazytemplate", "\x85\x02.\x18\x02\r"},
{"internal/msan", "\xd5\x02"}, {"internal/msan", "\xe2\x02"},
{"internal/nettest", "\x03\nqG@\f\n\x12\x06\x15\x05\x0f"},
{"internal/nettrace", ""}, {"internal/nettrace", ""},
{"internal/obscuretestdata", "l\x8e\x01,"}, {"internal/obscuretestdata", "o\x96\x01."},
{"internal/oserror", "t"}, {"internal/oserror", "~"},
{"internal/pkgbits", "\x03R\x18\a\x03\x04\fs\r\x1f\r\n\x01"}, {"internal/pkgbits", "\x03T\x19\x0e\x03\x04\vu\r!\r\n\x01"},
{"internal/platform", ""}, {"internal/platform", ""},
{"internal/poll", "tl\x05\x159\r\x01\x01\r\x06"}, {"internal/poll", "~m\x05\x15;\r\x01\x01\r\x06"},
{"internal/profile", "\x03\x04m\x03\x83\x017\n\x01\x01\x01\x11"}, {"internal/profile", "\x03\x04w\x03\x84\x019\n\x01\x01\x01\x11"},
{"internal/profilerecord", ""}, {"internal/profilerecord", ""},
{"internal/race", "\x9b\x01\xba\x01"}, {"internal/race", "\xa4\x01\xbe\x01"},
{"internal/reflectlite", "\x9b\x01!;<\""}, {"internal/reflectlite", "\xa4\x01\"<>\""},
{"internal/runtime/atomic", "\xbc\x01\x99\x01"}, {"internal/runtime/atomic", "\xc6\x01\x9c\x01"},
{"internal/runtime/cgroup", "\x9f\x01=\x04u"}, {"internal/runtime/cgroup", "\xa8\x01?\x04w"},
{"internal/runtime/exithook", "\xd1\x01\x84\x01"}, {"internal/runtime/exithook", "\xdc\x01\x86\x01"},
{"internal/runtime/gc", "\xbc\x01"}, {"internal/runtime/gc", "\xc6\x01"},
{"internal/runtime/gc/internal/gen", "\nc\n\x18k\x04\v\x1d\b\x10\x02"}, {"internal/runtime/gc/internal/gen", "\nf\x11\x17m\x04\v\x1f\b\x10\x02"},
{"internal/runtime/gc/scan", "\xb5\x01\a\x18\az"}, {"internal/runtime/gc/scan", "\xbe\x01\b\x19\a|"},
{"internal/runtime/maps", "\x9b\x01\x01 \n\t\t\x03z"}, {"internal/runtime/maps", "\xa4\x01\x01\x04\x15\b\x03\a\n\t\x03.N"},
{"internal/runtime/math", "\xbc\x01"}, {"internal/runtime/math", "\xc6\x01"},
{"internal/runtime/pprof/label", ""}, {"internal/runtime/pprof/label", ""},
{"internal/runtime/startlinetest", ""}, {"internal/runtime/startlinetest", ""},
{"internal/runtime/sys", "\xbc\x01\x04"}, {"internal/runtime/sys", "\xc6\x01\x04"},
{"internal/runtime/syscall/linux", "\xbc\x01\x99\x01"}, {"internal/runtime/syscall/linux", "\xc6\x01\x9c\x01"},
{"internal/runtime/wasitest", ""}, {"internal/runtime/wasitest", ""},
{"internal/saferio", "\xfa\x01["}, {"internal/saferio", "\x85\x02]"},
{"internal/singleflight", "\xc0\x02"}, {"internal/singleflight", "\xcd\x02"},
{"internal/strconv", "\x89\x02L"}, {"internal/strconv", "\x94\x02N"},
{"internal/stringslite", "\x9f\x01\xb6\x01"}, {"internal/stringslite", "\xa8\x01\xba\x01"},
{"internal/sync", "\x9b\x01!\x13r\x14"}, {"internal/sync", "\xa4\x01\"\x14t\x14"},
{"internal/synctest", "\x9b\x01\xba\x01"}, {"internal/synctest", "\xa4\x01\xbe\x01"},
{"internal/syscall/execenv", "\xc2\x02"}, {"internal/syscall/execenv", "\xcf\x02"},
{"internal/syscall/unix", "\xb3\x02\x0e\x01\x13"}, {"internal/syscall/unix", "\xeb\x01U\x0e\x01\x13"},
{"internal/sysinfo", "\x02\x01\xb2\x01E,\x18\x02"}, {"internal/sysinfo", "\x02\x01\xbb\x01G.\x18\x02"},
{"internal/syslist", ""}, {"internal/syslist", ""},
{"internal/testenv", "\x03\ng\x02\x01*\x1b\x0f0+\x01\x05\a\n\x01\x02\x02\x01\f"}, {"internal/testenv", "\x03\nq\x02\x01)\x1c\x100-\x01\x05\a\n\x01\x02\x02\x01\f"},
{"internal/testhash", "\x03\x87\x01p\x118\f"}, {"internal/testhash", "\x03\x90\x01r\x11:\f"},
{"internal/testlog", "\xc0\x02\x01\x14"}, {"internal/testlog", "\xcd\x02\x01\x14"},
{"internal/testpty", "t\x03\xaf\x01"}, {"internal/testpty", "~\x03\xb2\x01"},
{"internal/trace", "\x02\x01\x01\x06c\a\x03w\x03\x03\x06\x03\t+\n\x01\x01\x01\x11\x06"}, {"internal/trace", "\x02\x01\x01\x06f\x0e\x03x\x03\x03\x06\x03\t-\n\x01\x01\x01\x11\x06"},
{"internal/trace/internal/testgen", "\x03j\nu\x03\x02\x03\x011\v\r\x11"}, {"internal/trace/internal/testgen", "\x03m\x11v\x03\x02\x03\x013\v\r\x11"},
{"internal/trace/internal/tracev1", "\x03\x01i\a\x03}\x06\f5\x01"}, {"internal/trace/internal/tracev1", "\x03\x01l\x0e\x03~\x06\f7\x01"},
{"internal/trace/raw", "\x02k\nz\x03\x06C\x01\x13"}, {"internal/trace/raw", "\x02n\x11{\x03\x06E\x01\x13"},
{"internal/trace/testtrace", "\x02\x01q\x03q\x04\x03\x05\x01\x05,\v\x02\b\x02\x01\x05"}, {"internal/trace/testtrace", "\x02\x01{\x03r\x04\x03\x05\x01\x05.\v\x02\b\x02\x01\x05"},
{"internal/trace/tracev2", ""}, {"internal/trace/tracev2", ""},
{"internal/trace/traceviewer", "\x02d\v\x06\x1a<\x1f\a\a\x04\b\v\x15\x01\x05\a\n\x01\x02\x0f"}, {"internal/trace/traceviewer", "\x02g\v\r\x19>\x1f\a\a\x04\b\v\x17\x01\x05\a\n\x01\x02\x0f"},
{"internal/trace/traceviewer/format", ""}, {"internal/trace/traceviewer/format", ""},
{"internal/trace/version", "wz\t"}, {"internal/trace/version", "\x81\x01{\t"},
{"internal/txtar", "\x03t\xaf\x01\x18"}, {"internal/txtar", "\x03~\xb2\x01\x18"},
{"internal/types/errors", "\xbd\x02"}, {"internal/types/errors", "\xca\x02"},
{"internal/unsafeheader", "\xd5\x02"}, {"internal/unsafeheader", "\xe2\x02"},
{"internal/xcoff", "`\r\a\x03g\x1c,\x17\x01"}, {"internal/xcoff", "c\r\x0e\x03h\x1c.\x17\x01"},
{"internal/zstd", "m\a\x03\x83\x01\x0f"}, {"internal/zstd", "p\x0e\x03\x84\x01\x0f"},
{"io", "t\xcc\x01"}, {"io", "~\xcf\x01"},
{"io/fs", "t+*11\x10\x14\x04"}, {"io/fs", "~*,13\x10\x14\x04"},
{"io/ioutil", "\xfa\x01\x01+\x15\x03"}, {"io/ioutil", "\x85\x02\x01-\x15\x03"},
{"iter", "\xcf\x01d\""}, {"iter", "\xda\x01f\""},
{"log", "w\x83\x01\x05'\r\r\x01\x0e"}, {"log", "\x81\x01\x84\x01\x05)\r\r\x01\x0e"},
{"log/internal", ""}, {"log/internal", ""},
{"log/slog", "\x03\n[\t\x03\x03\x83\x01\x04\x01\x02\x02\x03(\x05\b\x02\x01\x02\x01\x0e\x02\x02\x02"}, {"log/slog", "\x03\n^\t\n\x03H<\x04\x01\x02\x02\x03*\x05\b\x02\x01\x02\x01\x0e\x02\x02\x02"},
{"log/slog/internal", ""}, {"log/slog/internal", ""},
{"log/slog/internal/benchmarks", "\rg\x03\x83\x01\x06\x03:\x12"}, {"log/slog/internal/benchmarks", "\rq\x03\x84\x01\x06\x03<\x12"},
{"log/slog/internal/buffer", "\xc0\x02"}, {"log/slog/internal/buffer", "\xcd\x02"},
{"log/syslog", "t\x03\x87\x01\x12\x16\x18\x02\x0f"}, {"log/syslog", "~\x03\x88\x01\x12\x18\x18\x02\x0f"},
{"maps", "\xfd\x01X"}, {"maps", "\x88\x02Z"},
{"math", "\xb5\x01TL"}, {"math", "\xbe\x01VN"},
{"math/big", "\x03q\x03)\x15E\f\x03\x020\x02\x01\x02\x15"}, {"math/big", "\x03{\x03(\x15G\f\x03\x022\x02\x01\x02\x15"},
{"math/big/internal/asmgen", "\x03\x01s\x92\x012\x03"}, {"math/big/internal/asmgen", "\x03\x01}\x93\x014\x03"},
{"math/bits", "\xd5\x02"}, {"math/bits", "\xe2\x02"},
{"math/cmplx", "\x86\x02\x03"}, {"math/cmplx", "\x91\x02\x03"},
{"math/rand", "\xbd\x01I:\x01\x14"}, {"math/rand", "\xc7\x01J<\x01\x14"},
{"math/rand/v2", "t,\x03c\x03L"}, {"math/rand/v2", "~+\x03e\x03N"},
{"mime", "\x02\x01i\b\x03\x83\x01\v!\x15\x03\x02\x11\x02"}, {"mime", "\x02\x01l\x0f\x03\x84\x01\v#\x15\x03\x02\x11\x02"},
{"mime/multipart", "\x02\x01N#\x03F=\v\x01\a\x02\x15\x02\x06\x0f\x02\x01\x17"}, {"mime/multipart", "\x02\x01P+\x03F>\v\x01\a\x02\x17\x02\x06\x0f\x02\x01\x17"},
{"mime/quotedprintable", "\x02\x01t\x83\x01"}, {"mime/quotedprintable", "\x02\x01~\x84\x01"},
{"net", "\x04\tg+\x1e\n\x05\x13\x01\x01\x04\x15\x01%\x06\r\b\x05\x01\x01\r\x06\a"}, {"net", "\x04\tq*\x1f\v\x05\x13\x01\x01\x04\x15\x01'\x06\r\b\x05\x01\x01\r\x06\t"},
{"net/http", "\x02\x01\x03\x01\x04\x02D\b\x13\x01\a\x03F=\x01\x03\a\x01\x03\x02\x02\x01\x02\x06\x02\x01\x01\n\x01\x01\x05\x01\x02\x05\b\x01\x01\x01\x02\x01\x0e\x02\x02\x02\b\x01\x01\x01"}, {"net/http", "\x02\x01\x03\x01\x04\x02N\x14\x0f\x03F>\x01\x03\a\x01\x06\x01\x01\x02\x06\x02\x01\x01\f\x01\x01\x05\x01\x02\x05\b\x01\x01\x01\x02\x01\x0e\x02\x02\x02\n\x01\x03"},
{"net/http/cgi", "\x02W\x1b\x03\x83\x01\x04\a\v\x01\x13\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x11\x0e"}, {"net/http/cgi", "\x02Y#\x03\x84\x01\x04\a\v\x01\x15\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x11\x10"},
{"net/http/cookiejar", "\x04p\x03\x99\x01\x01\b\a\x05\x16\x03\x02\x0f\x04"}, {"net/http/cookiejar", "\x04z\x03\x9a\x01\x01\b\t\x05\x16\x03\x02\x0f\x04"},
{"net/http/fcgi", "\x02\x01\n`\a\x03\x83\x01\x16\x01\x01\x14\x18\x02\x0f"}, {"net/http/fcgi", "\x02\x01\nc\x0e\x03\x84\x01\x16\x01\x01\x16\x18\x02\x0f"},
{"net/http/httptest", "\x02\x01\nL\x02\x1b\x01\x83\x01\x04\x12\x01\n\t\x02\x17\x01\x02\x0f\x0e"}, {"net/http/httptest", "\x02\x01\nN\x02#\x01P4\x04\x12\x01\f\t\x02\r\n\x01\x02\x03\f\x06\n"},
{"net/http/httptrace", "\rLnI\x14\n!"}, {"net/http/httptrace", "\rNwI\x16+"},
{"net/http/httputil", "\x02\x01\ng\x03\x83\x01\x04\x0f\x03\x01\x05\x02\x01\v\x01\x19\x02\x01\x0e\x0e"}, {"net/http/httputil", "\x02\x01\nq\x03F>\x04\x0f\x03\x01\x05\x02\x01\r\x01\x19\x02\x01\x0e\x10"},
{"net/http/internal", "\x02\x01q\x03\x83\x01"}, {"net/http/internal", "\x02\x01m\x0e\x03\x84\x01"},
{"net/http/internal/ascii", "\xbe\x02\x13"}, {"net/http/internal/ascii", "\xcb\x02\x13"},
{"net/http/internal/httpcommon", "\rg\x03\x9f\x01\x0e\x01\x17\x01\x01\x02\x1d\x02"}, {"net/http/internal/http2", "\x02\x01\x03\x01\x06F\b\x15\x0e\x03\x84\x01\x01\x03\b\x03\x02\x03\x02\x06\x02\x03\x01\n\x01\x01\b\x05\b\x02\x01\x02\x01\x0e\x10\x02\x02"},
{"net/http/internal/testcert", "\xbe\x02"}, {"net/http/internal/httpcommon", "\rq\x03\xa0\x01\x10\x01\x17\x01\x01\x02\x1f\x02"},
{"net/http/pprof", "\x02\x01\nj\x19-\x02\x0e-\x04\x13\x14\x01\r\x04\x03\x01\x02\x01\x11"}, {"net/http/internal/httpsfv", "\xc8\x02\x02\x01\x11\x04"},
{"net/http/internal/testcert", "\xcb\x02"},
{"net/http/pprof", "\x02\x01\nt\x18.\x11-\x04\x13\x16\x01\r\x04\x03\x01\x02\x01\x11"},
{"net/internal/cgotest", ""}, {"net/internal/cgotest", ""},
{"net/internal/socktest", "w\xc9\x01\x02"}, {"net/internal/socktest", "\x81\x01\xcc\x01\x02"},
{"net/mail", "\x02r\x03\x83\x01\x04\x0f\x03\x14\x1a\x02\x0f\x04"}, {"net/mail", "\x02|\x03\x84\x01\x04\x0f\x03\x16\x1a\x02\x0f\x04"},
{"net/netip", "\x04p+\x01f\x034\x17"}, {"net/netip", "\x04z*\x01h\x036\x17"},
{"net/rpc", "\x02m\x05\x03\x10\ni\x04\x12\x01\x1d\r\x03\x02"}, {"net/rpc", "\x02p\f\x03\x0f\nk\x04\x12\x01\x1f\r\x03\x02"},
{"net/rpc/jsonrpc", "q\x03\x03\x83\x01\x16\x11\x1f"}, {"net/rpc/jsonrpc", "t\n\x03\x84\x01\x16\x13\x1f"},
{"net/smtp", "\x194\f\x13\b\x03\x83\x01\x16\x14\x1a"}, {"net/smtp", "\x195\r\x14\x0f\x03\x84\x01\x16\x16\x1a"},
{"net/textproto", "\x02\x01q\x03\x83\x01\f\n-\x01\x02\x15"}, {"net/textproto", "\x02\x01{\x03\x84\x01\f\n/\x01\x02\x15"},
{"net/url", "t\x03Fc\v\x10\x02\x01\x17"}, {"net/url", "~\x03Ff\v\x10\x02\x01\x17"},
{"os", "t+\x01\x19\x03\x10\x14\x01\x03\x01\x05\x10\x018\b\x05\x01\x01\r\x06"}, {"os", "~*\x01\x19\x04\x11\x14\x01\x03\x01\x05\x10\x01:\b\x05\x01\x01\r\x06"},
{"os/exec", "\x03\ngI'\x01\x15\x01+\x06\a\n\x01\x03\x01\r"}, {"os/exec", "\x03\nqI(\x01\x15\x01-\x06\a\n\x01\x03\x01\r"},
{"os/exec/internal/fdtest", "\xc2\x02"}, {"os/exec/internal/fdtest", "\xcf\x02"},
{"os/signal", "\r\x99\x02\x15\x05\x02"}, {"os/signal", "\r\xa6\x02\x15\x05\x02"},
{"os/user", "\x02\x01q\x03\x83\x01,\r\n\x01\x02"}, {"os/user", "\x02\x01{\x03\x84\x01.\r\n\x01\x02"},
{"path", "t+\xb4\x01"}, {"path", "~*\xb8\x01"},
{"path/filepath", "t+\x1aB+\r\b\x03\x04\x11"}, {"path/filepath", "~*\x1aD-\r\b\x03\x04\x11"},
{"plugin", "t"}, {"plugin", "~"},
{"reflect", "t'\x04\x1d\x13\b\x04\x05\x17\x06\t-\n\x03\x11\x02\x02"}, {"reflect", "~&\x04\x1e\x03\x11\b\x04\x05\x17\x06\t/\n\x03\x11\x02\x02"},
{"reflect/internal/example1", ""}, {"reflect/internal/example1", ""},
{"reflect/internal/example2", ""}, {"reflect/internal/example2", ""},
{"regexp", "\x03\xf7\x018\t\x02\x01\x02\x11\x02"}, {"regexp", "\x03\x82\x02\x037\t\x02\x01\x02\x11\x02"},
{"regexp/syntax", "\xbb\x02\x01\x01\x01\x02\x11\x02"}, {"regexp/syntax", "\xc8\x02\x01\x01\x01\x02\x11\x02"},
{"runtime", "\x9b\x01\x04\x01\x03\f\x06\a\x02\x01\x01\x0e\x03\x01\x01\x01\x02\x01\x01\x01\x02\x01\x04\x01\x10\x18L"}, {"runtime", "\xa4\x01\x04\x01\x03\f\x06\b\x02\x01\x01\x0f\x03\x01\x01\x01\x02\x01\x01\x01\x02\x01\x04\x01\x10\x18N"},
{"runtime/coverage", "\xa7\x01S"}, {"runtime/coverage", "\xb0\x01U"},
{"runtime/debug", "wUZ\r\b\x02\x01\x11\x06"}, {"runtime/debug", "\x81\x01V\\\r\b\x02\x01\x11\x06"},
{"runtime/metrics", "\xbe\x01H-\""}, {"runtime/metrics", "\xc8\x01I/\""},
{"runtime/pprof", "\x02\x01\x01\x03\x06`\a\x03$$\x0f\v!\f \r\b\x01\x01\x01\x02\x02\n\x03\x06"}, {"runtime/pprof", "\x02\x01\x01\x03\x06c\x0e\x03#5\v!\f\"\r\b\x01\x01\x01\x02\x02\n\x03\x06"},
{"runtime/race", "\xb9\x02"}, {"runtime/race", "\xc6\x02"},
{"runtime/race/internal/amd64v1", ""}, {"runtime/race/internal/amd64v1", ""},
{"runtime/trace", "\rg\x03z\t9\b\x05\x01\x0e\x06"}, {"runtime/trace", "\rq\x03{\t;\b\x05\x01\x0e\x06"},
{"slices", "\x04\xf9\x01\fL"}, {"slices", "\x04\x84\x02\fN"},
{"sort", "\xd0\x0192"}, {"sort", "\xdb\x0194"},
{"strconv", "t+A\x01r"}, {"strconv", "~*C\x01t"},
{"strings", "t'\x04B\x19\x03\f7\x11\x02\x02"}, {"strings", "~&\x04D\x19\x03\f9\x11\x02\x02"},
{"structs", ""}, {"structs", ""},
{"sync", "\xcf\x01\x13\x01P\x0e\x14"}, {"sync", "\xda\x01\x02\x11\x01R\x0e\x14"},
{"sync/atomic", "\xd5\x02"}, {"sync/atomic", "\xe2\x02"},
{"syscall", "t(\x03\x01\x1c\n\x03\x06\r\x04S\b\x05\x01\x14"}, {"syscall", "~'\x03\x01\x1d\n\x04\x06\r\x04U\b\x05\x01\x14"},
{"testing", "\x03\ng\x02\x01X\x17\x14\f\x05\x1b\x06\x02\x05\x02\x05\x01\x02\x01\x02\x01\x0e\x02\x04"}, {"testing", "\x03\nq\x02\x01Y\x17\x14\f\x05\x1d\x06\x02\x05\x02\x05\x01\x02\x01\x02\x01\x0e\x02\x04"},
{"testing/cryptotest", "QOZ\x124\x03\x12"}, {"testing/cryptotest", "SV\\\x126\x03\x12"},
{"testing/fstest", "t\x03\x83\x01\x01\n&\x10\x03\t\b"}, {"testing/fstest", "~\x03\x84\x01\x01\n(\x10\x03\t\b"},
{"testing/internal/testdeps", "\x02\v\xae\x01/\x10,\x03\x05\x03\x06\a\x02\x0f"}, {"testing/internal/testdeps", "\x02\v\xb7\x011\x10.\x03\x05\x03\x06\a\x02\x0f"},
{"testing/iotest", "\x03q\x03\x83\x01\x04"}, {"testing/iotest", "\x03{\x03\x84\x01\x04"},
{"testing/quick", "v\x01\x8f\x01\x05#\x10\x11"}, {"testing/quick", "\x80\x01\x01\x90\x01\x05%\x10\x11"},
{"testing/slogtest", "\rg\x03\x89\x01.\x05\x10\f"}, {"testing/slogtest", "\rq\x03\x8a\x010\x05\x10\f"},
{"testing/synctest", "\xe3\x01`\x12"}, {"testing/synctest", "\xee\x01b\f\x06"},
{"text/scanner", "\x03t\x83\x01,+\x02"}, {"text/scanner", "\x03~\x84\x01.+\x02"},
{"text/tabwriter", "w\x83\x01Y"}, {"text/tabwriter", "\x81\x01\x84\x01["},
{"text/template", "t\x03C@\x01\n \x01\x05\x01\x02\x05\v\x02\x0e\x03\x02"}, {"text/template", "~\x03BB\x01\n\"\x01\x05\x01\x02\x05\v\x02\x0e\x03\x02"},
{"text/template/parse", "\x03t\xbc\x01\n\x01\x13\x02"}, {"text/template/parse", "\x03~\xbf\x01\n\x01\x13\x02"},
{"time", "t+\x1e$(*\r\x02\x13"}, {"time", "~*D(,\r\x02\x13"},
{"time/tzdata", "t\xce\x01\x13"}, {"time/tzdata", "~\xd1\x01\x13"},
{"unicode", ""}, {"unicode", ""},
{"unicode/utf16", ""}, {"unicode/utf16", ""},
{"unicode/utf8", ""}, {"unicode/utf8", ""},
{"unique", "\x9b\x01!%\x01Q\r\x01\x14\x12"}, {"unique", "\xa4\x01\"&\x01S\r\x01\x14\x19"},
{"unsafe", ""}, {"unsafe", ""},
{"vendor/golang.org/x/crypto/chacha20", "\x10]\a\x95\x01*'"}, {"uuid", "\x03\x01O\x1d\x03\v\xcf\x01\x0f"},
{"vendor/golang.org/x/crypto/chacha20poly1305", "\x10\aV\a\xe2\x01\x04\x01\a"}, {"vendor/golang.org/x/crypto/chacha20", "\x10`\x0e\x96\x01,)"},
{"vendor/golang.org/x/crypto/cryptobyte", "j\n\x03\x90\x01'!\n"}, {"vendor/golang.org/x/crypto/chacha20poly1305", "\x10\aY\x0e\xe6\x01\x05\x01\f"},
{"vendor/golang.org/x/crypto/cryptobyte", "m\x11\x03\x91\x01)!\v"},
{"vendor/golang.org/x/crypto/cryptobyte/asn1", ""}, {"vendor/golang.org/x/crypto/cryptobyte/asn1", ""},
{"vendor/golang.org/x/crypto/internal/alias", "\xd5\x02"}, {"vendor/golang.org/x/crypto/hkdf", "\x18\x01e\x15r"},
{"vendor/golang.org/x/crypto/internal/poly1305", "X\x15\x9c\x01"}, {"vendor/golang.org/x/crypto/internal/alias", "\xe2\x02"},
{"vendor/golang.org/x/net/dns/dnsmessage", "t\xc7\x01"}, {"vendor/golang.org/x/crypto/internal/poly1305", "Z\x16\xa4\x01"},
{"vendor/golang.org/x/net/http/httpguts", "\x90\x02\x14\x1a\x15\r"}, {"vendor/golang.org/x/net/dns/dnsmessage", "~\xca\x01"},
{"vendor/golang.org/x/net/http/httpproxy", "t\x03\x99\x01\x10\x05\x01\x18\x15\r"}, {"vendor/golang.org/x/net/http/httpguts", "\x9b\x02\x16\x1a\x15\x10"},
{"vendor/golang.org/x/net/http2/hpack", "\x03q\x03\x83\x01F"}, {"vendor/golang.org/x/net/http/httpproxy", "~\x03\x9a\x01\x12\x05\x01\x18\x15\x10"},
{"vendor/golang.org/x/net/idna", "w\x8f\x018\x15\x10\x02\x01"}, {"vendor/golang.org/x/net/http2/hpack", "\x03{\x03\x84\x01H"},
{"vendor/golang.org/x/net/nettest", "\x03j\a\x03\x83\x01\x11\x05\x16\x01\f\n\x01\x02\x02\x01\f"}, {"vendor/golang.org/x/net/http3", "\x9c\x02@\x06\x0f\x04"},
{"vendor/golang.org/x/sys/cpu", "\xa6\x02\r\n\x01\x17"}, {"vendor/golang.org/x/net/idna", "\x81\x01\x90\x01:\x13\x02\x17\x02\x01"},
{"vendor/golang.org/x/text/secure/bidirule", "t\xdf\x01\x11\x01"}, {"vendor/golang.org/x/net/internal/http3", "\rN#\x03\x84\x01\v\x04\a\x01\x05\x10\x01\x16\x02\x01\x02\x0f\x10\x02\x04\x03"},
{"vendor/golang.org/x/text/transform", "\x03q\x86\x01Y"}, {"vendor/golang.org/x/net/internal/httpcommon", "\rq\x03\xa0\x01\x10\x01\x17\x01\x01\x02\x1f\x02"},
{"vendor/golang.org/x/text/unicode/bidi", "\x03\bl\x87\x01>\x17"}, {"vendor/golang.org/x/net/internal/quic/quicwire", "p"},
{"vendor/golang.org/x/text/unicode/norm", "m\n\x83\x01F\x13\x11"}, {"vendor/golang.org/x/net/nettest", "\x03m\x0e\x03\x84\x01\x11\x05\x18\x01\f\n\x01\x02\x02\x01\f"},
{"weak", "\x9b\x01\x98\x01\""}, {"vendor/golang.org/x/net/quic", "\x03\n\x01\x01\x01\t:\x04\x04\x15\x03\v\x03\x12r\x06\x06\x06\x04\x12\x06\x15\x02\x01\x02\x01\x01\r\x06\x02\x01\x01\x02\v"},
{"vendor/golang.org/x/sys/cpu", "\xb3\x02\r\n\x01\x17"},
{"vendor/golang.org/x/text/secure/bidirule", "~\xe2\x01\x18\x01"},
{"vendor/golang.org/x/text/transform", "\x03{\x87\x01["},
{"vendor/golang.org/x/text/unicode/bidi", "\x03\bv\x88\x01@\x17"},
{"vendor/golang.org/x/text/unicode/norm", "p\x11\x84\x01H\x13\x18"},
{"weak", "\xa4\x01\x9c\x01\""},
} }
// bootstrap is the list of bootstrap packages extracted from cmd/dist. // bootstrap is the list of bootstrap packages extracted from cmd/dist.
@@ -408,6 +428,7 @@ var bootstrap = map[string]bool{
"cmd/compile/internal/logopt": true, "cmd/compile/internal/logopt": true,
"cmd/compile/internal/loong64": true, "cmd/compile/internal/loong64": true,
"cmd/compile/internal/loopvar": true, "cmd/compile/internal/loopvar": true,
"cmd/compile/internal/midway": true,
"cmd/compile/internal/mips": true, "cmd/compile/internal/mips": true,
"cmd/compile/internal/mips64": true, "cmd/compile/internal/mips64": true,
"cmd/compile/internal/noder": true, "cmd/compile/internal/noder": true,
@@ -512,6 +533,7 @@ var bootstrap = map[string]bool{
"internal/race": true, "internal/race": true,
"internal/runtime/gc": true, "internal/runtime/gc": true,
"internal/saferio": true, "internal/saferio": true,
"internal/strconv": true,
"internal/syscall/unix": true, "internal/syscall/unix": true,
"internal/types/errors": true, "internal/types/errors": true,
"internal/unsafeheader": true, "internal/unsafeheader": true,
+286 -1
View File
@@ -270,6 +270,7 @@ var PackageSymbols = map[string][]Symbol{
{"ContainsRune", Func, 7, "func(b []byte, r rune) bool"}, {"ContainsRune", Func, 7, "func(b []byte, r rune) bool"},
{"Count", Func, 0, "func(s []byte, sep []byte) int"}, {"Count", Func, 0, "func(s []byte, sep []byte) int"},
{"Cut", Func, 18, "func(s []byte, sep []byte) (before []byte, after []byte, found bool)"}, {"Cut", Func, 18, "func(s []byte, sep []byte) (before []byte, after []byte, found bool)"},
{"CutLast", Func, 27, "func(s []byte, sep []byte) (before []byte, after []byte, found bool)"},
{"CutPrefix", Func, 20, "func(s []byte, prefix []byte) (after []byte, found bool)"}, {"CutPrefix", Func, 20, "func(s []byte, prefix []byte) (after []byte, found bool)"},
{"CutSuffix", Func, 20, "func(s []byte, suffix []byte) (before []byte, found bool)"}, {"CutSuffix", Func, 20, "func(s []byte, suffix []byte) (before []byte, found bool)"},
{"Equal", Func, 0, "func(a []byte, b []byte) bool"}, {"Equal", Func, 0, "func(a []byte, b []byte) bool"},
@@ -538,6 +539,7 @@ var PackageSymbols = map[string][]Symbol{
{"MD4", Const, 0, ""}, {"MD4", Const, 0, ""},
{"MD5", Const, 0, ""}, {"MD5", Const, 0, ""},
{"MD5SHA1", Const, 0, ""}, {"MD5SHA1", Const, 0, ""},
{"MLDSAMu", Const, 27, ""},
{"MessageSigner", Type, 25, ""}, {"MessageSigner", Type, 25, ""},
{"PrivateKey", Type, 0, ""}, {"PrivateKey", Type, 0, ""},
{"PublicKey", Type, 2, ""}, {"PublicKey", Type, 2, ""},
@@ -812,6 +814,40 @@ var PackageSymbols = map[string][]Symbol{
{"Size", Const, 0, ""}, {"Size", Const, 0, ""},
{"Sum", Func, 2, "func(data []byte) [16]byte"}, {"Sum", Func, 2, "func(data []byte) [16]byte"},
}, },
"crypto/mldsa": {
{"(*Options).HashFunc", Method, 27, ""},
{"(*PrivateKey).Bytes", Method, 27, ""},
{"(*PrivateKey).Equal", Method, 27, ""},
{"(*PrivateKey).Public", Method, 27, ""},
{"(*PrivateKey).PublicKey", Method, 27, ""},
{"(*PrivateKey).Sign", Method, 27, ""},
{"(*PrivateKey).SignDeterministic", Method, 27, ""},
{"(*PublicKey).Bytes", Method, 27, ""},
{"(*PublicKey).Equal", Method, 27, ""},
{"(*PublicKey).Parameters", Method, 27, ""},
{"(Parameters).PublicKeySize", Method, 27, ""},
{"(Parameters).SignatureSize", Method, 27, ""},
{"(Parameters).String", Method, 27, ""},
{"GenerateKey", Func, 27, "func(params Parameters) (*PrivateKey, error)"},
{"MLDSA44", Func, 27, "func() Parameters"},
{"MLDSA44PublicKeySize", Const, 27, ""},
{"MLDSA44SignatureSize", Const, 27, ""},
{"MLDSA65", Func, 27, "func() Parameters"},
{"MLDSA65PublicKeySize", Const, 27, ""},
{"MLDSA65SignatureSize", Const, 27, ""},
{"MLDSA87", Func, 27, "func() Parameters"},
{"MLDSA87PublicKeySize", Const, 27, ""},
{"MLDSA87SignatureSize", Const, 27, ""},
{"NewPrivateKey", Func, 27, "func(params Parameters, seed []byte) (*PrivateKey, error)"},
{"NewPublicKey", Func, 27, "func(params Parameters, encoding []byte) (*PublicKey, error)"},
{"Options", Type, 27, ""},
{"Options.Context", Field, 27, ""},
{"Parameters", Type, 27, ""},
{"PrivateKey", Type, 27, ""},
{"PrivateKeySize", Const, 27, ""},
{"PublicKey", Type, 27, ""},
{"Verify", Func, 27, "func(pk *PublicKey, message []byte, signature []byte, opts *Options) error"},
},
"crypto/mlkem": { "crypto/mlkem": {
{"(*DecapsulationKey1024).Bytes", Method, 24, ""}, {"(*DecapsulationKey1024).Bytes", Method, 24, ""},
{"(*DecapsulationKey1024).Decapsulate", Method, 24, ""}, {"(*DecapsulationKey1024).Decapsulate", Method, 24, ""},
@@ -1120,6 +1156,7 @@ var PackageSymbols = map[string][]Symbol{
{"ConnectionState.ECHAccepted", Field, 23, ""}, {"ConnectionState.ECHAccepted", Field, 23, ""},
{"ConnectionState.HandshakeComplete", Field, 0, ""}, {"ConnectionState.HandshakeComplete", Field, 0, ""},
{"ConnectionState.HelloRetryRequest", Field, 26, ""}, {"ConnectionState.HelloRetryRequest", Field, 26, ""},
{"ConnectionState.LocalCertificate", Field, 27, ""},
{"ConnectionState.NegotiatedProtocol", Field, 0, ""}, {"ConnectionState.NegotiatedProtocol", Field, 0, ""},
{"ConnectionState.NegotiatedProtocolIsMutual", Field, 0, ""}, {"ConnectionState.NegotiatedProtocolIsMutual", Field, 0, ""},
{"ConnectionState.OCSPResponse", Field, 5, ""}, {"ConnectionState.OCSPResponse", Field, 5, ""},
@@ -1152,6 +1189,10 @@ var PackageSymbols = map[string][]Symbol{
{"InsecureCipherSuites", Func, 14, "func() []*CipherSuite"}, {"InsecureCipherSuites", Func, 14, "func() []*CipherSuite"},
{"Listen", Func, 0, "func(network string, laddr string, config *Config) (net.Listener, error)"}, {"Listen", Func, 0, "func(network string, laddr string, config *Config) (net.Listener, error)"},
{"LoadX509KeyPair", Func, 0, "func(certFile string, keyFile string) (Certificate, error)"}, {"LoadX509KeyPair", Func, 0, "func(certFile string, keyFile string) (Certificate, error)"},
{"MLDSA44", Const, 27, ""},
{"MLDSA65", Const, 27, ""},
{"MLDSA87", Const, 27, ""},
{"MLKEM1024", Const, 27, ""},
{"NewLRUClientSessionCache", Func, 3, "func(capacity int) ClientSessionCache"}, {"NewLRUClientSessionCache", Func, 3, "func(capacity int) ClientSessionCache"},
{"NewListener", Func, 0, "func(inner net.Listener, config *Config) net.Listener"}, {"NewListener", Func, 0, "func(inner net.Listener, config *Config) net.Listener"},
{"NewResumptionState", Func, 21, "func(ticket []byte, state *SessionState) (*ClientSessionState, error)"}, {"NewResumptionState", Func, 21, "func(ticket []byte, state *SessionState) (*ClientSessionState, error)"},
@@ -1166,6 +1207,7 @@ var PackageSymbols = map[string][]Symbol{
{"ParseSessionState", Func, 21, "func(data []byte) (*SessionState, error)"}, {"ParseSessionState", Func, 21, "func(data []byte) (*SessionState, error)"},
{"QUICClient", Func, 21, "func(config *QUICConfig) *QUICConn"}, {"QUICClient", Func, 21, "func(config *QUICConfig) *QUICConn"},
{"QUICConfig", Type, 21, ""}, {"QUICConfig", Type, 21, ""},
{"QUICConfig.ClientHelloInfoConn", Field, 27, ""},
{"QUICConfig.EnableSessionEvents", Field, 23, ""}, {"QUICConfig.EnableSessionEvents", Field, 23, ""},
{"QUICConfig.TLSConfig", Field, 21, ""}, {"QUICConfig.TLSConfig", Field, 21, ""},
{"QUICConn", Type, 21, ""}, {"QUICConn", Type, 21, ""},
@@ -1334,6 +1376,7 @@ var PackageSymbols = map[string][]Symbol{
{"Certificate.PublicKeyAlgorithm", Field, 0, ""}, {"Certificate.PublicKeyAlgorithm", Field, 0, ""},
{"Certificate.Raw", Field, 0, ""}, {"Certificate.Raw", Field, 0, ""},
{"Certificate.RawIssuer", Field, 0, ""}, {"Certificate.RawIssuer", Field, 0, ""},
{"Certificate.RawSignatureAlgorithm", Field, 27, ""},
{"Certificate.RawSubject", Field, 0, ""}, {"Certificate.RawSubject", Field, 0, ""},
{"Certificate.RawSubjectPublicKeyInfo", Field, 0, ""}, {"Certificate.RawSubjectPublicKeyInfo", Field, 0, ""},
{"Certificate.RawTBSCertificate", Field, 0, ""}, {"Certificate.RawTBSCertificate", Field, 0, ""},
@@ -1362,6 +1405,7 @@ var PackageSymbols = map[string][]Symbol{
{"CertificateRequest.PublicKey", Field, 3, ""}, {"CertificateRequest.PublicKey", Field, 3, ""},
{"CertificateRequest.PublicKeyAlgorithm", Field, 3, ""}, {"CertificateRequest.PublicKeyAlgorithm", Field, 3, ""},
{"CertificateRequest.Raw", Field, 3, ""}, {"CertificateRequest.Raw", Field, 3, ""},
{"CertificateRequest.RawSignatureAlgorithm", Field, 27, ""},
{"CertificateRequest.RawSubject", Field, 3, ""}, {"CertificateRequest.RawSubject", Field, 3, ""},
{"CertificateRequest.RawSubjectPublicKeyInfo", Field, 3, ""}, {"CertificateRequest.RawSubjectPublicKeyInfo", Field, 3, ""},
{"CertificateRequest.RawTBSCertificateRequest", Field, 3, ""}, {"CertificateRequest.RawTBSCertificateRequest", Field, 3, ""},
@@ -1422,6 +1466,10 @@ var PackageSymbols = map[string][]Symbol{
{"KeyUsageKeyEncipherment", Const, 0, ""}, {"KeyUsageKeyEncipherment", Const, 0, ""},
{"MD2WithRSA", Const, 0, ""}, {"MD2WithRSA", Const, 0, ""},
{"MD5WithRSA", Const, 0, ""}, {"MD5WithRSA", Const, 0, ""},
{"MLDSA", Const, 27, ""},
{"MLDSA44", Const, 27, ""},
{"MLDSA65", Const, 27, ""},
{"MLDSA87", Const, 27, ""},
{"MarshalECPrivateKey", Func, 2, "func(key *ecdsa.PrivateKey) ([]byte, error)"}, {"MarshalECPrivateKey", Func, 2, "func(key *ecdsa.PrivateKey) ([]byte, error)"},
{"MarshalPKCS1PrivateKey", Func, 0, "func(key *rsa.PrivateKey) []byte"}, {"MarshalPKCS1PrivateKey", Func, 0, "func(key *rsa.PrivateKey) []byte"},
{"MarshalPKCS1PublicKey", Func, 10, "func(key *rsa.PublicKey) []byte"}, {"MarshalPKCS1PublicKey", Func, 10, "func(key *rsa.PublicKey) []byte"},
@@ -1468,6 +1516,7 @@ var PackageSymbols = map[string][]Symbol{
{"RevocationList.Number", Field, 15, ""}, {"RevocationList.Number", Field, 15, ""},
{"RevocationList.Raw", Field, 19, ""}, {"RevocationList.Raw", Field, 19, ""},
{"RevocationList.RawIssuer", Field, 19, ""}, {"RevocationList.RawIssuer", Field, 19, ""},
{"RevocationList.RawSignatureAlgorithm", Field, 27, ""},
{"RevocationList.RawTBSRevocationList", Field, 19, ""}, {"RevocationList.RawTBSRevocationList", Field, 19, ""},
{"RevocationList.RevokedCertificateEntries", Field, 21, ""}, {"RevocationList.RevokedCertificateEntries", Field, 21, ""},
{"RevocationList.RevokedCertificates", Field, 15, ""}, {"RevocationList.RevokedCertificates", Field, 15, ""},
@@ -1648,6 +1697,7 @@ var PackageSymbols = map[string][]Symbol{
{"(Scanner).Scan", Method, 0, ""}, {"(Scanner).Scan", Method, 0, ""},
{"ColumnType", Type, 8, ""}, {"ColumnType", Type, 8, ""},
{"Conn", Type, 9, ""}, {"Conn", Type, 9, ""},
{"ConvertAssign", Func, 27, "func(scanCtx driver.ScanContext, dest any, src driver.Value) error"},
{"DB", Type, 0, ""}, {"DB", Type, 0, ""},
{"DBStats", Type, 5, ""}, {"DBStats", Type, 5, ""},
{"DBStats.Idle", Field, 11, ""}, {"DBStats.Idle", Field, 11, ""},
@@ -1744,6 +1794,11 @@ var PackageSymbols = map[string][]Symbol{
{"(Rows).Next", Method, 0, ""}, {"(Rows).Next", Method, 0, ""},
{"(RowsAffected).LastInsertId", Method, 0, ""}, {"(RowsAffected).LastInsertId", Method, 0, ""},
{"(RowsAffected).RowsAffected", Method, 0, ""}, {"(RowsAffected).RowsAffected", Method, 0, ""},
{"(RowsColumnScanner).Close", Method, 27, ""},
{"(RowsColumnScanner).Columns", Method, 27, ""},
{"(RowsColumnScanner).Next", Method, 27, ""},
{"(RowsColumnScanner).NextRow", Method, 27, ""},
{"(RowsColumnScanner).ScanColumn", Method, 27, ""},
{"(RowsColumnTypeDatabaseTypeName).Close", Method, 8, ""}, {"(RowsColumnTypeDatabaseTypeName).Close", Method, 8, ""},
{"(RowsColumnTypeDatabaseTypeName).ColumnTypeDatabaseTypeName", Method, 8, ""}, {"(RowsColumnTypeDatabaseTypeName).ColumnTypeDatabaseTypeName", Method, 8, ""},
{"(RowsColumnTypeDatabaseTypeName).Columns", Method, 8, ""}, {"(RowsColumnTypeDatabaseTypeName).Columns", Method, 8, ""},
@@ -1815,12 +1870,14 @@ var PackageSymbols = map[string][]Symbol{
{"ResultNoRows", Var, 0, ""}, {"ResultNoRows", Var, 0, ""},
{"Rows", Type, 0, ""}, {"Rows", Type, 0, ""},
{"RowsAffected", Type, 0, ""}, {"RowsAffected", Type, 0, ""},
{"RowsColumnScanner", Type, 27, ""},
{"RowsColumnTypeDatabaseTypeName", Type, 8, ""}, {"RowsColumnTypeDatabaseTypeName", Type, 8, ""},
{"RowsColumnTypeLength", Type, 8, ""}, {"RowsColumnTypeLength", Type, 8, ""},
{"RowsColumnTypeNullable", Type, 8, ""}, {"RowsColumnTypeNullable", Type, 8, ""},
{"RowsColumnTypePrecisionScale", Type, 8, ""}, {"RowsColumnTypePrecisionScale", Type, 8, ""},
{"RowsColumnTypeScanType", Type, 8, ""}, {"RowsColumnTypeScanType", Type, 8, ""},
{"RowsNextResultSet", Type, 8, ""}, {"RowsNextResultSet", Type, 8, ""},
{"ScanContext", Type, 27, ""},
{"SessionResetter", Type, 10, ""}, {"SessionResetter", Type, 10, ""},
{"Stmt", Type, 0, ""}, {"Stmt", Type, 0, ""},
{"StmtExecContext", Type, 8, ""}, {"StmtExecContext", Type, 8, ""},
@@ -5038,24 +5095,32 @@ var PackageSymbols = map[string][]Symbol{
{"(*InvalidUnmarshalError).Error", Method, 0, ""}, {"(*InvalidUnmarshalError).Error", Method, 0, ""},
{"(*MarshalerError).Error", Method, 0, ""}, {"(*MarshalerError).Error", Method, 0, ""},
{"(*MarshalerError).Unwrap", Method, 13, ""}, {"(*MarshalerError).Unwrap", Method, 13, ""},
{"(*Number).UnmarshalJSONFrom", Method, 27, ""},
{"(*RawMessage).MarshalJSON", Method, 0, ""}, {"(*RawMessage).MarshalJSON", Method, 0, ""},
{"(*RawMessage).UnmarshalJSON", Method, 0, ""}, {"(*RawMessage).UnmarshalJSON", Method, 0, ""},
{"(*SyntaxError).Error", Method, 0, ""}, {"(*SyntaxError).Error", Method, 0, ""},
{"(*UnmarshalFieldError).Error", Method, 0, ""}, {"(*UnmarshalFieldError).Error", Method, 0, ""},
{"(*UnmarshalTypeError).Error", Method, 0, ""}, {"(*UnmarshalTypeError).Error", Method, 0, ""},
{"(*UnmarshalTypeError).Unwrap", Method, 27, ""},
{"(*UnsupportedTypeError).Error", Method, 0, ""}, {"(*UnsupportedTypeError).Error", Method, 0, ""},
{"(*UnsupportedValueError).Error", Method, 0, ""}, {"(*UnsupportedValueError).Error", Method, 0, ""},
{"(Delim).String", Method, 5, ""}, {"(Delim).String", Method, 5, ""},
{"(Marshaler).MarshalJSON", Method, 0, ""}, {"(Marshaler).MarshalJSON", Method, 0, ""},
{"(Number).Float64", Method, 1, ""}, {"(Number).Float64", Method, 1, ""},
{"(Number).Int64", Method, 1, ""}, {"(Number).Int64", Method, 1, ""},
{"(Number).MarshalJSONTo", Method, 27, ""},
{"(Number).String", Method, 1, ""}, {"(Number).String", Method, 1, ""},
{"(RawMessage).MarshalJSON", Method, 8, ""}, {"(RawMessage).MarshalJSON", Method, 8, ""},
{"(Unmarshaler).UnmarshalJSON", Method, 0, ""}, {"(Unmarshaler).UnmarshalJSON", Method, 0, ""},
{"CallMethodsWithLegacySemantics", Func, 27, "func(v bool) Options"},
{"Compact", Func, 0, "func(dst *bytes.Buffer, src []byte) error"}, {"Compact", Func, 0, "func(dst *bytes.Buffer, src []byte) error"},
{"Decoder", Type, 0, ""}, {"Decoder", Type, 0, ""},
{"DefaultOptionsV1", Func, 27, "func() Options"},
{"Delim", Type, 5, ""}, {"Delim", Type, 5, ""},
{"Encoder", Type, 0, ""}, {"Encoder", Type, 0, ""},
{"FormatByteArrayAsArray", Func, 27, "func(v bool) Options"},
{"FormatBytesWithLegacySemantics", Func, 27, "func(v bool) Options"},
{"FormatDurationAsNano", Func, 27, "func(v bool) Options"},
{"HTMLEscape", Func, 0, "func(dst *bytes.Buffer, src []byte)"}, {"HTMLEscape", Func, 0, "func(dst *bytes.Buffer, src []byte)"},
{"Indent", Func, 0, "func(dst *bytes.Buffer, src []byte, prefix string, indent string) error"}, {"Indent", Func, 0, "func(dst *bytes.Buffer, src []byte, prefix string, indent string) error"},
{"InvalidUTF8Error", Type, 0, ""}, {"InvalidUTF8Error", Type, 0, ""},
@@ -5068,19 +5133,29 @@ var PackageSymbols = map[string][]Symbol{
{"MarshalerError", Type, 0, ""}, {"MarshalerError", Type, 0, ""},
{"MarshalerError.Err", Field, 0, ""}, {"MarshalerError.Err", Field, 0, ""},
{"MarshalerError.Type", Field, 0, ""}, {"MarshalerError.Type", Field, 0, ""},
{"MatchCaseSensitiveDelimiter", Func, 27, "func(v bool) Options"},
{"MergeWithLegacySemantics", Func, 27, "func(v bool) Options"},
{"NewDecoder", Func, 0, "func(r io.Reader) *Decoder"}, {"NewDecoder", Func, 0, "func(r io.Reader) *Decoder"},
{"NewEncoder", Func, 0, "func(w io.Writer) *Encoder"}, {"NewEncoder", Func, 0, "func(w io.Writer) *Encoder"},
{"Number", Type, 1, ""}, {"Number", Type, 1, ""},
{"OmitEmptyWithLegacySemantics", Func, 27, "func(v bool) Options"},
{"Options", Type, 27, ""},
{"ParseBytesWithLooseRFC4648", Func, 27, "func(v bool) Options"},
{"ParseTimeWithLooseRFC3339", Func, 27, "func(v bool) Options"},
{"RawMessage", Type, 0, ""}, {"RawMessage", Type, 0, ""},
{"ReportErrorsWithLegacySemantics", Func, 27, "func(v bool) Options"},
{"StringifyWithLegacySemantics", Func, 27, "func(v bool) Options"},
{"SyntaxError", Type, 0, ""}, {"SyntaxError", Type, 0, ""},
{"SyntaxError.Offset", Field, 0, ""}, {"SyntaxError.Offset", Field, 0, ""},
{"Token", Type, 5, ""}, {"Token", Type, 5, ""},
{"Unmarshal", Func, 0, "func(data []byte, v any) error"}, {"Unmarshal", Func, 0, "func(data []byte, v any) error"},
{"UnmarshalArrayFromAnyLength", Func, 27, "func(v bool) Options"},
{"UnmarshalFieldError", Type, 0, ""}, {"UnmarshalFieldError", Type, 0, ""},
{"UnmarshalFieldError.Field", Field, 0, ""}, {"UnmarshalFieldError.Field", Field, 0, ""},
{"UnmarshalFieldError.Key", Field, 0, ""}, {"UnmarshalFieldError.Key", Field, 0, ""},
{"UnmarshalFieldError.Type", Field, 0, ""}, {"UnmarshalFieldError.Type", Field, 0, ""},
{"UnmarshalTypeError", Type, 0, ""}, {"UnmarshalTypeError", Type, 0, ""},
{"UnmarshalTypeError.Err", Field, 27, ""},
{"UnmarshalTypeError.Field", Field, 8, ""}, {"UnmarshalTypeError.Field", Field, 8, ""},
{"UnmarshalTypeError.Offset", Field, 5, ""}, {"UnmarshalTypeError.Offset", Field, 5, ""},
{"UnmarshalTypeError.Struct", Field, 8, ""}, {"UnmarshalTypeError.Struct", Field, 8, ""},
@@ -5094,6 +5169,158 @@ var PackageSymbols = map[string][]Symbol{
{"UnsupportedValueError.Value", Field, 0, ""}, {"UnsupportedValueError.Value", Field, 0, ""},
{"Valid", Func, 9, "func(data []byte) bool"}, {"Valid", Func, 9, "func(data []byte) bool"},
}, },
"encoding/json/jsontext": {
{"(*Decoder).InputOffset", Method, 27, ""},
{"(*Decoder).Options", Method, 27, ""},
{"(*Decoder).PeekKind", Method, 27, ""},
{"(*Decoder).ReadToken", Method, 27, ""},
{"(*Decoder).ReadValue", Method, 27, ""},
{"(*Decoder).Reset", Method, 27, ""},
{"(*Decoder).SkipValue", Method, 27, ""},
{"(*Decoder).StackDepth", Method, 27, ""},
{"(*Decoder).StackIndex", Method, 27, ""},
{"(*Decoder).StackPointer", Method, 27, ""},
{"(*Decoder).UnreadBuffer", Method, 27, ""},
{"(*Encoder).AvailableBuffer", Method, 27, ""},
{"(*Encoder).Options", Method, 27, ""},
{"(*Encoder).OutputOffset", Method, 27, ""},
{"(*Encoder).Reset", Method, 27, ""},
{"(*Encoder).StackDepth", Method, 27, ""},
{"(*Encoder).StackIndex", Method, 27, ""},
{"(*Encoder).StackPointer", Method, 27, ""},
{"(*Encoder).WriteToken", Method, 27, ""},
{"(*Encoder).WriteValue", Method, 27, ""},
{"(*SyntacticError).Error", Method, 27, ""},
{"(*SyntacticError).Unwrap", Method, 27, ""},
{"(*Value).Canonicalize", Method, 27, ""},
{"(*Value).Compact", Method, 27, ""},
{"(*Value).Format", Method, 27, ""},
{"(*Value).Indent", Method, 27, ""},
{"(*Value).UnmarshalJSON", Method, 27, ""},
{"(Kind).String", Method, 27, ""},
{"(Pointer).AppendToken", Method, 27, ""},
{"(Pointer).Contains", Method, 27, ""},
{"(Pointer).IsValid", Method, 27, ""},
{"(Pointer).LastToken", Method, 27, ""},
{"(Pointer).Parent", Method, 27, ""},
{"(Pointer).Tokens", Method, 27, ""},
{"(Token).Bool", Method, 27, ""},
{"(Token).Clone", Method, 27, ""},
{"(Token).Float", Method, 27, ""},
{"(Token).Float32", Method, 27, ""},
{"(Token).Int", Method, 27, ""},
{"(Token).Kind", Method, 27, ""},
{"(Token).String", Method, 27, ""},
{"(Token).Uint", Method, 27, ""},
{"(Value).Clone", Method, 27, ""},
{"(Value).IsValid", Method, 27, ""},
{"(Value).Kind", Method, 27, ""},
{"(Value).MarshalJSON", Method, 27, ""},
{"(Value).String", Method, 27, ""},
{"AllowDuplicateNames", Func, 27, "func(v bool) Options"},
{"AllowInvalidUTF8", Func, 27, "func(v bool) Options"},
{"AppendFloat", Func, 27, "func(dst []byte, src float64, bits int) []byte"},
{"AppendFormat", Func, 27, "func[Bytes ~[]byte | ~string](dst []byte, src Bytes, opts ...Options) ([]byte, error)"},
{"AppendQuote", Func, 27, "func[Bytes ~[]byte | ~string](dst []byte, src Bytes) ([]byte, error)"},
{"AppendUnquote", Func, 27, "func[Bytes ~[]byte | ~string](dst []byte, src Bytes) ([]byte, error)"},
{"BeginArray", Var, 27, ""},
{"BeginObject", Var, 27, ""},
{"Bool", Func, 27, "func(b bool) Token"},
{"CanonicalizeRawFloats", Func, 27, "func(v bool) Options"},
{"CanonicalizeRawInts", Func, 27, "func(v bool) Options"},
{"Decoder", Type, 27, ""},
{"Encoder", Type, 27, ""},
{"EndArray", Var, 27, ""},
{"EndObject", Var, 27, ""},
{"ErrDuplicateName", Var, 27, ""},
{"ErrNonStringName", Var, 27, ""},
{"EscapeForHTML", Func, 27, "func(v bool) Options"},
{"EscapeForJS", Func, 27, "func(v bool) Options"},
{"False", Var, 27, ""},
{"Float", Func, 27, "func(n float64) Token"},
{"Float32", Func, 27, "func(n float32) Token"},
{"Int", Func, 27, "func(n int64) Token"},
{"Internal", Var, 27, ""},
{"Kind", Type, 27, ""},
{"KindBeginArray", Const, 27, ""},
{"KindBeginObject", Const, 27, ""},
{"KindEndArray", Const, 27, ""},
{"KindEndObject", Const, 27, ""},
{"KindFalse", Const, 27, ""},
{"KindInvalid", Const, 27, ""},
{"KindNull", Const, 27, ""},
{"KindNumber", Const, 27, ""},
{"KindString", Const, 27, ""},
{"KindTrue", Const, 27, ""},
{"Multiline", Func, 27, "func(v bool) Options"},
{"NewDecoder", Func, 27, "func(r io.Reader, opts ...Options) *Decoder"},
{"NewEncoder", Func, 27, "func(w io.Writer, opts ...Options) *Encoder"},
{"Null", Var, 27, ""},
{"Options", Type, 27, ""},
{"Pointer", Type, 27, ""},
{"PreserveRawStrings", Func, 27, "func(v bool) Options"},
{"ReorderRawObjects", Func, 27, "func(v bool) Options"},
{"SpaceAfterColon", Func, 27, "func(v bool) Options"},
{"SpaceAfterComma", Func, 27, "func(v bool) Options"},
{"String", Func, 27, "func(s string) Token"},
{"SyntacticError", Type, 27, ""},
{"SyntacticError.ByteOffset", Field, 27, ""},
{"SyntacticError.Err", Field, 27, ""},
{"SyntacticError.JSONPointer", Field, 27, ""},
{"Token", Type, 27, ""},
{"True", Var, 27, ""},
{"Uint", Func, 27, "func(n uint64) Token"},
{"Value", Type, 27, ""},
{"WithIndent", Func, 27, "func(indent string) Options"},
{"WithIndentPrefix", Func, 27, "func(prefix string) Options"},
},
"encoding/json/v2": {
{"(*SemanticError).Error", Method, 27, ""},
{"(*SemanticError).Unwrap", Method, 27, ""},
{"(Marshaler).MarshalJSON", Method, 27, ""},
{"(MarshalerTo).MarshalJSONTo", Method, 27, ""},
{"(Unmarshaler).UnmarshalJSON", Method, 27, ""},
{"(UnmarshalerFrom).UnmarshalJSONFrom", Method, 27, ""},
{"DefaultOptionsV2", Func, 27, "func() Options"},
{"Deterministic", Func, 27, "func(v bool) Options"},
{"ErrUnknownName", Var, 27, ""},
{"FormatNilMapAsNull", Func, 27, "func(v bool) Options"},
{"FormatNilSliceAsNull", Func, 27, "func(v bool) Options"},
{"GetOption", Func, 27, "func[T any](opts Options, setter func(T) Options) (T, bool)"},
{"JoinMarshalers", Func, 27, "func(ms ...*Marshalers) *Marshalers"},
{"JoinOptions", Func, 27, "func(srcs ...Options) Options"},
{"JoinUnmarshalers", Func, 27, "func(us ...*Unmarshalers) *Unmarshalers"},
{"Marshal", Func, 27, "func(in any, opts ...Options) (out []byte, err error)"},
{"MarshalEncode", Func, 27, "func(out *jsontext.Encoder, in any, opts ...Options) (err error)"},
{"MarshalFunc", Func, 27, "func[T any](fn func(T) ([]byte, error)) *Marshalers"},
{"MarshalToFunc", Func, 27, "func[T any](fn func(*jsontext.Encoder, T) error) *Marshalers"},
{"MarshalWrite", Func, 27, "func(out io.Writer, in any, opts ...Options) (err error)"},
{"Marshaler", Type, 27, ""},
{"MarshalerTo", Type, 27, ""},
{"Marshalers", Type, 27, ""},
{"MatchCaseInsensitiveNames", Func, 27, "func(v bool) Options"},
{"OmitZeroStructFields", Func, 27, "func(v bool) Options"},
{"Options", Type, 27, ""},
{"RejectUnknownMembers", Func, 27, "func(v bool) Options"},
{"SemanticError", Type, 27, ""},
{"SemanticError.ByteOffset", Field, 27, ""},
{"SemanticError.Err", Field, 27, ""},
{"SemanticError.GoType", Field, 27, ""},
{"SemanticError.JSONKind", Field, 27, ""},
{"SemanticError.JSONPointer", Field, 27, ""},
{"SemanticError.JSONValue", Field, 27, ""},
{"StringifyNumbers", Func, 27, "func(v bool) Options"},
{"Unmarshal", Func, 27, "func(in []byte, out any, opts ...Options) (err error)"},
{"UnmarshalDecode", Func, 27, "func(in *jsontext.Decoder, out any, opts ...Options) (err error)"},
{"UnmarshalFromFunc", Func, 27, "func[T any](fn func(*jsontext.Decoder, T) error) *Unmarshalers"},
{"UnmarshalFunc", Func, 27, "func[T any](fn func([]byte, T) error) *Unmarshalers"},
{"UnmarshalRead", Func, 27, "func(in io.Reader, out any, opts ...Options) (err error)"},
{"Unmarshaler", Type, 27, ""},
{"UnmarshalerFrom", Type, 27, ""},
{"Unmarshalers", Type, 27, ""},
{"WithMarshalers", Func, 27, "func(v *Marshalers) Options"},
{"WithUnmarshalers", Func, 27, "func(v *Unmarshalers) Options"},
},
"encoding/pem": { "encoding/pem": {
{"Block", Type, 0, ""}, {"Block", Type, 0, ""},
{"Block.Bytes", Field, 0, ""}, {"Block.Bytes", Field, 0, ""},
@@ -6002,6 +6229,7 @@ var PackageSymbols = map[string][]Symbol{
{"Shift", Func, 5, "func(x Value, op token.Token, s uint) Value"}, {"Shift", Func, 5, "func(x Value, op token.Token, s uint) Value"},
{"Sign", Func, 5, "func(x Value) int"}, {"Sign", Func, 5, "func(x Value) int"},
{"String", Const, 5, ""}, {"String", Const, 5, ""},
{"StringLen", Func, 27, "func(x Value) int64"},
{"StringVal", Func, 5, "func(x Value) string"}, {"StringVal", Func, 5, "func(x Value) string"},
{"ToComplex", Func, 6, "func(x Value) Value"}, {"ToComplex", Func, 6, "func(x Value) Value"},
{"ToFloat", Func, 6, "func(x Value) Value"}, {"ToFloat", Func, 6, "func(x Value) Value"},
@@ -6183,6 +6411,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*ErrorList).Add", Method, 0, ""}, {"(*ErrorList).Add", Method, 0, ""},
{"(*ErrorList).RemoveMultiples", Method, 0, ""}, {"(*ErrorList).RemoveMultiples", Method, 0, ""},
{"(*ErrorList).Reset", Method, 0, ""}, {"(*ErrorList).Reset", Method, 0, ""},
{"(*Scanner).End", Method, 27, ""},
{"(*Scanner).Init", Method, 0, ""}, {"(*Scanner).Init", Method, 0, ""},
{"(*Scanner).Scan", Method, 0, ""}, {"(*Scanner).Scan", Method, 0, ""},
{"(Error).Error", Method, 0, ""}, {"(Error).Error", Method, 0, ""},
@@ -6222,6 +6451,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*File).SetLines", Method, 0, ""}, {"(*File).SetLines", Method, 0, ""},
{"(*File).SetLinesForContent", Method, 0, ""}, {"(*File).SetLinesForContent", Method, 0, ""},
{"(*File).Size", Method, 0, ""}, {"(*File).Size", Method, 0, ""},
{"(*File).String", Method, 27, ""},
{"(*FileSet).AddExistingFiles", Method, 25, ""}, {"(*FileSet).AddExistingFiles", Method, 25, ""},
{"(*FileSet).AddFile", Method, 0, ""}, {"(*FileSet).AddFile", Method, 0, ""},
{"(*FileSet).Base", Method, 0, ""}, {"(*FileSet).Base", Method, 0, ""},
@@ -6529,6 +6759,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*Tuple).Variables", Method, 24, ""}, {"(*Tuple).Variables", Method, 24, ""},
{"(*TypeList).At", Method, 18, ""}, {"(*TypeList).At", Method, 18, ""},
{"(*TypeList).Len", Method, 18, ""}, {"(*TypeList).Len", Method, 18, ""},
{"(*TypeList).String", Method, 27, ""},
{"(*TypeList).Types", Method, 24, ""}, {"(*TypeList).Types", Method, 24, ""},
{"(*TypeName).Exported", Method, 5, ""}, {"(*TypeName).Exported", Method, 5, ""},
{"(*TypeName).Id", Method, 5, ""}, {"(*TypeName).Id", Method, 5, ""},
@@ -6547,6 +6778,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*TypeParam).Underlying", Method, 18, ""}, {"(*TypeParam).Underlying", Method, 18, ""},
{"(*TypeParamList).At", Method, 18, ""}, {"(*TypeParamList).At", Method, 18, ""},
{"(*TypeParamList).Len", Method, 18, ""}, {"(*TypeParamList).Len", Method, 18, ""},
{"(*TypeParamList).String", Method, 27, ""},
{"(*TypeParamList).TypeParams", Method, 24, ""}, {"(*TypeParamList).TypeParams", Method, 24, ""},
{"(*Union).Len", Method, 18, ""}, {"(*Union).Len", Method, 18, ""},
{"(*Union).String", Method, 18, ""}, {"(*Union).String", Method, 18, ""},
@@ -6571,9 +6803,14 @@ var PackageSymbols = map[string][]Symbol{
{"(Checker).PkgNameOf", Method, 22, ""}, {"(Checker).PkgNameOf", Method, 22, ""},
{"(Checker).TypeOf", Method, 5, ""}, {"(Checker).TypeOf", Method, 5, ""},
{"(Error).Error", Method, 5, ""}, {"(Error).Error", Method, 5, ""},
{"(Hasher).Equal", Method, 27, ""},
{"(Hasher).Hash", Method, 27, ""},
{"(HasherIgnoreTags).Equal", Method, 27, ""},
{"(HasherIgnoreTags).Hash", Method, 27, ""},
{"(Importer).Import", Method, 5, ""}, {"(Importer).Import", Method, 5, ""},
{"(ImporterFrom).Import", Method, 6, ""}, {"(ImporterFrom).Import", Method, 6, ""},
{"(ImporterFrom).ImportFrom", Method, 6, ""}, {"(ImporterFrom).ImportFrom", Method, 6, ""},
{"(Instance).String", Method, 27, ""},
{"(Object).Exported", Method, 5, ""}, {"(Object).Exported", Method, 5, ""},
{"(Object).Id", Method, 5, ""}, {"(Object).Id", Method, 5, ""},
{"(Object).Name", Method, 5, ""}, {"(Object).Name", Method, 5, ""},
@@ -6643,6 +6880,8 @@ var PackageSymbols = map[string][]Symbol{
{"Float32", Const, 5, ""}, {"Float32", Const, 5, ""},
{"Float64", Const, 5, ""}, {"Float64", Const, 5, ""},
{"Func", Type, 5, ""}, {"Func", Type, 5, ""},
{"Hasher", Type, 27, ""},
{"HasherIgnoreTags", Type, 27, ""},
{"Id", Func, 5, "func(pkg *Package, name string) string"}, {"Id", Func, 5, "func(pkg *Package, name string) string"},
{"Identical", Func, 5, "func(x Type, y Type) bool"}, {"Identical", Func, 5, "func(x Type, y Type) bool"},
{"IdenticalIgnoreTags", Func, 8, "func(x Type, y Type) bool"}, {"IdenticalIgnoreTags", Func, 8, "func(x Type, y Type) bool"},
@@ -6877,9 +7116,13 @@ var PackageSymbols = map[string][]Symbol{
{"(*Hash).Write", Method, 14, ""}, {"(*Hash).Write", Method, 14, ""},
{"(*Hash).WriteByte", Method, 14, ""}, {"(*Hash).WriteByte", Method, 14, ""},
{"(*Hash).WriteString", Method, 14, ""}, {"(*Hash).WriteString", Method, 14, ""},
{"(ComparableHasher).Equal", Method, 27, ""},
{"(ComparableHasher).Hash", Method, 27, ""},
{"Bytes", Func, 19, "func(seed Seed, b []byte) uint64"}, {"Bytes", Func, 19, "func(seed Seed, b []byte) uint64"},
{"Comparable", Func, 24, "func[T comparable](seed Seed, v T) uint64"}, {"Comparable", Func, 24, "func[T comparable](seed Seed, v T) uint64"},
{"ComparableHasher", Type, 27, ""},
{"Hash", Type, 14, ""}, {"Hash", Type, 14, ""},
{"Hasher", Type, 27, ""},
{"MakeSeed", Func, 14, "func() Seed"}, {"MakeSeed", Func, 14, "func() Seed"},
{"Seed", Type, 14, ""}, {"Seed", Type, 14, ""},
{"String", Func, 19, "func(seed Seed, s string) uint64"}, {"String", Func, 19, "func(seed Seed, s string) uint64"},
@@ -8035,6 +8278,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*Int).CmpAbs", Method, 10, ""}, {"(*Int).CmpAbs", Method, 10, ""},
{"(*Int).Div", Method, 0, ""}, {"(*Int).Div", Method, 0, ""},
{"(*Int).DivMod", Method, 0, ""}, {"(*Int).DivMod", Method, 0, ""},
{"(*Int).Divide", Method, 27, ""},
{"(*Int).Exp", Method, 0, ""}, {"(*Int).Exp", Method, 0, ""},
{"(*Int).FillBytes", Method, 15, ""}, {"(*Int).FillBytes", Method, 15, ""},
{"(*Int).Float64", Method, 21, ""}, {"(*Int).Float64", Method, 21, ""},
@@ -8119,9 +8363,11 @@ var PackageSymbols = map[string][]Symbol{
{"Accuracy", Type, 5, ""}, {"Accuracy", Type, 5, ""},
{"AwayFromZero", Const, 5, ""}, {"AwayFromZero", Const, 5, ""},
{"Below", Const, 5, ""}, {"Below", Const, 5, ""},
{"Ceil", Const, 27, ""},
{"ErrNaN", Type, 5, ""}, {"ErrNaN", Type, 5, ""},
{"Exact", Const, 5, ""}, {"Exact", Const, 5, ""},
{"Float", Type, 5, ""}, {"Float", Type, 5, ""},
{"Floor", Const, 27, ""},
{"Int", Type, 0, ""}, {"Int", Type, 0, ""},
{"Jacobi", Func, 5, "func(x *Int, y *Int) int"}, {"Jacobi", Func, 5, "func(x *Int, y *Int) int"},
{"MaxBase", Const, 0, ""}, {"MaxBase", Const, 0, ""},
@@ -8133,12 +8379,14 @@ var PackageSymbols = map[string][]Symbol{
{"NewRat", Func, 0, "func(a int64, b int64) *Rat"}, {"NewRat", Func, 0, "func(a int64, b int64) *Rat"},
{"ParseFloat", Func, 5, "func(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error)"}, {"ParseFloat", Func, 5, "func(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error)"},
{"Rat", Type, 0, ""}, {"Rat", Type, 0, ""},
{"Round", Const, 27, ""},
{"RoundingMode", Type, 5, ""}, {"RoundingMode", Type, 5, ""},
{"ToNearestAway", Const, 5, ""}, {"ToNearestAway", Const, 5, ""},
{"ToNearestEven", Const, 5, ""}, {"ToNearestEven", Const, 5, ""},
{"ToNegativeInf", Const, 5, ""}, {"ToNegativeInf", Const, 5, ""},
{"ToPositiveInf", Const, 5, ""}, {"ToPositiveInf", Const, 5, ""},
{"ToZero", Const, 5, ""}, {"ToZero", Const, 5, ""},
{"Trunc", Const, 27, ""},
{"Word", Type, 0, ""}, {"Word", Type, 0, ""},
}, },
"math/bits": { "math/bits": {
@@ -8290,6 +8538,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*Rand).Int64", Method, 22, ""}, {"(*Rand).Int64", Method, 22, ""},
{"(*Rand).Int64N", Method, 22, ""}, {"(*Rand).Int64N", Method, 22, ""},
{"(*Rand).IntN", Method, 22, ""}, {"(*Rand).IntN", Method, 22, ""},
{"(*Rand).N", Method, 27, ""},
{"(*Rand).NormFloat64", Method, 22, ""}, {"(*Rand).NormFloat64", Method, 22, ""},
{"(*Rand).Perm", Method, 22, ""}, {"(*Rand).Perm", Method, 22, ""},
{"(*Rand).Shuffle", Method, 22, ""}, {"(*Rand).Shuffle", Method, 22, ""},
@@ -8985,7 +9234,7 @@ var PackageSymbols = map[string][]Symbol{
{"NoBody", Var, 8, ""}, {"NoBody", Var, 8, ""},
{"NotFound", Func, 0, "func(w ResponseWriter, r *Request)"}, {"NotFound", Func, 0, "func(w ResponseWriter, r *Request)"},
{"NotFoundHandler", Func, 0, "func() Handler"}, {"NotFoundHandler", Func, 0, "func() Handler"},
{"ParseCookie", Func, 23, "func(line string) ([]*Cookie, error)"}, {"ParseCookie", Func, 23, "func(line string) (#rv1 []*Cookie, #rv2 error)"},
{"ParseHTTPVersion", Func, 0, "func(vers string) (major int, minor int, ok bool)"}, {"ParseHTTPVersion", Func, 0, "func(vers string) (major int, minor int, ok bool)"},
{"ParseSetCookie", Func, 23, "func(line string) (*Cookie, error)"}, {"ParseSetCookie", Func, 23, "func(line string) (*Cookie, error)"},
{"ParseTime", Func, 1, "func(text string) (t time.Time, err error)"}, {"ParseTime", Func, 1, "func(text string) (t time.Time, err error)"},
@@ -9061,6 +9310,7 @@ var PackageSymbols = map[string][]Symbol{
{"Server.BaseContext", Field, 13, ""}, {"Server.BaseContext", Field, 13, ""},
{"Server.ConnContext", Field, 13, ""}, {"Server.ConnContext", Field, 13, ""},
{"Server.ConnState", Field, 3, ""}, {"Server.ConnState", Field, 3, ""},
{"Server.DisableClientPriority", Field, 27, ""},
{"Server.DisableGeneralOptionsHandler", Field, 20, ""}, {"Server.DisableGeneralOptionsHandler", Field, 20, ""},
{"Server.ErrorLog", Field, 3, ""}, {"Server.ErrorLog", Field, 3, ""},
{"Server.HTTP2", Field, 24, ""}, {"Server.HTTP2", Field, 24, ""},
@@ -9226,6 +9476,7 @@ var PackageSymbols = map[string][]Symbol{
{"NewRequestWithContext", Func, 23, "func(ctx context.Context, method string, target string, body io.Reader) *http.Request"}, {"NewRequestWithContext", Func, 23, "func(ctx context.Context, method string, target string, body io.Reader) *http.Request"},
{"NewServer", Func, 0, "func(handler http.Handler) *Server"}, {"NewServer", Func, 0, "func(handler http.Handler) *Server"},
{"NewTLSServer", Func, 0, "func(handler http.Handler) *Server"}, {"NewTLSServer", Func, 0, "func(handler http.Handler) *Server"},
{"NewTestServer", Func, 27, "func(t testing.TB, handler http.Handler) *Server"},
{"NewUnstartedServer", Func, 0, "func(handler http.Handler) *Server"}, {"NewUnstartedServer", Func, 0, "func(handler http.Handler) *Server"},
{"ResponseRecorder", Type, 0, ""}, {"ResponseRecorder", Type, 0, ""},
{"ResponseRecorder.Body", Field, 0, ""}, {"ResponseRecorder.Body", Field, 0, ""},
@@ -9596,6 +9847,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*Error).Timeout", Method, 6, ""}, {"(*Error).Timeout", Method, 6, ""},
{"(*Error).Unwrap", Method, 13, ""}, {"(*Error).Unwrap", Method, 13, ""},
{"(*URL).AppendBinary", Method, 24, ""}, {"(*URL).AppendBinary", Method, 24, ""},
{"(*URL).Clone", Method, 27, ""},
{"(*URL).EscapedFragment", Method, 15, ""}, {"(*URL).EscapedFragment", Method, 15, ""},
{"(*URL).EscapedPath", Method, 5, ""}, {"(*URL).EscapedPath", Method, 5, ""},
{"(*URL).Hostname", Method, 8, ""}, {"(*URL).Hostname", Method, 8, ""},
@@ -9616,6 +9868,7 @@ var PackageSymbols = map[string][]Symbol{
{"(EscapeError).Error", Method, 0, ""}, {"(EscapeError).Error", Method, 0, ""},
{"(InvalidHostError).Error", Method, 6, ""}, {"(InvalidHostError).Error", Method, 6, ""},
{"(Values).Add", Method, 0, ""}, {"(Values).Add", Method, 0, ""},
{"(Values).Clone", Method, 27, ""},
{"(Values).Del", Method, 0, ""}, {"(Values).Del", Method, 0, ""},
{"(Values).Encode", Method, 0, ""}, {"(Values).Encode", Method, 0, ""},
{"(Values).Get", Method, 0, ""}, {"(Values).Get", Method, 0, ""},
@@ -10793,6 +11046,7 @@ var PackageSymbols = map[string][]Symbol{
{"ContainsRune", Func, 0, "func(s string, r rune) bool"}, {"ContainsRune", Func, 0, "func(s string, r rune) bool"},
{"Count", Func, 0, "func(s string, substr string) int"}, {"Count", Func, 0, "func(s string, substr string) int"},
{"Cut", Func, 18, "func(s string, sep string) (before string, after string, found bool)"}, {"Cut", Func, 18, "func(s string, sep string) (before string, after string, found bool)"},
{"CutLast", Func, 27, "func(s string, sep string) (before string, after string, found bool)"},
{"CutPrefix", Func, 20, "func(s string, prefix string) (after string, found bool)"}, {"CutPrefix", Func, 20, "func(s string, prefix string) (after string, found bool)"},
{"CutSuffix", Func, 20, "func(s string, suffix string) (before string, found bool)"}, {"CutSuffix", Func, 20, "func(s string, suffix string) (before string, found bool)"},
{"EqualFold", Func, 0, "func(s string, t string) bool"}, {"EqualFold", Func, 0, "func(s string, t string) bool"},
@@ -17476,6 +17730,7 @@ var PackageSymbols = map[string][]Symbol{
{"TestHandler", Func, 21, "func(h slog.Handler, results func() []map[string]any) error"}, {"TestHandler", Func, 21, "func(h slog.Handler, results func() []map[string]any) error"},
}, },
"testing/synctest": { "testing/synctest": {
{"Sleep", Func, 27, "func(d time.Duration)"},
{"Test", Func, 25, "func(t *testing.T, f func(*testing.T))"}, {"Test", Func, 25, "func(t *testing.T, f func(*testing.T))"},
{"Wait", Func, 25, "func()"}, {"Wait", Func, 25, "func()"},
}, },
@@ -17980,6 +18235,7 @@ var PackageSymbols = map[string][]Symbol{
{"Bassa_Vah", Var, 4, ""}, {"Bassa_Vah", Var, 4, ""},
{"Batak", Var, 0, ""}, {"Batak", Var, 0, ""},
{"Bengali", Var, 0, ""}, {"Bengali", Var, 0, ""},
{"Beria_Erfe", Var, 27, ""},
{"Bhaiksuki", Var, 7, ""}, {"Bhaiksuki", Var, 7, ""},
{"Bidi_Control", Var, 0, ""}, {"Bidi_Control", Var, 0, ""},
{"Bopomofo", Var, 0, ""}, {"Bopomofo", Var, 0, ""},
@@ -18029,6 +18285,7 @@ var PackageSymbols = map[string][]Symbol{
{"Extender", Var, 0, ""}, {"Extender", Var, 0, ""},
{"FoldCategory", Var, 0, ""}, {"FoldCategory", Var, 0, ""},
{"FoldScript", Var, 0, ""}, {"FoldScript", Var, 0, ""},
{"Garay", Var, 27, ""},
{"Georgian", Var, 0, ""}, {"Georgian", Var, 0, ""},
{"Glagolitic", Var, 0, ""}, {"Glagolitic", Var, 0, ""},
{"Gothic", Var, 0, ""}, {"Gothic", Var, 0, ""},
@@ -18038,6 +18295,7 @@ var PackageSymbols = map[string][]Symbol{
{"Gujarati", Var, 0, ""}, {"Gujarati", Var, 0, ""},
{"Gunjala_Gondi", Var, 13, ""}, {"Gunjala_Gondi", Var, 13, ""},
{"Gurmukhi", Var, 0, ""}, {"Gurmukhi", Var, 0, ""},
{"Gurung_Khema", Var, 27, ""},
{"Han", Var, 0, ""}, {"Han", Var, 0, ""},
{"Hangul", Var, 0, ""}, {"Hangul", Var, 0, ""},
{"Hanifi_Rohingya", Var, 13, ""}, {"Hanifi_Rohingya", Var, 13, ""},
@@ -18049,6 +18307,9 @@ var PackageSymbols = map[string][]Symbol{
{"Hyphen", Var, 0, ""}, {"Hyphen", Var, 0, ""},
{"IDS_Binary_Operator", Var, 0, ""}, {"IDS_Binary_Operator", Var, 0, ""},
{"IDS_Trinary_Operator", Var, 0, ""}, {"IDS_Trinary_Operator", Var, 0, ""},
{"IDS_Unary_Operator", Var, 27, ""},
{"ID_Compat_Math_Continue", Var, 27, ""},
{"ID_Compat_Math_Start", Var, 27, ""},
{"Ideographic", Var, 0, ""}, {"Ideographic", Var, 0, ""},
{"Imperial_Aramaic", Var, 0, ""}, {"Imperial_Aramaic", Var, 0, ""},
{"In", Func, 2, "func(r rune, ranges ...*RangeTable) bool"}, {"In", Func, 2, "func(r rune, ranges ...*RangeTable) bool"},
@@ -18082,6 +18343,7 @@ var PackageSymbols = map[string][]Symbol{
{"Khmer", Var, 0, ""}, {"Khmer", Var, 0, ""},
{"Khojki", Var, 4, ""}, {"Khojki", Var, 4, ""},
{"Khudawadi", Var, 4, ""}, {"Khudawadi", Var, 4, ""},
{"Kirat_Rai", Var, 27, ""},
{"L", Var, 0, ""}, {"L", Var, 0, ""},
{"LC", Var, 25, ""}, {"LC", Var, 25, ""},
{"Lao", Var, 0, ""}, {"Lao", Var, 0, ""},
@@ -18125,6 +18387,7 @@ var PackageSymbols = map[string][]Symbol{
{"Miao", Var, 1, ""}, {"Miao", Var, 1, ""},
{"Mn", Var, 0, ""}, {"Mn", Var, 0, ""},
{"Modi", Var, 4, ""}, {"Modi", Var, 4, ""},
{"Modifier_Combining_Mark", Var, 27, ""},
{"Mongolian", Var, 0, ""}, {"Mongolian", Var, 0, ""},
{"Mro", Var, 4, ""}, {"Mro", Var, 4, ""},
{"Multani", Var, 5, ""}, {"Multani", Var, 5, ""},
@@ -18145,6 +18408,7 @@ var PackageSymbols = map[string][]Symbol{
{"Nyiakeng_Puachue_Hmong", Var, 14, ""}, {"Nyiakeng_Puachue_Hmong", Var, 14, ""},
{"Ogham", Var, 0, ""}, {"Ogham", Var, 0, ""},
{"Ol_Chiki", Var, 0, ""}, {"Ol_Chiki", Var, 0, ""},
{"Ol_Onal", Var, 27, ""},
{"Old_Hungarian", Var, 5, ""}, {"Old_Hungarian", Var, 5, ""},
{"Old_Italic", Var, 0, ""}, {"Old_Italic", Var, 0, ""},
{"Old_North_Arabian", Var, 4, ""}, {"Old_North_Arabian", Var, 4, ""},
@@ -18214,6 +18478,7 @@ var PackageSymbols = map[string][]Symbol{
{"Sharada", Var, 1, ""}, {"Sharada", Var, 1, ""},
{"Shavian", Var, 0, ""}, {"Shavian", Var, 0, ""},
{"Siddham", Var, 4, ""}, {"Siddham", Var, 4, ""},
{"Sidetic", Var, 27, ""},
{"SignWriting", Var, 5, ""}, {"SignWriting", Var, 5, ""},
{"SimpleFold", Func, 0, "func(r rune) rune"}, {"SimpleFold", Func, 0, "func(r rune) rune"},
{"Sinhala", Var, 0, ""}, {"Sinhala", Var, 0, ""},
@@ -18227,6 +18492,7 @@ var PackageSymbols = map[string][]Symbol{
{"Space", Var, 0, ""}, {"Space", Var, 0, ""},
{"SpecialCase", Type, 0, ""}, {"SpecialCase", Type, 0, ""},
{"Sundanese", Var, 0, ""}, {"Sundanese", Var, 0, ""},
{"Sunuwar", Var, 27, ""},
{"Syloti_Nagri", Var, 0, ""}, {"Syloti_Nagri", Var, 0, ""},
{"Symbol", Var, 0, ""}, {"Symbol", Var, 0, ""},
{"Syriac", Var, 0, ""}, {"Syriac", Var, 0, ""},
@@ -18235,6 +18501,7 @@ var PackageSymbols = map[string][]Symbol{
{"Tai_Le", Var, 0, ""}, {"Tai_Le", Var, 0, ""},
{"Tai_Tham", Var, 0, ""}, {"Tai_Tham", Var, 0, ""},
{"Tai_Viet", Var, 0, ""}, {"Tai_Viet", Var, 0, ""},
{"Tai_Yo", Var, 27, ""},
{"Takri", Var, 1, ""}, {"Takri", Var, 1, ""},
{"Tamil", Var, 0, ""}, {"Tamil", Var, 0, ""},
{"Tangsa", Var, 21, ""}, {"Tangsa", Var, 21, ""},
@@ -18252,7 +18519,10 @@ var PackageSymbols = map[string][]Symbol{
{"ToLower", Func, 0, "func(r rune) rune"}, {"ToLower", Func, 0, "func(r rune) rune"},
{"ToTitle", Func, 0, "func(r rune) rune"}, {"ToTitle", Func, 0, "func(r rune) rune"},
{"ToUpper", Func, 0, "func(r rune) rune"}, {"ToUpper", Func, 0, "func(r rune) rune"},
{"Todhri", Var, 27, ""},
{"Tolong_Siki", Var, 27, ""},
{"Toto", Var, 21, ""}, {"Toto", Var, 21, ""},
{"Tulu_Tigalari", Var, 27, ""},
{"TurkishCase", Var, 0, ""}, {"TurkishCase", Var, 0, ""},
{"Ugaritic", Var, 0, ""}, {"Ugaritic", Var, 0, ""},
{"Unified_Ideograph", Var, 0, ""}, {"Unified_Ideograph", Var, 0, ""},
@@ -18320,6 +18590,21 @@ var PackageSymbols = map[string][]Symbol{
{"String", Func, 0, ""}, {"String", Func, 0, ""},
{"StringData", Func, 0, ""}, {"StringData", Func, 0, ""},
}, },
"uuid": {
{"(*UUID).UnmarshalText", Method, 27, ""},
{"(UUID).AppendText", Method, 27, ""},
{"(UUID).Compare", Method, 27, ""},
{"(UUID).MarshalText", Method, 27, ""},
{"(UUID).String", Method, 27, ""},
{"Max", Func, 27, "func() UUID"},
{"MustParse", Func, 27, "func(s string) UUID"},
{"New", Func, 27, "func() UUID"},
{"NewV4", Func, 27, "func() UUID"},
{"NewV7", Func, 27, "func() UUID"},
{"Nil", Func, 27, "func() UUID"},
{"Parse", Func, 27, "func(s string) (UUID, error)"},
{"UUID", Type, 27, ""},
},
"weak": { "weak": {
{"(Pointer).Value", Method, 24, ""}, {"(Pointer).Value", Method, 24, ""},
{"Make", Func, 24, "func[T any](ptr *T) Pointer[T]"}, {"Make", Func, 24, "func[T any](ptr *T) Pointer[T]"},
+6 -2
View File
@@ -37,6 +37,10 @@ func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T type
tmset := msets.MethodSet(T) tmset := msets.MethodSet(T)
for method := range tmset.Methods() { for method := range tmset.Methods() {
sig := method.Type().(*types.Signature) sig := method.Type().(*types.Signature)
if sig.TypeParams() != nil {
continue // skip type-parameterized methods
}
// It is tempting to call visit(sig, false) // It is tempting to call visit(sig, false)
// but, as noted in golang.org/cl/65450043, // but, as noted in golang.org/cl/65450043,
// the Signature.Recv field is ignored by // the Signature.Recv field is ignored by
@@ -123,10 +127,10 @@ func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T type
case *types.TypeParam, *types.Union: case *types.TypeParam, *types.Union:
// forEachReachable must not be called on parameterized types. // forEachReachable must not be called on parameterized types.
panic(T) panic(fmt.Sprintf("ForEachElement called on type containing %T", T))
default: default:
panic(T) panic(fmt.Sprintf("ForEachElement called on unexpected type %T", T))
} }
} }
visit(T, false) visit(T, false)
+28
View File
@@ -22,6 +22,7 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"go/types" "go/types"
"iter"
"reflect" "reflect"
"golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/ast/inspector"
@@ -242,3 +243,30 @@ func ObjectKind(obj types.Object) string {
} }
return "unknown symbol" return "unknown symbol"
} }
// ImplicitFieldSelections returns the sequence of implicit embedded fields
// traversed by the given selection. It skips the final leaf field or method.
// The boolean component indicates whether the traversal traversed a pointer.
func ImplicitFieldSelections(seln types.Selection) iter.Seq2[*types.Var, bool] {
return func(yield func(*types.Var, bool) bool) {
var (
t = seln.Recv()
indices = seln.Index()
)
for _, idx := range indices[:len(indices)-1] {
ptr, isPtr := t.Underlying().(*types.Pointer)
if isPtr {
t = ptr.Elem()
}
structType, ok := t.Underlying().(*types.Struct)
if !ok {
break
}
field := structType.Field(idx)
if !yield(field, isPtr) {
break
}
t = field.Type()
}
}
}
+7 -7
View File
@@ -259,13 +259,13 @@ func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
case *types.Signature: case *types.Signature:
var params []*ast.Field var params []*ast.Field
for v := range t.Params().Variables() { for v := range t.Params().Variables() {
var names []*ast.Ident
if v.Name() != "" {
names = []*ast.Ident{ast.NewIdent(v.Name())}
}
params = append(params, &ast.Field{ params = append(params, &ast.Field{
Type: TypeExpr(v.Type(), qual), Type: TypeExpr(v.Type(), qual),
Names: []*ast.Ident{ Names: names,
{
Name: v.Name(),
},
},
}) })
} }
if t.Variadic() { if t.Variadic() {
@@ -328,10 +328,10 @@ func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
return expr return expr
case *types.Struct: case *types.Struct:
return ast.NewIdent(t.String()) return ast.NewIdent(types.TypeString(t, qual))
case *types.Interface: case *types.Interface:
return ast.NewIdent(t.String()) return ast.NewIdent(types.TypeString(t, qual))
case *types.Union: case *types.Union:
if t.Len() == 0 { if t.Len() == 0 {
+10 -8
View File
@@ -322,12 +322,14 @@ go.uber.org/mock/mockgen
go.uber.org/mock/mockgen/model go.uber.org/mock/mockgen/model
# golang.org/x/arch v0.4.0 # golang.org/x/arch v0.4.0
## explicit; go 1.17 ## explicit; go 1.17
# golang.org/x/crypto v0.52.0 # golang.org/x/crypto v0.53.0
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/crypto/blake2b golang.org/x/crypto/blake2b
golang.org/x/crypto/blowfish golang.org/x/crypto/blowfish
golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20
golang.org/x/crypto/chacha20poly1305 golang.org/x/crypto/chacha20poly1305
golang.org/x/crypto/cryptobyte
golang.org/x/crypto/cryptobyte/asn1
golang.org/x/crypto/curve25519 golang.org/x/crypto/curve25519
golang.org/x/crypto/hkdf golang.org/x/crypto/hkdf
golang.org/x/crypto/internal/alias golang.org/x/crypto/internal/alias
@@ -337,13 +339,13 @@ golang.org/x/crypto/nacl/secretbox
golang.org/x/crypto/salsa20/salsa golang.org/x/crypto/salsa20/salsa
golang.org/x/crypto/ssh golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
# golang.org/x/mod v0.35.0 # golang.org/x/mod v0.37.0
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/mod/internal/lazyregexp golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile golang.org/x/mod/modfile
golang.org/x/mod/module golang.org/x/mod/module
golang.org/x/mod/semver golang.org/x/mod/semver
# golang.org/x/net v0.55.0 # golang.org/x/net v0.56.0
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/net/bpf golang.org/x/net/bpf
golang.org/x/net/context golang.org/x/net/context
@@ -368,10 +370,10 @@ golang.org/x/net/websocket
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/oauth2 golang.org/x/oauth2
golang.org/x/oauth2/internal golang.org/x/oauth2/internal
# golang.org/x/sync v0.20.0 # golang.org/x/sync v0.22.0
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/sync/errgroup golang.org/x/sync/errgroup
# golang.org/x/sys v0.45.0 # golang.org/x/sys v0.46.0
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/sys/cpu golang.org/x/sys/cpu
golang.org/x/sys/execabs golang.org/x/sys/execabs
@@ -382,10 +384,10 @@ golang.org/x/sys/windows/registry
golang.org/x/sys/windows/svc golang.org/x/sys/windows/svc
golang.org/x/sys/windows/svc/eventlog golang.org/x/sys/windows/svc/eventlog
golang.org/x/sys/windows/svc/mgr golang.org/x/sys/windows/svc/mgr
# golang.org/x/term v0.43.0 # golang.org/x/term v0.44.0
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/term golang.org/x/term
# golang.org/x/text v0.37.0 # golang.org/x/text v0.40.0
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/text/cases golang.org/x/text/cases
golang.org/x/text/internal golang.org/x/text/internal
@@ -397,7 +399,7 @@ golang.org/x/text/secure/bidirule
golang.org/x/text/transform golang.org/x/text/transform
golang.org/x/text/unicode/bidi golang.org/x/text/unicode/bidi
golang.org/x/text/unicode/norm golang.org/x/text/unicode/norm
# golang.org/x/tools v0.44.0 # golang.org/x/tools v0.47.0
## explicit; go 1.25.0 ## explicit; go 1.25.0
golang.org/x/tools/cover golang.org/x/tools/cover
golang.org/x/tools/go/ast/astutil golang.org/x/tools/go/ast/astutil