Bump reva

This commit is contained in:
André Duffeck committed 2026-08-19 12:35:43 +02:00
1 parent e3bf541d88
commit 320284d03e
34 files changed
+1721 -506

No files matched your search

+5 -5
View File
@@ -64,7 +64,7 @@ require (
github.com/open-policy-agent/opa v1.19.0
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260818063016-69f82a7dde55
github.com/opencloud-eu/reva/v2 v2.48.1-0.20260818072644-485a511e30c2
github.com/opencloud-eu/reva/v2 v2.48.1-0.20260819103057-5d7976d4bed3
github.com/opensearch-project/opensearch-go/v4 v4.6.0
github.com/orcaman/concurrent-map v1.0.0
github.com/pkg/errors v0.9.1
@@ -102,14 +102,14 @@ require (
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0
go.opentelemetry.io/otel/sdk v1.45.0
go.opentelemetry.io/otel/trace v1.45.0
golang.org/x/crypto v0.54.0
golang.org/x/crypto v0.55.0
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f
golang.org/x/image v0.44.0
golang.org/x/net v0.57.0
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.22.0
golang.org/x/term v0.45.0
golang.org/x/text v0.40.0
golang.org/x/text v0.41.0
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d
google.golang.org/grpc v1.83.0
google.golang.org/protobuf v1.36.11
@@ -384,10 +384,10 @@ require (
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/mod v0.37.0 // indirect
golang.org/x/mod v0.38.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.47.0 // indirect
golang.org/x/tools v0.48.0 // indirect
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
+10 -10
View File
@@ -942,8 +942,8 @@ github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 h1:W1ms+l
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89/go.mod h1:vigJkNss1N2QEceCuNw/ullDehncuJNFB6mEnzfq9UI=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260818063016-69f82a7dde55 h1:dzYZ5iA6i0QoFUap9l6sZ4Ts2HXiXVfsOoiRYToYgm8=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260818063016-69f82a7dde55/go.mod h1:lTM8JeGblNpoMySTW7Lui2+c5TTLI95mwxtdUIHHrhU=
github.com/opencloud-eu/reva/v2 v2.48.1-0.20260818072644-485a511e30c2 h1:OKUkfXQYOlBIFFiOg4I2w/p2J+OSjvTt+Oeb6HQQQG0=
github.com/opencloud-eu/reva/v2 v2.48.1-0.20260818072644-485a511e30c2/go.mod h1:ReY9Pc8omXotf3Phn+nsKGalppMsG6kt0mpnKcgKmMU=
github.com/opencloud-eu/reva/v2 v2.48.1-0.20260819103057-5d7976d4bed3 h1:/EoAuqownx+in+8skA31j8BD+tXGxvbP+f9QRIIFPN4=
github.com/opencloud-eu/reva/v2 v2.48.1-0.20260819103057-5d7976d4bed3/go.mod h1:OesdFn3szHcO/gifHWjbMkbkH6tgggkXL3KaNCI81ko=
github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4 h1:l2oB/RctH+t8r7QBj5p8thfEHCM/jF35aAY3WQ3hADI=
github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -1354,8 +1354,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1393,8 +1393,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1576,8 +1576,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1638,8 +1638,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+10 -24
View File
@@ -40,10 +40,10 @@ import (
// Identity provides methods to query users and groups from an LDAP server
type Identity struct {
User userConfig `mapstructure:",squash"`
Group groupConfig `mapstructure:",squash"`
Tenant tenantConfig `mapstructure:",squash"`
LookupCacheTTL string `mapstructure:"lookup_cache_ttl"`
User userConfig `mapstructure:",squash"`
Group groupConfig `mapstructure:",squash"`
Tenant tenantConfig `mapstructure:",squash"`
LookupCacheTTL time.Duration `mapstructure:"lookup_cache_ttl"`
lookupCache entryCache
}
@@ -76,8 +76,7 @@ func (c entryCache) Add(key string, entry *ldap.Entry) {
const (
tracerName = "pkg/utils/ldap"
lookupCacheDefaultTTL = 10 * time.Second
lookupCacheSize = 1024
lookupCacheSize = 1024
)
type userConfig struct {
@@ -258,25 +257,12 @@ func (i *Identity) Setup() error {
}
}
if i.LookupCacheTTL != "" {
// Parse the TTL string if provided
parsedTTL, err := time.ParseDuration(i.LookupCacheTTL)
if err != nil {
return fmt.Errorf("error parsing lookup_cache_ttl %q: %w", i.LookupCacheTTL, err)
}
switch {
case parsedTTL < 0:
return fmt.Errorf("error configuring lookup cache ttl: duration must be >= 0")
case parsedTTL == 0:
// A TTL of 0 disables the lookup cache entirely. A zero-value
// entryCache always misses and never stores anything.
i.lookupCache = entryCache{}
default:
i.lookupCache = entryCache{lru: expirable.NewLRU[string, *ldap.Entry](lookupCacheSize, nil, parsedTTL)}
}
if i.LookupCacheTTL > 0 {
i.lookupCache = entryCache{lru: expirable.NewLRU[string, *ldap.Entry](lookupCacheSize, nil, i.LookupCacheTTL)}
} else {
// Use default TTL if not provided
i.lookupCache = entryCache{lru: expirable.NewLRU[string, *ldap.Entry](lookupCacheSize, nil, lookupCacheDefaultTTL)}
// A TTL of 0 disables the lookup cache entirely. A zero-value
// entryCache always misses and never stores anything.
i.lookupCache = entryCache{}
}
return nil
+1 -1
View File
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (!amd64 && !loong64 && !ppc64le && !ppc64 && !s390x) || !gc || purego
//go:build (!amd64 && !loong64 && !ppc64le && !ppc64 && !riscv64 && !s390x) || !gc || purego
package poly1305
+1 -1
View File
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le)
//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le || riscv64)
package poly1305
+158
View File
@@ -0,0 +1,158 @@
// 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.
//go:build gc && !purego
#define LOAD64U(base, offset, t0, t1, t2, t3, dst) \
MOVBU (offset+0*1)(base), t0; \
MOVBU (offset+1*1)(base), t1; \
MOVBU (offset+2*1)(base), t2; \
MOVBU (offset+3*1)(base), t3; \
SLL $8, t1; \
SLL $16, t2; \
SLL $24, t3; \
OR t1, t0; \
OR t3, t2; \
OR t2, t0, dst; \
MOVBU (offset+4*1)(base), t0; \
MOVBU (offset+5*1)(base), t1; \
MOVBU (offset+6*1)(base), t2; \
MOVBU (offset+7*1)(base), t3; \
SLL $32, t0; \
SLL $40, t1; \
SLL $48, t2; \
SLL $56, t3; \
OR t1, t0; \
OR t3, t2; \
OR t2, t0; \
OR t0, dst
// func update(state *macState, msg []byte)
TEXT ·update(SB), $0-32
MOV state+0(FP), X5
MOV msg_base+8(FP), X6
MOV msg_len+16(FP), X7
MOV $16, X8
AND $7, X6, X28
MOV (0*8)(X5), X9 // h0
MOV (1*8)(X5), X10 // h1
MOV (2*8)(X5), X11 // h2
MOV (3*8)(X5), X12 // r0
MOV (4*8)(X5), X13 // r1
BLT X7, X8, tail
loop:
BEQZ X28, aligned_load
LOAD64U(X6, 0*8, X16, X18, X19, X20, X15) // msg[0:8]
LOAD64U(X6, 1*8, X16, X18, X19, X20, X17) // msg[8:16]
JMP block
aligned_load:
MOV (0*8)(X6), X15 // msg[0:8]
MOV (1*8)(X6), X17 // msg[8:16]
block:
ADD X15, X9 // h0 (x1 + y1 = z1', if z1' < x1 then z1' overflow)
SLTU X15, X9, X19 // h0.carry
ADD X17, X10, X22
SLTU X17, X22, X23
ADD X22, X19, X10 // h1
SLTU X22, X10, X19
OR X23, X19 // h1.carry
ADD $1, X19
ADD X19, X11 // h2
ADD $16, X6 // msg = msg[16:]
multiply:
MULHU X9, X12, X16 // h0r0.hi
MUL X9, X12, X15 // h0r0.lo
MULHU X10, X12, X17 // h1r0.hi
MUL X10, X12, X14 // h1r0.lo
ADD X14, X16
SLTU X14, X16, X19
ADD X19, X17
MUL X11, X12, X20
ADD X17, X20
MULHU X9, X13, X17 // h0r1.hi
MUL X9, X13, X14 // h0r1.lo
ADD X14, X16
SLTU X14, X16, X19
ADD X19, X17
MOV X17, X9
MUL X11, X13, X21 // h2r1
MULHU X10, X13, X17 // h1r1.hi
MUL X10, X13, X14 // h1r1.lo
ADD X14, X20
ADD X17, X21, X22
SLTU X14, X20, X19
ADD X22, X19, X21
ADD X9, X20
SLTU X9, X20, X19
ADD X19, X21
AND $3, X20, X11
AND $-4, X20, X18
ADD X18, X15, X9
ADD X21, X16, X22
SLTU X18, X9, X19
SLTU X21, X22, X23
ADD X22, X19, X10
SLTU X22, X10, X19
OR X19, X23, X19
ADD X19, X11
SLL $62, X21, X22
SRL $2, X20, X23
SRL $2, X21, X21
OR X22, X23, X20
ADD X20, X9, X9
ADD X21, X10, X22
SLTU X20, X9, X19
SLTU X21, X22, X23
ADD X22, X19, X10
SLTU X22, X10, X19
OR X19, X23, X19
ADD X19, X11, X11
SUB $16, X7, X7
BGE X7, X8, loop
tail:
BEQ X7, X0, done
MOV $1, X15
MOV $0, X16
ADD X7, X6, X6
flush_buffer:
MOVBU -1(X6), X20
SRL $56, X15, X19
SLL $8, X16, X23
SLL $8, X15, X15
OR X19, X23, X16
XOR X20, X15
SUB $1, X7, X7
SUB $1, X6, X6
BNE X7, X0, flush_buffer
ADD X15, X9
SLTU X15, X9, X19
ADD X16, X10, X22
SLTU X16, X22, X23
ADD X22, X19, X10
SLTU X22, X10, X19
OR X23, X19
ADD X19, X11
MOV $16, X7
JMP multiply
done:
MOV X9, (0*8)(X5) // h0
MOV X10, (1*8)(X5)
MOV X11, (2*8)(X5)
RET
+12 -5
View File
@@ -85,7 +85,8 @@ type certID struct {
// https://tools.ietf.org/html/rfc2560#section-4.1.1
type ocspRequest struct {
TBSRequest tbsRequest
TBSRequest tbsRequest
OptionalSignature asn1.RawValue `asn1:"explicit,tag:0,optional"`
}
type tbsRequest struct {
@@ -321,10 +322,10 @@ type Request struct {
func (req *Request) Marshal() ([]byte, error) {
hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm)
if hashAlg == nil {
return nil, errors.New("Unknown hash algorithm")
return nil, errors.New("unknown hash algorithm")
}
return asn1.Marshal(ocspRequest{
tbsRequest{
TBSRequest: tbsRequest{
Version: 0,
RequestList: []request{
{
@@ -418,8 +419,10 @@ func (p ParseError) Error() string {
}
// ParseRequest parses an OCSP request in DER form. It only supports
// requests for a single certificate. Signed requests are not supported.
// If a request includes a signature, it will result in a ParseError.
// requests for a single certificate identifier. If a request includes
// multiple certificate identifiers, only the first will be included in
// the parsed Request. Signed requests are not supported. If a request
// includes a signature, it will result in a ParseError.
func ParseRequest(bytes []byte) (*Request, error) {
var req ocspRequest
rest, err := asn1.Unmarshal(bytes, &req)
@@ -430,6 +433,10 @@ func ParseRequest(bytes []byte) (*Request, error) {
return nil, ParseError("trailing data in OCSP request")
}
if len(req.OptionalSignature.FullBytes) > 0 {
return nil, ParseError("signed OCSP requests are not supported")
}
if len(req.TBSRequest.RequestList) == 0 {
return nil, ParseError("OCSP request contains no request body")
}
+1 -1
View File
@@ -104,7 +104,7 @@ func (r *keyring) Unlock(passphrase []byte) error {
if !r.locked {
return errors.New("agent: not locked")
}
if 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) {
if subtle.ConstantTimeCompare(passphrase, r.passphrase) != 1 {
return fmt.Errorf("agent: incorrect passphrase")
}
+2 -2
View File
@@ -246,10 +246,10 @@ func setConstraints(key *AddedKey, constraintBytes []byte) error {
// on arbitrary inputs; the CRT coefficient recomputation is cubic in
// |p| and can consume excessive CPU on oversized keys.
func checkRSAKeyParams(N, E, P, Q *big.Int) error {
if N.BitLen() > 8192 {
if N.BitLen() > 16384 {
return errors.New("agent: RSA modulus too large")
}
if P.BitLen() > 4096 || Q.BitLen() > 4096 {
if P.BitLen() > 8192 || Q.BitLen() > 8192 {
return errors.New("agent: RSA prime too large")
}
if E.BitLen() > 24 {
+10 -5
View File
@@ -229,15 +229,20 @@ func parseCert(in []byte, privAlgo string) (*Certificate, error) {
return nil, err
}
c.Reserved = g.Reserved
// Reject a certificate whose signature key is itself a certificate before
// parsing it. Certificates signed by certificates are not supported (see
// PROTOCOL.certkeys), and rejecting after ParsePublicKey returns would allow
// a chain of nested certificates to recurse once per level, exhausting the
// goroutine stack.
if sigAlgo, _, ok := parseString(g.SignatureKey); !ok {
return nil, errShortRead
} else if _, ok := certKeyAlgoNames[string(sigAlgo)]; ok {
return nil, fmt.Errorf("ssh: the signature key type %q is invalid for certificates", sigAlgo)
}
k, err := ParsePublicKey(g.SignatureKey)
if err != nil {
return nil, err
}
// The Type() function is intended to return only certificate key types, but
// we use certKeyAlgoNames anyway for safety, to match [Certificate.Type].
if _, ok := certKeyAlgoNames[k.Type()]; ok {
return nil, fmt.Errorf("ssh: the signature key type %q is invalid for certificates", k.Type())
}
c.SignatureKey = k
c.Signature, rest, ok = parseSignatureBody(g.Signature)
if !ok || len(rest) > 0 {
+42 -25
View File
@@ -216,6 +216,10 @@ type channel struct {
// packetPool has a buffer for each extended channel ID to
// save allocations during writes.
packetPool map[uint32][]byte
// closeOnce guards close so it is idempotent: closing the internal Go
// channels (msg, incomingRequests) more than once would panic.
closeOnce sync.Once
}
// writePacket sends a packet. If the packet is a channel close, it updates
@@ -340,7 +344,18 @@ func (ch *channel) handleData(packet []byte) error {
if extended == 1 {
ch.extPending.write(data)
} else if extended > 0 {
// discard other extended data.
// RFC 4254, Section 5.2 defines no extended data types other
// than stderr (type 1, handled above) and this package provides
// no API to read them, so the data is discarded. Credit its
// window back immediately: it can never be read, so the
// deduction above would otherwise shrink the window permanently.
// adjustWindow returns io.EOF if the local side has already
// sent a channel close; ignore it like ReadExtended does, since
// an error returned here would terminate the mux read loop and
// tear down the whole connection.
if err := ch.adjustWindow(length); err != nil && err != io.EOF {
return err
}
} else {
ch.pending.write(data)
}
@@ -393,17 +408,19 @@ func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error)
}
func (c *channel) close() {
c.pending.eof()
c.extPending.eof()
close(c.msg)
close(c.incomingRequests)
c.writeMu.Lock()
// This is not necessary for a normal channel teardown, but if
// there was another error, it is.
c.sentClose = true
c.writeMu.Unlock()
// Unblock writers.
c.remoteWin.close()
c.closeOnce.Do(func() {
c.pending.eof()
c.extPending.eof()
close(c.msg)
close(c.incomingRequests)
c.writeMu.Lock()
// This is not necessary for a normal channel teardown, but if
// there was another error, it is.
c.sentClose = true
c.writeMu.Unlock()
// Unblock writers.
c.remoteWin.close()
})
}
// responseMessageReceived is called when a success or failure message is
@@ -493,19 +510,20 @@ func (ch *channel) handlePacket(packet []byte) error {
func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel {
ch := &channel{
remoteWin: window{Cond: newCond()},
myWindow: channelWindowSize,
pending: newBuffer(),
extPending: newBuffer(),
direction: direction,
incomingRequests: make(chan *Request, chanSize),
msg: make(chan interface{}, chanSize),
chanType: chanType,
extraData: extraData,
mux: m,
packetPool: make(map[uint32][]byte),
remoteWin: window{Cond: newCond()},
myWindow: channelWindowSize,
maxIncomingPayload: channelMaxPacket,
pending: newBuffer(),
extPending: newBuffer(),
direction: direction,
incomingRequests: make(chan *Request, chanSize),
msg: make(chan interface{}, chanSize),
chanType: chanType,
extraData: extraData,
mux: m,
packetPool: make(map[uint32][]byte),
}
ch.localId = m.chanList.add(ch)
m.chanList.add(ch)
return ch
}
@@ -529,7 +547,6 @@ func (ch *channel) Accept() (Channel, <-chan *Request, error) {
if ch.decided {
return nil, nil, errDecidedAlready
}
ch.maxIncomingPayload = channelMaxPacket
confirm := channelOpenConfirmMsg{
PeersID: ch.remoteId,
MyID: ch.localId,
+1 -1
View File
@@ -798,7 +798,7 @@ func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn,
return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+
"Major Status: %d\n"+
"Minor Status: %d\n"+
"Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus,
"Error Message: %q\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus,
userAuthGSSAPIErrorResp.Message)
case msgUserAuthGSSAPIToken:
userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
+4 -4
View File
@@ -419,7 +419,7 @@ type AlgorithmNegotiationError struct {
}
func (a *AlgorithmNegotiationError) Error() string {
return fmt.Sprintf("ssh: no common algorithm for %s; we offered: %v, peer offered: %v",
return fmt.Sprintf("ssh: no common algorithm for %s; we offered: %q, peer offered: %q",
a.What, a.SupportedAlgorithms, a.RequestedAlgorithms)
}
@@ -544,7 +544,7 @@ func (c *Config) SetDefaults() {
if c.Rand == nil {
c.Rand = rand.Reader
}
if c.Ciphers == nil {
if len(c.Ciphers) == 0 {
c.Ciphers = defaultCiphers
}
var ciphers []string
@@ -556,7 +556,7 @@ func (c *Config) SetDefaults() {
}
c.Ciphers = ciphers
if c.KeyExchanges == nil {
if len(c.KeyExchanges) == 0 {
c.KeyExchanges = defaultKexAlgos
}
var kexs []string
@@ -571,7 +571,7 @@ func (c *Config) SetDefaults() {
}
c.KeyExchanges = kexs
if c.MACs == nil {
if len(c.MACs) == 0 {
c.MACs = defaultMACs
}
var macs []string
+1 -1
View File
@@ -17,7 +17,7 @@ type OpenChannelError struct {
}
func (e *OpenChannelError) Error() string {
return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
return fmt.Sprintf("ssh: rejected: %s (%q)", e.Reason, e.Message)
}
// ConnMetadata holds metadata for the connection.
+1 -1
View File
@@ -162,7 +162,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
t.remoteAddr = addr
t.hostKeyCallback = config.HostKeyCallback
t.bannerCallback = config.BannerCallback
if config.HostKeyAlgorithms != nil {
if len(config.HostKeyAlgorithms) > 0 {
t.hostKeyAlgorithms = config.HostKeyAlgorithms
} else {
t.hostKeyAlgorithms = defaultHostKeyAlgos
+9 -8
View File
@@ -485,10 +485,11 @@ func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
return nil, nil, err
}
// 8192 bits is also the maximum RSA key size accepted by crypto/tls for
// signature verification:
// https://github.com/golang/go/blob/69801b25/src/crypto/tls/handshake_client.go#L1096
if w.N.BitLen() > 8192 {
// 16384 bits is the largest RSA key OpenSSH will generate (ssh-keygen
// caps -b at 16384), so it is the practical upper bound for keys seen on
// the wire. Rejecting anything larger bounds the CPU spent verifying an
// attacker-supplied key and signature, mitigating a denial of service.
if w.N.BitLen() > 16384 {
return nil, nil, errors.New("ssh: rsa modulus too large")
}
if w.E.BitLen() > 24 {
@@ -1669,13 +1670,13 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
}
// 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
// modulus at the OpenSSH-generated maximum, 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 {
if key.N.BitLen() > 16384 {
return nil, errors.New("ssh: rsa modulus too large")
}
if key.P.BitLen() > 4096 || key.Q.BitLen() > 4096 {
if key.P.BitLen() > 8192 || key.Q.BitLen() > 8192 {
return nil, errors.New("ssh: rsa prime too large")
}
if key.E.BitLen() > 24 {
+1 -10
View File
@@ -44,16 +44,7 @@ type disconnectMsg struct {
}
func (d *disconnectMsg) Error() string {
return fmt.Sprintf("ssh: disconnect, reason %d: %q", d.Reason, sanitizeString(d.Message))
}
func sanitizeString(s string) string {
return strings.Map(func(r rune) rune {
if r == '\t' || (r >= ' ' && r < 0x7f) {
return r
}
return -1
}, s)
return fmt.Sprintf("ssh: disconnect, reason %d: %q", d.Reason, d.Message)
}
// See RFC 4253, section 7.1.
+7 -6
View File
@@ -32,18 +32,21 @@ type chanList struct {
offset uint32
}
// Assigns a channel ID to the given channel.
func (c *chanList) add(ch *channel) uint32 {
// add stores the given channel and assigns its localId while holding the
// lock, so that getChan can never return a channel whose localId is not yet
// initialized.
func (c *chanList) add(ch *channel) {
c.Lock()
defer c.Unlock()
for i := range c.chans {
if c.chans[i] == nil {
c.chans[i] = ch
return uint32(i) + c.offset
ch.localId = uint32(i) + c.offset
return
}
}
c.chans = append(c.chans, ch)
return uint32(len(c.chans)-1) + c.offset
ch.localId = uint32(len(c.chans)-1) + c.offset
}
// getChan returns the channel for the given ID.
@@ -343,8 +346,6 @@ func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Reque
func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {
ch := m.newChannel(chanType, channelOutbound, extra)
ch.maxIncomingPayload = channelMaxPacket
open := channelOpenMsg{
ChanType: chanType,
PeersWindow: ch.myWindow,
+56 -23
View File
@@ -26,10 +26,16 @@ type Permissions struct {
// defines "force-command" (only allow the given command to
// execute) and "source-address" (only allow connections from
// the given address). The SSH package currently only enforces
// the "source-address" critical option. It is up to server
// implementations to enforce other critical options, such as
// "force-command", by checking them after the SSH handshake
// is successful. In general, SSH servers should reject
// the "source-address" critical option: it is validated against
// the client's remote address whenever it is present in the
// Permissions returned by any authentication callback. Its value
// is a comma-separated list of IP addresses and CIDR blocks;
// consistently with OpenSSH, a connection whose remote address is
// not an IP address, such as a Unix domain socket, never matches
// the list and is rejected when the option is present. It is up
// to server implementations to enforce other critical options,
// such as "force-command", by checking them after the SSH
// handshake is successful. In general, SSH servers should reject
// connections that specify critical options that are unknown
// or not supported.
CriticalOptions map[string]string
@@ -223,7 +229,9 @@ type ServerConfig struct {
// Permissions object can be the same object, optionally modified, or a
// completely new object. If VerifiedPublicKeyCallback is non-nil,
// PublicKeyCallback is not allowed to return a PartialSuccessError, which
// can instead be returned by VerifiedPublicKeyCallback.
// can instead be returned by VerifiedPublicKeyCallback. The
// signatureAlgorithm argument is the format of the signature that was
// successfully verified.
//
// VerifiedPublicKeyCallback does not affect which authentication methods
// are included in the list of methods that can be attempted by the client.
@@ -442,6 +450,10 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
return perms, err
}
// checkSourceAddress matches addr against sourceAddrs, a comma-separated list
// of IP addresses and CIDR blocks. Consistently with OpenSSH, a remote address
// that is not IP-based, such as a Unix domain socket, never matches the list
// and is rejected.
func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
if addr == nil {
return errors.New("ssh: no address known for client, but source-address match required")
@@ -449,7 +461,7 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
tcpAddr, ok := addr.(*net.TCPAddr)
if !ok {
return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
return fmt.Errorf("ssh: remote address %v is not a TCP address when checking source-address match", addr)
}
for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
@@ -472,6 +484,21 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
}
// checkSourceAddressCriticalOption enforces the source-address critical
// option, if present in perms, as documented in Permissions.CriticalOptions.
// A present but empty value matches no address, so it denies authentication,
// consistently with OpenSSH, rather than being treated as absent.
func checkSourceAddressCriticalOption(addr net.Addr, perms *Permissions) error {
if perms == nil {
return nil
}
saco, ok := perms.CriticalOptions[sourceAddressCriticalOption]
if !ok {
return nil
}
return checkSourceAddress(addr, saco)
}
func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, token []byte, s *connection,
sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) {
gssAPIServer := gssapiConfig.Server
@@ -685,7 +712,7 @@ userAuthLoop:
}
if userAuthReq.Service != serviceSSH {
return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
return nil, fmt.Errorf("ssh: client attempted to negotiate for unknown service: %q", userAuthReq.Service)
}
if s.user != userAuthReq.User && partialSuccessReturned {
@@ -771,7 +798,8 @@ userAuthLoop:
pubKey, err := ParsePublicKey(pubKeyData)
if err != nil {
return nil, err
authErr = err
break
}
candidate, ok := cache.get(s.user, pubKeyData)
@@ -784,13 +812,14 @@ userAuthLoop:
return nil, errors.New("ssh: invalid library usage: PublicKeyCallback must not return partial success when VerifiedPublicKeyCallback is defined")
}
if (candidate.result == nil || isPartialSuccessError) &&
candidate.perms != nil &&
candidate.perms.CriticalOptions != nil &&
candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
if err := checkSourceAddress(
s.RemoteAddr(),
candidate.perms.CriticalOptions[sourceAddressCriticalOption]); err != nil {
// This check is authoritative for the Permissions returned by
// PublicKeyCallback: the check at the end of the auth loop sees
// the final Permissions, which VerifiedPublicKeyCallback may
// have replaced, and is skipped on partial success. It also
// makes public key queries fail before the client signs when
// PublicKeyCallback supplies the restriction.
if candidate.result == nil || isPartialSuccessError {
if err := checkSourceAddressCriticalOption(s.RemoteAddr(), candidate.perms); err != nil {
candidate.result = err
}
}
@@ -864,14 +893,7 @@ userAuthLoop:
// Only call VerifiedPublicKeyCallback after the key has been accepted
// and successfully verified. If authErr is non-nil, the key is not
// considered verified and the callback must not run.
perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, algo)
}
if authErr == nil && perms != nil && perms.CriticalOptions != nil {
if saco := perms.CriticalOptions[sourceAddressCriticalOption]; saco != "" {
if err := checkSourceAddress(s.RemoteAddr(), saco); err != nil {
authErr = err
}
}
perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, sig.Format)
}
}
case "gssapi-with-mic":
@@ -925,6 +947,17 @@ userAuthLoop:
authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
}
// The source-address critical option is enforced on the Permissions
// returned by any authentication callback. Permissions returned
// together with a PartialSuccessError skip this check: that is safe
// because they are required to be nil, as enforced in the partial
// success handling below.
if authErr == nil {
if err := checkSourceAddressCriticalOption(s.RemoteAddr(), perms); err != nil {
authErr = err
}
}
authErrs = append(authErrs, authErr)
if config.AuthLogCallback != nil {
+10 -6
View File
@@ -118,24 +118,28 @@ func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) {
OIDS: make([]asn1.ObjectIdentifier, n),
}
for i := 0; i < int(n); i++ {
var (
desiredMech []byte
err error
)
var desiredMech []byte
desiredMech, rest, ok = parseString(rest)
if !ok {
return nil, errors.New("parse string failed")
}
if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil {
trailing, err := asn1.Unmarshal(desiredMech, &s.OIDS[i])
if err != nil {
return nil, err
}
if len(trailing) != 0 {
return nil, errors.New("trailing bytes after OID")
}
}
if len(rest) != 0 {
return nil, errors.New("trailing bytes after mechanisms")
}
return s, nil
}
// See RFC 4462 section 3.6.
func buildMIC(sessionID string, username string, service string, authMethod string) []byte {
out := make([]byte, 0, 0)
out := make([]byte, 0)
out = appendString(out, sessionID)
out = append(out, msgUserAuthRequest)
out = appendString(out, username)
+2
View File
@@ -58,6 +58,7 @@ func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
return nil, err
}
go DiscardRequests(in)
go io.Copy(io.Discard, ch.Stderr())
return ch, err
}
@@ -79,6 +80,7 @@ func (l *unixListener) Accept() (net.Conn, error) {
return nil, err
}
go DiscardRequests(incoming)
go io.Copy(io.Discard, ch.Stderr())
return &chanConn{
Channel: ch,
+2
View File
@@ -332,6 +332,7 @@ func (l *tcpListener) Accept() (net.Conn, error) {
return nil, err
}
go DiscardRequests(incoming)
go io.Copy(io.Discard, ch.Stderr())
return &chanConn{
Channel: ch,
@@ -495,6 +496,7 @@ func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel
return nil, err
}
go DiscardRequests(in)
go io.Copy(io.Discard, ch.Stderr())
return ch, nil
}
+8 -1
View File
@@ -30,6 +30,7 @@ import (
"slices"
"strconv"
"strings"
"sync"
"golang.org/x/tools/internal/typesinternal"
)
@@ -126,7 +127,8 @@ func For(obj types.Object) (Path, error) {
// An Encoder amortizes the cost of encoding the paths of multiple objects.
// The zero value of an Encoder is ready to use.
type Encoder struct {
pkgIndex map[*types.Package]*pkgIndex
pkgIndexMu sync.Mutex
pkgIndex map[*types.Package]*pkgIndex
}
// A traversal encapsulates the state of a single traversal of the object/type graph.
@@ -191,6 +193,8 @@ type pkgIndex struct {
// For returns the path to an object relative to its package,
// or an error if the object is not accessible from the package's Scope.
//
// For is safe for concurrent use.
//
// The For function guarantees to return a path only for the following objects:
// - package-level types
// - exported package-level non-types
@@ -320,6 +324,9 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
panic(obj)
}
enc.pkgIndexMu.Lock()
defer enc.pkgIndexMu.Unlock()
// 4. Search the object/type graph for the path to
// the var (field/param/result) or method.
ix, ok := enc.pkgIndex[pkg]
+47 -2
View File
@@ -32,6 +32,7 @@ import (
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/gopathwalk"
"golang.org/x/tools/internal/modindex"
"golang.org/x/tools/internal/stdlib"
)
@@ -320,6 +321,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string {
// load reads in everything necessary to run a pass, and reports whether the
// file already has all the imports it needs. It fills in p.missingRefs with the
// file's missing symbols, if any, or removes unused imports if not.
// This is called 3(!) times: self, otherFiles, loadRealPackageNames
func (p *pass) load(ctx context.Context) ([]*ImportFix, bool) {
p.knownPackages = map[string]*PackageInfo{}
p.missingRefs = References{}
@@ -577,6 +579,17 @@ func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename st
}
func getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, goroot string, logf func(string, ...any), source Source) ([]*ImportFix, error) {
// If there is an Index for the GOMODCACHE, remember that, and later make it so that the
// directory walk doesn't go into the module cache, since we already have all the information
var ix *modindex.Index
src, ok := source.(*ProcessEnvSource)
if ok {
var err error
if ix, err = modindex.Read(src.env.Env["GOMODCACHE"]); err != nil {
ix = nil // don't use it if there was an error
}
}
// This logic is defensively duplicated from getFixes.
abs, err := filepath.Abs(filename)
if err != nil {
@@ -635,6 +648,20 @@ func getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, f
}
p.loadRealPackageNames = true
p.otherFiles = otherFiles
if ix != nil {
src, ok := p.source.(*ProcessEnvSource)
if ok {
// For safety, clone the env so that we don't modify the caller's env.
env := *src.env
env.Env = maps.Clone(src.env.Env)
src.env = &env
// avoid looking in the module cache, as we have the index instead:
// This makes a later call to newModuleresolver (from
// LoadPackageNames) produce a resolver that will not look
// in the module cache
src.env.Env["GOMODCACHE"] = ""
}
}
if fixes, done := p.load(ctx); done {
return fixes, nil
}
@@ -649,7 +676,7 @@ func getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, f
// Go look for candidates in $GOPATH, etc. We don't necessarily load
// the real exports of sibling imports, so keep assuming their contents.
if err := addExternalCandidates(ctx, p, p.missingRefs, filename); err != nil {
if err := addExternalCandidates(ctx, p, p.missingRefs, filename, ix); err != nil {
return nil, err
}
@@ -1184,7 +1211,7 @@ type scanCallback struct {
exportsLoaded func(pkg *pkg, exports []stdlib.Symbol)
}
func addExternalCandidates(ctx context.Context, pass *pass, refs References, filename string) error {
func addExternalCandidates(ctx context.Context, pass *pass, refs References, filename string, ix *modindex.Index) error {
ctx, done := event.Start(ctx, "imports.addExternalCandidates")
defer done()
@@ -1193,6 +1220,24 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs References, fil
return err
}
// Add candidates from the module cache.
if ix != nil {
for k, v := range refs {
for n := range v {
cands := ix.Lookup(k, n, false)
for _, cand := range cands {
x := &Result{
&ImportInfo{ImportPath: cand.ImportPath},
&PackageInfo{Name: cand.PkgName,
Exports: map[string]bool{cand.Name: true},
},
}
results = append(results, x)
}
}
}
}
for _, result := range results {
if result == nil {
continue
+1 -24
View File
@@ -166,10 +166,7 @@ func newModuleResolver(e *ProcessEnv, moduleCacheCache *DirInfoCache) (*ModuleRe
}
}
r.moduleCacheDir = gomodcacheForEnv(goenv)
if r.moduleCacheDir == "" {
return nil, fmt.Errorf("cannot resolve GOMODCACHE")
}
r.moduleCacheDir = goenv["GOMODCACHE"]
sort.Slice(r.modsByModPath, func(i, j int) bool {
count := func(x int) int {
@@ -238,26 +235,6 @@ func newModuleResolver(e *ProcessEnv, moduleCacheCache *DirInfoCache) (*ModuleRe
return r, nil
}
// gomodcacheForEnv returns the GOMODCACHE value to use based on the given env
// map, which must have GOMODCACHE and GOPATH populated.
//
// TODO(rfindley): this is defensive refactoring.
// 1. Is this even relevant anymore? Can't we just read GOMODCACHE.
// 2. Use this to separate module cache scanning from other scanning.
func gomodcacheForEnv(goenv map[string]string) string {
if gmc := goenv["GOMODCACHE"]; gmc != "" {
// golang/go#67156: ensure that the module cache is clean, since it is
// assumed as a prefix to directories scanned by gopathwalk, which are
// themselves clean.
return filepath.Clean(gmc)
}
gopaths := filepath.SplitList(goenv["GOPATH"])
if len(gopaths) == 0 {
return ""
}
return filepath.Join(gopaths[0], "/pkg/mod")
}
func (r *ModuleResolver) initAllMods() error {
stdout, err := r.env.invokeGo(context.TODO(), "list", "-m", "-e", "-json", "...")
if err != nil {
+1 -1
View File
@@ -53,7 +53,7 @@ func (s *ProcessEnvSource) ResolveReferences(ctx context.Context, filename strin
found := make(map[string][]pkgDistance)
callback := &scanCallback{
rootFound: func(gopathwalk.Root) bool {
return true // We want everything.
return true
},
dirFound: func(pkg *pkg) bool {
return pkgIsCandidate(filename, refs, pkg)
+131
View File
@@ -0,0 +1,131 @@
// Copyright 2024 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 modindex
import (
"fmt"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"sync"
"time"
"golang.org/x/mod/semver"
"golang.org/x/tools/internal/gopathwalk"
)
type directory struct {
path string // relative to GOMODCACHE
importPath string
version string // semantic version
}
// bestDirByImportPath returns the best directory for each import
// path, where "best" means most recent semantic version. These import
// paths are inferred from the GOMODCACHE-relative dir names in dirs.
func bestDirByImportPath(dirs []string) (map[string]directory, error) {
dirsByPath := make(map[string]directory)
for _, dir := range dirs {
importPath, version, err := dirToImportPathVersion(dir)
if err != nil {
return nil, err
}
new := directory{
path: dir,
importPath: importPath,
version: version,
}
if old, ok := dirsByPath[importPath]; !ok || compareDirectory(new, old) < 0 {
dirsByPath[importPath] = new
}
}
return dirsByPath, nil
}
// compareDirectory defines an ordering of path@version directories,
// by descending version, then by ascending path.
func compareDirectory(x, y directory) int {
if sign := -semver.Compare(x.version, y.version); sign != 0 {
return sign // latest first
}
return strings.Compare(string(x.path), string(y.path))
}
// modCacheRegexp splits a relpathpath into module, module version, and package.
var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`)
// dirToImportPathVersion computes import path and semantic version
// from a GOMODCACHE-relative directory name.
func dirToImportPathVersion(dir string) (string, string, error) {
m := modCacheRegexp.FindStringSubmatch(string(dir))
// m[1] is the module path
// m[2] is the version major.minor.patch(-<pre release identifier)
// m[3] is the rest of the package path
if len(m) != 4 {
return "", "", fmt.Errorf("bad dir %s", dir)
}
if !semver.IsValid(m[2]) {
return "", "", fmt.Errorf("bad semantic version %s", m[2])
}
// ToSlash is required to convert Windows file paths
// into Go package import paths.
return filepath.ToSlash(m[1] + m[3]), m[2], nil
}
// findDirs returns an unordered list of relevant package directories,
// relative to the specified module cache root. The result includes only
// module dirs whose mtime is within (start, end).
func findDirs(root string, start, end time.Time) []string {
var (
resMu sync.Mutex
res []string
)
addDir := func(root gopathwalk.Root, dir string) {
// TODO(pjw): do we need to check times?
resMu.Lock()
defer resMu.Unlock()
res = append(res, relative(root.Path, dir))
}
skipDir := func(_ gopathwalk.Root, dir string) bool {
// The cache directory is already ignored in gopathwalk.
if filepath.Base(dir) == "internal" {
return true
}
// Skip toolchains.
if strings.Contains(dir, "toolchain@") {
return true
}
// Don't look inside @ directories that are too old/new.
if strings.Contains(filepath.Base(dir), "@") {
st, err := os.Stat(dir)
if err != nil {
log.Printf("can't stat dir %s %v", dir, err)
return true
}
mtime := st.ModTime()
return mtime.Before(start) || mtime.After(end)
}
return false
}
// TODO(adonovan): parallelize this. Even with a hot buffer cache,
// find $(go env GOMODCACHE) -type d
// can easily take up a minute.
roots := []gopathwalk.Root{{Path: root, Type: gopathwalk.RootModuleCache}}
gopathwalk.WalkSkip(roots, addDir, skipDir, gopathwalk.Options{
ModulesEnabled: true,
Concurrency: 1, // TODO(pjw): adjust concurrency
// Logf: log.Printf,
})
return res
}
+295
View File
@@ -0,0 +1,295 @@
// Copyright 2024 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 modindex
import (
"bufio"
"crypto/sha256"
"encoding/csv"
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
)
/*
The on-disk index ("payload") is a text file.
The first 3 lines are header information containing CurrentVersion,
the value of GOMODCACHE, and the validity date of the index.
(This is when the code started building the index.)
Following the header are sections of lines, one section for each
import path. These sections are sorted by package name.
The first line of each section, marked by a leading :, contains
the package name, the import path, the name of the directory relative
to GOMODCACHE, and its semantic version.
The rest of each section consists of one line per exported symbol.
The lines are sorted by the symbol's name and contain the name,
an indication of its lexical type (C, T, V, F), and if it is the
name of a function, information about the signature.
The fields in the section header lines are separated by commas, and
in the unlikely event this would be confusing, the csv package is used
to write (and read) them.
In the lines containing exported names, C=const, V=var, T=type, F=func.
If it is a func, the next field is the number of returned values,
followed by pairs consisting of formal parameter names and types.
All these fields are separated by spaces. Any spaces in a type
(e.g., chan struct{}) are replaced by $s on the disk. The $s are
turned back into spaces when read.
Here is an index header (the comments are not part of the index):
0 // version (of the index format)
/usr/local/google/home/pjw/go/pkg/mod // GOMODCACHE
2024-09-11 18:55:09 // validity date of the index
Here is an index section:
:yaml,gopkg.in/yaml.v1,gopkg.in/yaml.v1@v1.0.0-20140924161607-9f9df34309c0,v1.0.0-20140924161607-9f9df34309c0
Getter T
Marshal F 2 in interface{}
Setter T
Unmarshal F 1 in []byte out interface{}
The package name is yaml, the import path is gopkg.in/yaml.v1.
Getter and Setter are types, and Marshal and Unmarshal are functions.
The latter returns one value and has two arguments, 'in' and 'out'
whose types are []byte and interface{}.
*/
// CurrentVersion tells readers about the format of the index.
const CurrentVersion int = 0
// Index is returned by [Read].
type Index struct {
Version int
GOMODCACHE string // absolute path of Go module cache dir
ValidAt time.Time // moment at which the index was up to date
Entries []Entry
}
func (ix *Index) String() string {
return fmt.Sprintf("Index(%s v%d has %d entries at %v)",
ix.GOMODCACHE, ix.Version, len(ix.Entries), ix.ValidAt)
}
// An Entry contains information for an import path.
type Entry struct {
Dir string // package directory relative to GOMODCACHE; uses OS path separator
ImportPath string
PkgName string
Version string
Names []string // exported names and information
}
// IndexDir is where the module index is stored.
// Each logical index entry consists of a pair of files:
//
// - the "payload" (index-VERSION-XXX), whose name is
// randomized, holds the actual index; and
// - the "link" (index-name-VERSION-HASH),
// whose name is predictable, contains the
// name of the payload file.
//
// Since the link file is small (<512B),
// reads and writes to it may be assumed atomic.
var IndexDir string = func() string {
var dir string
if testing.Testing() {
dir = os.TempDir()
} else {
var err error
dir, err = os.UserCacheDir()
// shouldn't happen, but TempDir is better than
// creating ./goimports
if err != nil {
dir = os.TempDir()
}
}
dir = filepath.Join(dir, "goimports")
if err := os.MkdirAll(dir, 0777); err != nil {
dir = "" // #75505, people complain about the error message
}
return dir
}()
// Read reads the latest version of the on-disk index
// for the specified Go module cache directory.
// If there is no index, it returns a nil Index and an fs.ErrNotExist error.
func Read(gomodcache string) (*Index, error) {
gomodcache, err := filepath.Abs(gomodcache)
if err != nil {
return nil, err
}
if IndexDir == "" {
return nil, os.ErrNotExist
}
// Read the "link" file for the specified gomodcache directory.
// It names the payload file.
content, err := os.ReadFile(filepath.Join(IndexDir, linkFileBasename(gomodcache)))
if err != nil {
return nil, err
}
payloadFile := filepath.Join(IndexDir, string(content))
// Read the index out of the payload file.
f, err := os.Open(payloadFile)
if err != nil {
return nil, err
}
defer f.Close()
return readIndexFrom(gomodcache, bufio.NewReader(f))
}
func readIndexFrom(gomodcache string, r io.Reader) (*Index, error) {
scan := bufio.NewScanner(r)
// version
if !scan.Scan() {
return nil, fmt.Errorf("unexpected scan error: %v", scan.Err())
}
version, err := strconv.Atoi(scan.Text())
if err != nil {
return nil, err
}
if version != CurrentVersion {
return nil, fmt.Errorf("got version %d, expected %d", version, CurrentVersion)
}
// gomodcache
if !scan.Scan() {
return nil, fmt.Errorf("scanner error reading module cache dir: %v", scan.Err())
}
// TODO(pjw): need to check that this is the expected cache dir
// so the tag should be passed in to this function
if dir := string(scan.Text()); dir != gomodcache {
return nil, fmt.Errorf("index file GOMODCACHE mismatch: got %q, want %q", dir, gomodcache)
}
// changed
if !scan.Scan() {
return nil, fmt.Errorf("scanner error reading index creation time: %v", scan.Err())
}
changed, err := time.ParseInLocation(time.DateTime, scan.Text(), time.Local)
if err != nil {
return nil, err
}
// entries
var (
curEntry *Entry
entries []Entry
)
for scan.Scan() {
v := scan.Text()
if len(v) < 2 {
return nil, fmt.Errorf("malformed line: %q, %d entries", v, len(entries))
}
if v[0] == ':' {
if curEntry != nil {
entries = append(entries, *curEntry)
}
// as directories may contain commas and quotes, they need to be read as csv.
rdr := strings.NewReader(v[1:])
cs := csv.NewReader(rdr)
flds, err := cs.Read()
if err != nil {
return nil, err
}
if len(flds) != 4 {
return nil, fmt.Errorf("header contains %d fields, not 4: %q", len(v), v)
}
curEntry = &Entry{
PkgName: flds[0],
ImportPath: flds[1],
Dir: relative(gomodcache, flds[2]),
Version: flds[3],
}
continue
}
curEntry.Names = append(curEntry.Names, v)
}
if err := scan.Err(); err != nil {
return nil, fmt.Errorf("scanner failed while reading modindex entry: %v", err)
}
if curEntry != nil {
entries = append(entries, *curEntry)
}
return &Index{
Version: version,
GOMODCACHE: gomodcache,
ValidAt: changed,
Entries: entries,
}, nil
}
// write writes the index file and updates the index directory to refer to it.
func write(gomodcache string, ix *Index) error {
if IndexDir == "" {
return os.ErrNotExist
}
// Write the index into a payload file with a fresh name.
f, err := os.CreateTemp(IndexDir, fmt.Sprintf("index-%d-*", CurrentVersion))
if err != nil {
return err // e.g. disk full, or index dir deleted
}
if err := writeIndexToFile(ix, bufio.NewWriter(f)); err != nil {
_ = f.Close() // ignore error
return err
}
if err := f.Close(); err != nil {
return err
}
// Write the name of the payload file into a link file.
indexDirFile := filepath.Join(IndexDir, linkFileBasename(gomodcache))
content := []byte(filepath.Base(f.Name()))
return os.WriteFile(indexDirFile, content, 0666)
}
func writeIndexToFile(x *Index, w *bufio.Writer) error {
fmt.Fprintf(w, "%d\n", x.Version)
fmt.Fprintf(w, "%s\n", x.GOMODCACHE)
tm := x.ValidAt.Truncate(time.Second) // round the time down
fmt.Fprintf(w, "%s\n", tm.Format(time.DateTime))
for _, e := range x.Entries {
if e.ImportPath == "" {
continue // shouldn't happen
}
// PJW: maybe always write these headers as csv?
if strings.ContainsAny(string(e.Dir), ",\"") {
cw := csv.NewWriter(w)
cw.Write([]string{":" + e.PkgName, e.ImportPath, string(e.Dir), e.Version})
cw.Flush()
} else {
fmt.Fprintf(w, ":%s,%s,%s,%s\n", e.PkgName, e.ImportPath, e.Dir, e.Version)
}
for _, x := range e.Names {
fmt.Fprintf(w, "%s\n", x)
}
}
return w.Flush()
}
// linkFileBasename returns the base name of the link file in the
// index directory that holds the name of the payload file for the
// specified (absolute) Go module cache dir.
func linkFileBasename(gomodcache string) string {
// Note: coupled to logic in ./gomodindex/cmd.go. TODO: factor.
h := sha256.Sum256([]byte(gomodcache)) // collision-resistant hash
return fmt.Sprintf("index-name-%d-%032x", CurrentVersion, h)
}
func relative(base, file string) string {
if rel, err := filepath.Rel(base, file); err == nil {
return rel
}
return file
}
+184
View File
@@ -0,0 +1,184 @@
// Copyright 2024 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 modindex
import (
"slices"
"strconv"
"strings"
"golang.org/x/mod/module"
)
type Candidate struct {
PkgName string
Name string
Dir string
ImportPath string
Type LexType
Deprecated bool
// information for Funcs
Results int16 // how many results
Sig []Field // arg names and types
}
type Field struct {
Arg, Type string
}
type LexType int8
const (
Const LexType = iota
Var
Type
Func
)
// LookupAll only returns those Candidates whose import path
// finds all the names.
func (ix *Index) LookupAll(pkgName string, names ...string) map[string][]Candidate {
// this can be made faster when benchmarks show that it needs to be
names = uniquify(names)
byImpPath := make(map[string][]Candidate)
for _, nm := range names {
cands := ix.Lookup(pkgName, nm, false)
for _, c := range cands {
byImpPath[c.ImportPath] = append(byImpPath[c.ImportPath], c)
}
}
for k, v := range byImpPath {
if len(v) != len(names) {
delete(byImpPath, k)
}
}
return byImpPath
}
// remove duplicates
func uniquify(in []string) []string {
if len(in) == 0 {
return in
}
in = slices.Clone(in)
slices.Sort(in)
return slices.Compact(in)
}
// Lookup finds all the symbols in the index with the given PkgName and name.
// If prefix is true, it finds all of these with name as a prefix.
func (ix *Index) Lookup(pkgName, name string, prefix bool) []Candidate {
loc, ok := slices.BinarySearchFunc(ix.Entries, pkgName, func(e Entry, pkg string) int {
return strings.Compare(e.PkgName, pkgName)
})
if !ok {
return nil // didn't find the package
}
var ans []Candidate
// loc is the first entry for this package name, but there may be several
for i := loc; i < len(ix.Entries); i++ {
e := ix.Entries[i]
if e.PkgName != pkgName {
break // end of sorted package names
}
nloc, ok := slices.BinarySearchFunc(e.Names, name, func(s string, name string) int {
if strings.HasPrefix(s, name) {
return 0
}
if s < name {
return -1
}
return 1
})
if !ok {
continue // didn't find the name, nor any symbols with name as a prefix
}
for j := nloc; j < len(e.Names); j++ {
nstr := e.Names[j]
// benchmarks show this makes a difference when there are a lot of Possibilities
flds := fastSplit(nstr)
if !(flds[0] == name || prefix && strings.HasPrefix(flds[0], name)) {
// past range of matching Names
break
}
if len(flds) < 2 {
continue // should never happen
}
impPath, err := module.UnescapePath(e.ImportPath)
if err != nil {
continue
}
px := Candidate{
PkgName: pkgName,
Name: flds[0],
Dir: string(e.Dir),
ImportPath: impPath,
Type: asLexType(flds[1][0]),
Deprecated: len(flds[1]) > 1 && flds[1][1] == 'D',
}
if px.Type == Func {
n, err := strconv.Atoi(flds[2])
if err != nil {
continue // should never happen
}
px.Results = int16(n)
if len(flds) >= 4 {
sig := strings.Split(flds[3], " ")
for i := range sig {
// $ cannot otherwise occur. removing the spaces
// almost works, but for chan struct{}, e.g.
sig[i] = strings.Replace(sig[i], "$", " ", -1)
}
px.Sig = toFields(sig)
}
}
ans = append(ans, px)
}
}
return ans
}
func toFields(sig []string) []Field {
ans := make([]Field, len(sig)/2)
for i := range ans {
ans[i] = Field{Arg: sig[2*i], Type: sig[2*i+1]}
}
return ans
}
// benchmarks show this is measurably better than strings.Split
// split into first 4 fields separated by single space
func fastSplit(x string) []string {
ans := make([]string, 0, 4)
nxt := 0
start := 0
for i := 0; i < len(x); i++ {
if x[i] != ' ' {
continue
}
ans = append(ans, x[start:i])
nxt++
start = i + 1
if nxt >= 3 {
break
}
}
ans = append(ans, x[start:])
return ans
}
func asLexType(c byte) LexType {
switch c {
case 'C':
return Const
case 'V':
return Var
case 'T':
return Type
case 'F':
return Func
}
return -1
}
+121
View File
@@ -0,0 +1,121 @@
// Copyright 2024 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 modindex contains code for building and searching an
// [Index] of the Go module cache.
package modindex
// The directory containing the index, returned by
// [IndexDir], contains a file index-name-<ver> that contains the name
// of the current index. We believe writing that short file is atomic.
// [Read] reads that file to get the file name of the index.
// WriteIndex writes an index with a unique name and then
// writes that name into a new version of index-name-<ver>.
// (<ver> stands for the CurrentVersion of the index format.)
import (
"maps"
"os"
"path/filepath"
"slices"
"strings"
"time"
"golang.org/x/mod/semver"
)
// Update updates the index for the specified Go
// module cache directory, creating it as needed.
// On success it returns the current index.
func Update(gomodcache string) (*Index, error) {
prev, err := Read(gomodcache)
if err != nil {
if !os.IsNotExist(err) {
return nil, err
}
prev = nil
}
return update(gomodcache, prev)
}
// update builds, writes, and returns the current index.
//
// If old is nil, the new index is built from all of GOMODCACHE;
// otherwise it is built from the old index plus cache updates
// since the previous index's time.
func update(gomodcache string, old *Index) (*Index, error) {
gomodcache, err := filepath.Abs(gomodcache)
if err != nil {
return nil, err
}
new, changed, err := build(gomodcache, old)
if err != nil {
return nil, err
}
if old == nil || changed {
if err := write(gomodcache, new); err != nil {
return nil, err
}
}
return new, nil
}
// build returns a new index for the specified Go module cache (an
// absolute path).
//
// If an old index is provided, only directories more recent than it
// that it are scanned; older directories are provided by the old
// Index.
//
// The boolean result indicates whether new entries were found.
func build(gomodcache string, old *Index) (*Index, bool, error) {
// Set the time window.
var start time.Time // = dawn of time
if old != nil {
// -1s to accommodate skew between (fine-grained) time.Now
// and (coarse) file system's mtime clock.
start = old.ValidAt.Add(-1 * time.Second)
}
now := time.Now()
end := now.Add(24 * time.Hour) // safely in the future
// Enumerate GOMODCACHE package directories.
// Choose the best (latest) package for each import path.
pkgDirs := findDirs(gomodcache, start, end)
dirByPath, err := bestDirByImportPath(pkgDirs)
if err != nil {
return nil, false, err
}
// For each import path it might occur only in
// dirByPath, only in old, or in both.
// If both, use the semantically later one.
var entries []Entry
if old != nil {
for _, entry := range old.Entries {
dir, ok := dirByPath[entry.ImportPath]
if !ok || semver.Compare(dir.version, entry.Version) <= 0 {
// New dir is missing or not more recent; use old entry.
entries = append(entries, entry)
delete(dirByPath, entry.ImportPath)
}
}
}
// Extract symbol information for all the new directories.
newEntries := extractSymbols(gomodcache, maps.Values(dirByPath))
entries = append(entries, newEntries...)
slices.SortFunc(entries, func(x, y Entry) int {
if n := strings.Compare(x.PkgName, y.PkgName); n != 0 {
return n
}
return strings.Compare(x.ImportPath, y.ImportPath)
})
return &Index{
GOMODCACHE: gomodcache,
ValidAt: now, // time before the directories were scanned
Entries: entries,
}, len(newEntries) > 0, nil
}
+244
View File
@@ -0,0 +1,244 @@
// Copyright 2024 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 modindex
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"go/types"
"iter"
"os"
"path/filepath"
"runtime"
"slices"
"strings"
"sync"
"golang.org/x/sync/errgroup"
)
// The name of a symbol contains information about the symbol:
// <name> T for types, TD if the type is deprecated
// <name> C for consts, CD if the const is deprecated
// <name> V for vars, VD if the var is deprecated
// and for funcs: <name> F <num of return values> (<arg-name> <arg-type>)*
// any spaces in <arg-type> are replaced by $s so that the fields
// of the name are space separated. F is replaced by FD if the func
// is deprecated.
type symbol struct {
pkg string // name of the symbols's package
name string // declared name
kind string // T, C, V, or F, followed by D if deprecated
sig string // signature information, for F
}
// extractSymbols returns a (new, unordered) array of Entries, one for
// each provided package directory, describing its exported symbols.
func extractSymbols(cwd string, dirs iter.Seq[directory]) []Entry {
var (
mu sync.Mutex
entries []Entry
)
var g errgroup.Group
g.SetLimit(max(2, runtime.GOMAXPROCS(0)/2))
for dir := range dirs {
g.Go(func() error {
thedir := filepath.Join(cwd, string(dir.path))
mode := parser.SkipObjectResolution | parser.ParseComments
// Parse all Go files in dir and extract symbols.
dirents, err := os.ReadDir(thedir)
if err != nil {
return nil // log this someday?
}
var syms []symbol
for _, dirent := range dirents {
if !strings.HasSuffix(dirent.Name(), ".go") ||
strings.HasSuffix(dirent.Name(), "_test.go") {
continue
}
fname := filepath.Join(thedir, dirent.Name())
tr, err := parser.ParseFile(token.NewFileSet(), fname, nil, mode)
if err != nil {
continue // ignore errors, someday log them?
}
syms = append(syms, getFileExports(tr)...)
}
// Create an entry for the package.
pkg, names := processSyms(syms)
if pkg != "" {
mu.Lock()
defer mu.Unlock()
entries = append(entries, Entry{
PkgName: pkg,
Dir: dir.path,
ImportPath: dir.importPath,
Version: dir.version,
Names: names,
})
}
return nil
})
}
g.Wait() // ignore error
return entries
}
func getFileExports(f *ast.File) []symbol {
pkg := f.Name.Name
if pkg == "main" || pkg == "" {
return nil
}
var ans []symbol
// should we look for //go:build ignore?
for _, decl := range f.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
if decl.Recv != nil {
// ignore methods, as we are completing package selections
continue
}
name := decl.Name.Name
dtype := decl.Type
// not looking at dtype.TypeParams. That is, treating
// generic functions just like non-generic ones.
sig := dtype.Params
kind := "F"
if isDeprecated(decl.Doc) {
kind += "D"
}
result := []string{fmt.Sprintf("%d", dtype.Results.NumFields())}
for _, x := range sig.List {
// This code creates a string representing the type.
// TODO(pjw): it may be fragile:
// 1. x.Type could be nil, perhaps in ill-formed code
// 2. ExprString might someday change incompatibly to
// include struct tags, which can be arbitrary strings
if x.Type == nil {
// Can this happen without a parse error? (Files with parse
// errors are ignored in getSymbols)
continue // maybe report this someday
}
tp := types.ExprString(x.Type)
if len(tp) == 0 {
// Can this happen?
continue // maybe report this someday
}
// This is only safe if ExprString never returns anything with a $
// The only place a $ can occur seems to be in a struct tag, which
// can be an arbitrary string literal, and ExprString does not presently
// print struct tags. So for this to happen the type of a formal parameter
// has to be a explicit struct, e.g. foo(x struct{a int "$"}) and ExprString
// would have to show the struct tag. Even testing for this case seems
// a waste of effort, but let's remember the possibility
if strings.Contains(tp, "$") {
continue
}
tp = strings.Replace(tp, " ", "$", -1)
if len(x.Names) == 0 {
result = append(result, "_")
result = append(result, tp)
} else {
for _, y := range x.Names {
result = append(result, y.Name)
result = append(result, tp)
}
}
}
sigs := strings.Join(result, " ")
if s := newsym(pkg, name, kind, sigs); s != nil {
ans = append(ans, *s)
}
case *ast.GenDecl:
depr := isDeprecated(decl.Doc)
switch decl.Tok {
case token.CONST, token.VAR:
tp := "V"
if decl.Tok == token.CONST {
tp = "C"
}
if depr {
tp += "D"
}
for _, sp := range decl.Specs {
for _, x := range sp.(*ast.ValueSpec).Names {
if s := newsym(pkg, x.Name, tp, ""); s != nil {
ans = append(ans, *s)
}
}
}
case token.TYPE:
tp := "T"
if depr {
tp += "D"
}
for _, sp := range decl.Specs {
if s := newsym(pkg, sp.(*ast.TypeSpec).Name.Name, tp, ""); s != nil {
ans = append(ans, *s)
}
}
}
}
}
return ans
}
func newsym(pkg, name, kind, sig string) *symbol {
if len(name) == 0 || !ast.IsExported(name) {
return nil
}
sym := symbol{pkg: pkg, name: name, kind: kind, sig: sig}
return &sym
}
func isDeprecated(doc *ast.CommentGroup) bool {
if doc == nil {
return false
}
// go.dev/wiki/Deprecated Paragraph starting 'Deprecated:'
// This code fails for /* Deprecated: */, but it's the code from
// gopls/internal/analysis/deprecated
for line := range strings.SplitSeq(doc.Text(), "\n\n") {
if strings.HasPrefix(line, "Deprecated:") {
return true
}
}
return false
}
// return the package name and the value for the symbols.
// if there are multiple packages, choose one arbitrarily
// the returned slice is sorted lexicographically
func processSyms(syms []symbol) (string, []string) {
if len(syms) == 0 {
return "", nil
}
slices.SortFunc(syms, func(l, r symbol) int {
return strings.Compare(l.name, r.name)
})
pkg := syms[0].pkg
var names []string
for _, s := range syms {
if s.pkg != pkg {
// Symbols came from two files in same dir
// with different package declarations.
continue
}
var nx string
if s.sig != "" {
nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
} else {
nx = fmt.Sprintf("%s %s", s.name, s.kind)
}
names = append(names, nx)
}
return pkg, names
}
+335 -334
View File
@@ -12,386 +12,387 @@ type pkginfo struct {
}
var deps = [...]pkginfo{
{"archive/tar", "\x03{\x03F>\x01\n\x01&\x01\x01\x02\x05\b\x02\x01\x02\x02\r"},
{"archive/zip", "\x02\x04j\x0e\x03\x12\x022>\x01-\x05\x01\x0f\x03\x02\x0f\x04"},
{"bufio", "\x03{\x87\x01F\x15"},
{"bytes", "~*]\x03\fJ\x02\x02"},
{"archive/tar", "\x03|\x03F>\x01\n\x01&\x01\x01\x02\x05\b\x02\x01\x02\x02\r"},
{"archive/zip", "\x02\x04k\x0e\x03\x12\x022>\x01-\x05\x01\x0f\x03\x02\x0f\x04"},
{"bufio", "\x03|\x87\x01F\x15"},
{"bytes", "\x7f*]\x03\fJ\x02\x02"},
{"cmp", ""},
{"compress/bzip2", "\x02\x02\x81\x02C"},
{"compress/flate", "\x02|\x03\x84\x01\f\x034\x02\x03"},
{"compress/gzip", "\x02\x04j\x0e\x03\x14pW"},
{"compress/lzw", "\x02|\x03\x84\x01"},
{"compress/zlib", "\x02\x04j\x0e\x03\x12\x01q"},
{"container/heap", "\xc9\x02"},
{"compress/bzip2", "\x02\x02\x82\x02C"},
{"compress/flate", "\x02}\x03\x84\x01\f\x034\x02\x03"},
{"compress/gzip", "\x02\x04k\x0e\x03\x14pW"},
{"compress/lzw", "\x02}\x03\x84\x01"},
{"compress/zlib", "\x02\x04k\x0e\x03\x12\x01q"},
{"container/heap", "\xca\x02"},
{"container/list", ""},
{"container/ring", ""},
{"context", "~]r\x01\x0e"},
{"crypto", "\x93\x01rE"},
{"crypto/aes", "\x10\v\n\xa5\x02"},
{"crypto/cipher", "\x03\"\x01\x01 \x13$+\\"},
{"crypto/des", "\x10\x17 7+\xa1\x01\x03"},
{"crypto/dsa", "G\x034\x87\x01\r"},
{"crypto/ecdh", "\x03\v\r\x11\x04\x17\x03\x10$\x87\x01"},
{"crypto/ecdsa", "\x0e\x05\x03\x05\x01\x11\b\v\x06\x01\x03\x0f\x01$\x87\x01\r\x05O\x01"},
{"crypto/ed25519", "\x0e \x12\a\x03\t\a$I>E"},
{"crypto/elliptic", "5I\x87\x01\r;"},
{"crypto/fips140", "$\x05\x9e\x01\x9b\x01"},
{"crypto/hkdf", "1\x15\x017\x15"},
{"crypto/hmac", "\x1b\x17\x14\x01\x139"},
{"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\x0eu"},
{"crypto/internal/boring/bbig", "\x1b\xf7\x01P"},
{"crypto/internal/boring/bcache", "\xce\x02\x14"},
{"context", "\x7f]r\x01\x0e"},
{"crypto", "\x94\x01rE"},
{"crypto/aes", "\x10\v\v\xa5\x02"},
{"crypto/cipher", "\x03#\x01\x01 \x13$+\\"},
{"crypto/des", "\x10\x18 7+\xa1\x01\x03"},
{"crypto/dsa", "H\x034\x87\x01\r"},
{"crypto/ecdh", "\x03\v\r\x12\x04\x17\x03\x10$\x87\x01"},
{"crypto/ecdsa", "\x0e\x05\x03\x05\x01\x12\b\v\x06\x01\x03\x0f\x01$\x87\x01\r\x05O\x01"},
{"crypto/ed25519", "\x0e!\x12\a\x03\t\a$I>E"},
{"crypto/elliptic", "6I\x87\x01\r;"},
{"crypto/fips140", "%\x05\x9e\x01\x9b\x01"},
{"crypto/hkdf", "2\x15\x017\x15"},
{"crypto/hmac", "\x1b\x18\x14\x01\x139"},
{"crypto/hpke", "\x03\v\x02\x03\x04\x01\x0e\x01\x05\x1f\x06\a\x01\x01%\x03\x12\x16\x9f\x01\x1d"},
{"crypto/internal/boring", "\x0e\x02\x0ev"},
{"crypto/internal/boring/bbig", "\x1b\xf8\x01P"},
{"crypto/internal/boring/bcache", "\xcf\x02\x14"},
{"crypto/internal/boring/sig", ""},
{"crypto/internal/constanttime", ""},
{"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/cryptotest/wycheproof", "\x0e\x12S\x01\f\x01r@\x05\x03\x15\x10"},
{"crypto/internal/entropy", "L"},
{"crypto/internal/entropy/v1.0.0", "E9\x96\x01:\x14"},
{"crypto/internal/fips140", "D:\xc2\x01\v\x17"},
{"crypto/internal/fips140/aes", "\x03!\x03\x02\x14\x05\x01\x01\x055\x96\x016"},
{"crypto/internal/fips140/aes/gcm", "$\x01\x02\x02\x02\x12\x05\x01\x065\x93\x01"},
{"crypto/internal/fips140/alias", "\xe2\x02"},
{"crypto/internal/fips140/bigmod", ")\x19\x01\x065\x96\x01"},
{"crypto/internal/fips140/check", "$\x0e\a\t\x02\xc1\x01]"},
{"crypto/internal/fips140/check/checktest", ")\x97\x02\""},
{"crypto/internal/fips140/drbg", "\x03 \x01\x01\x04\x14\x05\n2\x87\x01\x0f9\x01"},
{"crypto/internal/fips140/ecdh", "\x03!\x05\x02\n\r<\x87\x01\x0f9"},
{"crypto/internal/fips140/ecdsa", "\x03!\x04\x01\x02\a\x03\x06C\x15r\x0f9"},
{"crypto/internal/fips140/ed25519", "\x03!\x05\x02\x04\fC\xcc\x01\x03"},
{"crypto/internal/fips140/edwards25519", "\x1f\n\a\x12<\x96\x019"},
{"crypto/internal/fips140/edwards25519/field", ")\x14\x05<\x96\x01"},
{"crypto/internal/fips140/hkdf", "\x03!\x05\t\aE\x15"},
{"crypto/internal/fips140/hmac", "\x03!\x15\x01\x01C\x15"},
{"crypto/internal/fips140/mldsa", "\x03\x1c\x05\x05\x02\x0e\x01\x03\x05<\x96\x019"},
{"crypto/internal/fips140/mlkem", "\x03!\x05\x02\x0f\x03\x05<\xcf\x01"},
{"crypto/internal/fips140/nistec", "\x1f\n\r\f<\x96\x01,\r\x15"},
{"crypto/internal/fips140/nistec/fiat", ")\x14A\x96\x01"},
{"crypto/internal/fips140/pbkdf2", "\x03!\x05\t\aE\x15"},
{"crypto/internal/fips140/rsa", "\x03\x1c\x05\x04\x01\x02\x0e\x01\x01\x02A\x15rH"},
{"crypto/internal/fips140/sha256", "\x03!\x1e\x01\x065\x15\x81\x01"},
{"crypto/internal/fips140/sha3", "\x03!\x19\x05\x01;\x96\x01N"},
{"crypto/internal/fips140/sha512", "\x03!\x1e\x01\x065\x15\x81\x01"},
{"crypto/internal/fips140/ssh", ")j"},
{"crypto/internal/fips140/subtle", "\x1f\b\x1b\xd2\x01"},
{"crypto/internal/fips140/tls12", "\x03!\x05\t\a\x02C\x15"},
{"crypto/internal/fips140/tls13", "\x03!\x05\b\b\t<\x15"},
{"crypto/internal/fips140cache", "\xc0\x02\r."},
{"crypto/internal/cryptotest", "\x03\r\v\n%\x11\x1a\r\x12\x12!\x04\x06\n\x19\x01\x11\x11\x1d\x01\a\x03\x02\b\x02\x01\x05\f"},
{"crypto/internal/cryptotest/wycheproof", "\x0e\x12T\x01\f\x01r@\x05\x03\x15\x10"},
{"crypto/internal/cryptotest/x509limbo", "u\n\x03\xba\x01\x03\x1e"},
{"crypto/internal/entropy", "M"},
{"crypto/internal/entropy/v1.0.0", "F9\x96\x01:\x14"},
{"crypto/internal/fips140", "E:\xc2\x01\v\x17"},
{"crypto/internal/fips140/aes", "\x03\"\x03\x02\x14\x05\x01\x01\x055\x96\x016"},
{"crypto/internal/fips140/aes/gcm", "%\x01\x02\x02\x02\x12\x05\x01\x065\x93\x01"},
{"crypto/internal/fips140/alias", "\xe3\x02"},
{"crypto/internal/fips140/bigmod", "*\x19\x01\x065\x96\x01"},
{"crypto/internal/fips140/check", "%\x0e\a\t\x02\xc1\x01]"},
{"crypto/internal/fips140/check/checktest", "*\x97\x02\""},
{"crypto/internal/fips140/drbg", "\x03!\x01\x01\x04\x14\x05\n2\x87\x01\x0f9\x01"},
{"crypto/internal/fips140/ecdh", "\x03\"\x05\x02\n\r<\x87\x01\x0f9"},
{"crypto/internal/fips140/ecdsa", "\x03\"\x04\x01\x02\a\x03\x06C\x15r\x0f9"},
{"crypto/internal/fips140/ed25519", "\x03\"\x05\x02\x04\fC\xcc\x01\x03"},
{"crypto/internal/fips140/edwards25519", "\x1f\v\a\x12<\x96\x019"},
{"crypto/internal/fips140/edwards25519/field", "*\x14\x05<\x96\x01"},
{"crypto/internal/fips140/hkdf", "\x03\"\x05\t\aE\x15"},
{"crypto/internal/fips140/hmac", "\x03\"\x15\x01\x01C\x15"},
{"crypto/internal/fips140/mldsa", "\x03\x1c\x06\x05\x02\x0e\x01\x03\x05<\x96\x019"},
{"crypto/internal/fips140/mlkem", "\x03\"\x05\x02\x0f\x03\x05<\xcf\x01"},
{"crypto/internal/fips140/nistec", "\x1f\v\r\f<\x96\x01,\r\x15"},
{"crypto/internal/fips140/nistec/fiat", "*\x14A\x96\x01"},
{"crypto/internal/fips140/pbkdf2", "\x03\"\x05\t\aE\x15"},
{"crypto/internal/fips140/rsa", "\x03\x1c\x06\x04\x01\x02\x0e\x01\x01\x02A\x15rH"},
{"crypto/internal/fips140/sha256", "\x03\"\x1e\x01\x065\x15\x81\x01"},
{"crypto/internal/fips140/sha3", "\x03\"\x19\x05\x01;\x96\x01N"},
{"crypto/internal/fips140/sha512", "\x03\"\x1e\x01\x065\x15\x81\x01"},
{"crypto/internal/fips140/ssh", "*j"},
{"crypto/internal/fips140/subtle", "\x1f\t\x1b\xd2\x01"},
{"crypto/internal/fips140/tls12", "\x03\"\x05\t\a\x02C\x15"},
{"crypto/internal/fips140/tls13", "\x03\"\x05\b\b\t<\x15"},
{"crypto/internal/fips140cache", "\xc1\x02\r."},
{"crypto/internal/fips140deps", ""},
{"crypto/internal/fips140deps/byteorder", "\xa9\x01"},
{"crypto/internal/fips140deps/cpu", "\xbe\x01\b"},
{"crypto/internal/fips140deps/godebug", "\xc7\x01"},
{"crypto/internal/fips140deps/time", "\xe2\x02"},
{"crypto/internal/fips140hash", ":\x1e;\xcf\x01"},
{"crypto/internal/fips140only", "\x17\x14\x0e\x01\x01Xr"},
{"crypto/internal/fips140deps/byteorder", "\xaa\x01"},
{"crypto/internal/fips140deps/cpu", "\xbf\x01\b"},
{"crypto/internal/fips140deps/godebug", "\xc8\x01"},
{"crypto/internal/fips140deps/time", "\xe3\x02"},
{"crypto/internal/fips140hash", ";\x1e;\xcf\x01"},
{"crypto/internal/fips140only", "\x17\x15\x0e\x01\x01Xr"},
{"crypto/internal/fips140test", ""},
{"crypto/internal/impl", "\xcb\x02"},
{"crypto/internal/rand", "\x1b\x10 |>]"},
{"crypto/internal/randutil", "\x85\x02\x12"},
{"crypto/internal/sysrand", "~r!\"\r\r\x01\x01\r\x06"},
{"crypto/internal/sysrand/internal/seccomp", "~"},
{"crypto/md5", "\x0e97\x15\x16k"},
{"crypto/mldsa", "\x0e%K\x87\x01"},
{"crypto/mlkem", "\x0e&"},
{"crypto/mlkem/mlkemtest", "4\x13\t."},
{"crypto/pbkdf2", "7\x0f\x017\x15"},
{"crypto/rand", "\x1b\x10\x1c\x034\x87\x01\rP"},
{"crypto/rc4", "' 7\xcc\x01"},
{"crypto/rsa", "\x0e\r\x01\f\x10\x0e\x01\x03\t\a$\x03\x124>\f\x01"},
{"crypto/sha1", "\x0e\r,\x025\x15\x16\x15V"},
{"crypto/sha256", "\x0e\r\x1eZ"},
{"crypto/sha3", "\x0e,Y\xcf\x01"},
{"crypto/sha512", "\x0e\r X"},
{"crypto/subtle", "\x1f\x1e\xa9\x01|"},
{"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/tls/internal/fips140tls", "\x17\xb7\x02"},
{"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"},
{"crypto/x509/pkix", "m\x06\x0e\x91\x019\x11"},
{"database/sql", "\x03\nS\x01\x1d\x03\x84\x01\v\a$\x05\b\x02\x03\x01\x0e\x02\x02\x02\x01"},
{"database/sql/driver", "\rT\x1d\x03\xba\x01\x0f\x12\a"},
{"crypto/internal/impl", "\xcc\x02"},
{"crypto/internal/rand", "\x1b\x11 |>]"},
{"crypto/internal/randutil", "\x86\x02\x12"},
{"crypto/internal/sysrand", "\x7fr!\"\r\r\x01\x01\r\x06"},
{"crypto/internal/sysrand/internal/seccomp", "\x7f"},
{"crypto/md5", "\x0e:7\x15\x16k"},
{"crypto/mldsa", "\x0e&K\x87\x01"},
{"crypto/mlkem", "\x0e'"},
{"crypto/mlkem/mlkemtest", "5\x13\t."},
{"crypto/pbkdf2", "8\x0f\x017\x15"},
{"crypto/rand", "\x1b\x11\x1c\x034\x87\x01\rP"},
{"crypto/rc4", "( 7\xcc\x01"},
{"crypto/rsa", "\x0e\r\x01\r\x10\x0e\x01\x03\t\a$\x03\x124>\f\x01"},
{"crypto/sha1", "\x0e\r-\x025\x15\x16\x15V"},
{"crypto/sha256", "\x0e\r\x1fZ"},
{"crypto/sha3", "\x0e-Y\xcf\x01"},
{"crypto/sha512", "\x0e\r!X"},
{"crypto/subtle", "\x1f\x1f\xa9\x01|"},
{"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x01\x01\x01\x01\x01\v\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/tls/internal/fips140tls", "\x17\xb8\x02"},
{"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x01\x018\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"},
{"crypto/x509/pkix", "n\x06\x0e\x91\x019\x11"},
{"database/sql", "\x03\nT\x01\x1d\x03\x84\x01\v\a$\x05\b\x02\x03\x01\x0e\x02\x02\x02\x01"},
{"database/sql/driver", "\rU\x1d\x03\xba\x01\x0f\x12\a"},
{"database/sql/internal", ""},
{"debug/buildinfo", "\x03a\x02\x01\x01\b\x0e\x03h\x1a\x02\x01-\x0f "},
{"debug/dwarf", "\x03m\x0e\x03\x84\x013\x11\x01\x01"},
{"debug/elf", "\x03\x06Z\r\x0e\x03h\x1b\x01\f\"\x17\x01\x17"},
{"debug/gosym", "\x03m\x11#\xa5\x01\x01\x01\x02"},
{"debug/macho", "\x03\x06Z\r\x11h\x1c.\x17\x01"},
{"debug/pe", "\x03\x06Z\r\x0e\x03h\x1c.\x17\x01\x17"},
{"debug/plan9obj", "p\x0e\x03h\x1c."},
{"embed", "~*D\x19\x01V"},
{"debug/buildinfo", "\x03b\x02\x01\x01\b\x0e\x03h\x1a\x02\x01-\x0f "},
{"debug/dwarf", "\x03n\x0e\x03\x84\x013\x11\x01\x01"},
{"debug/elf", "\x03\x06[\r\x0e\x03h\x1b\x01\f\"\x17\x01\x17"},
{"debug/gosym", "\x03n\x11#\xa5\x01\x01\x01\x02"},
{"debug/macho", "\x03\x06[\r\x11h\x1c.\x17\x01"},
{"debug/pe", "\x03\x06[\r\x0e\x03h\x1c.\x17\x01\x17"},
{"debug/plan9obj", "q\x0e\x03h\x1c."},
{"embed", "\x7f*D\x19\x01V"},
{"embed/internal/embedtest", ""},
{"encoding", ""},
{"encoding/ascii85", "\x85\x02E"},
{"encoding/asn1", "\x03{\x03h(\x01)\r\x02\x01\x11\x03\x01"},
{"encoding/base32", "\x85\x02C\x02"},
{"encoding/base64", "\xa9\x01\\C\x02"},
{"encoding/binary", "~\x87\x01\f*\r\x05"},
{"encoding/csv", "\x02\x01{\x03\x84\x01F\x13\x02"},
{"encoding/gob", "\x02i\x05\x0e\x03h\x1c\v\x01\x03\x1f\b\x12\x01\x10\x02"},
{"encoding/hex", "~\x03\x84\x01C\x03"},
{"encoding/json", "\x03\x01g\n\x01\x01\x02\x01\x01\x03\x03\x84\x016\x0f\x01"},
{"encoding/json/internal", "~"},
{"encoding/json/internal/jsonflags", "u"},
{"encoding/json/internal/jsonopts", "u\x01"},
{"encoding/json/internal/jsontest", "\x03f\x15\x03\x83\x01\x01\x012\b\b\x03\x02\x0f"},
{"encoding/json/internal/jsonwire", "\x04r\b\x87\x01\f7\x02\x01\x13\x01\x01"},
{"encoding/json/jsontext", "\x03r\x01\x01\x02\x05\x87\x01\x03\t\x034\x02\x01\x02\x13"},
{"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"},
{"encoding/pem", "\x03l\x0f\x87\x01C\x03"},
{"encoding/xml", "\x02\x01h\x13\x03\x84\x016\x05\n\x01\x02\x11\x02"},
{"errors", "\xdb\x01\x87\x01"},
{"expvar", "tSB\b\v\x17\r\b\x02\x03\x01\x12"},
{"flag", "k\x13\x03\x84\x01.\b\x05\b\x02\x01\x11"},
{"fmt", "~E)\x19\f\"\b\r\x02\x03\x13"},
{"go/ast", "\x03\x01}\x0e\x01u\x03+\b\r\x02\x01\x13\x02"},
{"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/build/constraint", "~\xcc\x01\x01\x13\x02"},
{"go/constant", "\x81\x01\x0f\x81\x01\x01\x026\x01\x02\x13"},
{"go/doc", "\x04}\x01\x05\t>73\x10\x02\x01\x13\x02"},
{"go/doc/comment", "\x03~\xc7\x01\x01\x01\x01\x13\x02"},
{"go/format", "\x03~\x01\v\x01\x02uF"},
{"go/importer", "\x83\x01\a\x01\x01\x04\x01t;"},
{"go/internal/gccgoimporter", "\x02\x01a\x1a\x03\x04\v\x01r\x02.\x01\x05\x11\x01\r\b"},
{"go/internal/gcimporter", "\x02\x7f\x0f\x010\x140.\x15\x03\x02"},
{"go/internal/srcimporter", "\x81\x01\x01\x01\n\x03\x01t.\x01\x05\x12\x02\x15"},
{"go/parser", "\x03{\x03\x01\x02\v\x01u\x01-\x06\x12"},
{"go/printer", "\x81\x01\x01\x02\x03\tu\f\"\x15\x02\x01\x02\f\x05\x02"},
{"go/scanner", "\x03~\x0fu4\x10\x01\x14\x02"},
{"go/token", "\x04}\x87\x01@\x02\x03\x01\x10\x02"},
{"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"},
{"go/version", "\xcc\x01\x7f"},
{"hash", "\x85\x02"},
{"hash/adler32", "~\x15\x16"},
{"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"},
{"encoding/ascii85", "\x86\x02E"},
{"encoding/asn1", "\x03|\x03h(\x01)\r\x02\x01\x11\x03\x01"},
{"encoding/base32", "\x86\x02C\x02"},
{"encoding/base64", "\xaa\x01\\C\x02"},
{"encoding/binary", "\x7f\x87\x01\f*\r\x05"},
{"encoding/csv", "\x02\x01|\x03\x84\x01F\x13\x02"},
{"encoding/gob", "\x02j\x05\x0e\x03h\x1c\v\x01\x03\x1f\b\x12\x01\x10\x02"},
{"encoding/hex", "\x7f\x03\x84\x01C\x03"},
{"encoding/json", "\x03\x01h\n\x01\x01\x02\x01\x01\x03\x03\x84\x016\x0f\x01"},
{"encoding/json/internal", "\x7f"},
{"encoding/json/internal/jsonflags", "v"},
{"encoding/json/internal/jsonopts", "v\x01"},
{"encoding/json/internal/jsontest", "\x03g\x15\x03\x83\x01\x01\x012\b\b\x03\x02\x0f"},
{"encoding/json/internal/jsonwire", "\x04s\b\x87\x01\f7\x02\x01\x13\x01\x01"},
{"encoding/json/jsontext", "\x03s\x01\x01\x02\x05\x87\x01\x03\t\x034\x02\x01\x02\x13"},
{"encoding/json/v2", "\x03\x01h\x03\x01\x01\x03\x02\x01\x01\x02\x01\x04\x03\x84\x01\f\x03'\r\x02\x01\x02\x0f\x02\x02"},
{"encoding/pem", "\x03m\x0f\x87\x01C\x03"},
{"encoding/xml", "\x02\x01i\x13\x03\x84\x016\x05\n\x01\x02\x11\x02"},
{"errors", "\xdc\x01\x87\x01"},
{"expvar", "uSB\b\v\x17\r\b\x02\x03\x01\x12"},
{"flag", "l\x13\x03\x84\x01.\b\x05\b\x02\x01\x11"},
{"fmt", "\x7fE)\x19\f\"\b\r\x02\x03\x13"},
{"go/ast", "\x03\x01~\x0e\x01u\x03+\b\r\x02\x01\x13\x02"},
{"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/build/constraint", "\x7f\xcc\x01\x01\x13\x02"},
{"go/constant", "\x82\x01\x0f\x81\x01\x01\x026\x01\x02\x13"},
{"go/doc", "\x04~\x01\x05\t>73\x10\x02\x01\x13\x02"},
{"go/doc/comment", "\x03\x7f\xc7\x01\x01\x01\x01\x13\x02"},
{"go/format", "\x03\x7f\x01\v\x01\x02uF"},
{"go/importer", "\x84\x01\a\x01\x01\x04\x01t;"},
{"go/internal/gccgoimporter", "\x02\x01b\x1a\x03\x04\v\x01r\x02.\x01\x05\x11\x01\r\b"},
{"go/internal/gcimporter", "\x02\x80\x01\x0f\x010\x140.\x15\x03\x02"},
{"go/internal/srcimporter", "\x82\x01\x01\x01\n\x03\x01t.\x01\x05\x12\x02\x15"},
{"go/parser", "\x03|\x03\x01\x02\v\x01u\x01-\x06\x12"},
{"go/printer", "\x82\x01\x01\x02\x03\tu\f\"\x15\x02\x01\x02\f\x05\x02"},
{"go/scanner", "\x03\x7f\x0fu4\x10\x01\x14\x02"},
{"go/token", "\x04~\x87\x01@\x02\x03\x01\x10\x02"},
{"go/types", "\x03\x01\x06u\x03\x01\x03\b\x03\x02\x0654\x04\x03\t\"\x06\a\b\x01\x01\x01\x02\x01\x10\x02\x02"},
{"go/version", "\xcd\x01\x7f"},
{"hash", "\x86\x02"},
{"hash/adler32", "\x7f\x15\x16"},
{"hash/crc32", "\x7f\x15\x16\x15\x8f\x01\x01\x14"},
{"hash/crc64", "\x7f\x15\x16\xa4\x01"},
{"hash/fnv", "\x7f\x15\x16k"},
{"hash/maphash", "\x94\x01\x11>\x80\x01"},
{"html", "\xcc\x02\x02\x13"},
{"html/template", "\x03r\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/palette", "\x9c\x01"},
{"image/draw", "\x9b\x01\x01\x04"},
{"image/gif", "\x02\x01\x05v\x03\x1a\x01\x01\x01\v\\\x0f"},
{"image/internal/imageutil", "\x9b\x01"},
{"image/jpeg", "\x02|\x1d\x01\x04e"},
{"image/png", "\x02\ag\x11\x12\x02\x06\x01iE"},
{"index/suffixarray", "\x03m\x0e\x87\x01\f-\n\x01"},
{"internal/abi", "\xc6\x01\x9c\x01"},
{"internal/asan", "\xe2\x02"},
{"internal/bisect", "\xc0\x02\r\x01"},
{"internal/buildcfg", "\x81\x01Hj\x06\x02\x05\n\x01"},
{"internal/bytealg", "\xbe\x01\xa4\x01"},
{"image/color/palette", "\x9d\x01"},
{"image/draw", "\x9c\x01\x01\x04"},
{"image/gif", "\x02\x01\x05w\x03\x1a\x01\x01\x01\v\\\x0f"},
{"image/internal/imageutil", "\x9c\x01"},
{"image/jpeg", "\x02}\x1d\x01\x04e"},
{"image/png", "\x02\ah\x11\x12\x02\x06\x01iE"},
{"index/suffixarray", "\x03n\x0e\x87\x01\f-\n\x01"},
{"internal/abi", "\xc7\x01\x9c\x01"},
{"internal/asan", "\xe3\x02"},
{"internal/bisect", "\xc1\x02\r\x01"},
{"internal/buildcfg", "\x82\x01Hj\x06\x02\x05\n\x01"},
{"internal/bytealg", "\xbf\x01\xa4\x01"},
{"internal/byteorder", ""},
{"internal/cfg", ""},
{"internal/cgrouptest", "\x81\x01\\V\x06\x0f\x02\x01\x04\x01"},
{"internal/chacha8rand", "\xa9\x01\x15\b\x9c\x01"},
{"internal/cgrouptest", "\x82\x01\\V\x06\x0f\x02\x01\x04\x01"},
{"internal/chacha8rand", "\xaa\x01\x15\b\x9c\x01"},
{"internal/copyright", ""},
{"internal/coverage", ""},
{"internal/coverage/calloc", ""},
{"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", "\x04}-\x04S\v8\x01\x02\x0e"},
{"internal/coverage/cmerge", "\x81\x01-c"},
{"internal/coverage/decodecounter", "p\x11-\v\x02J.\x17\x18"},
{"internal/coverage/decodemeta", "\x02n\x11\x16\x17\v\x02J."},
{"internal/coverage/encodecounter", "\x02n\x11-\f\x01\x02H\v#\x15"},
{"internal/coverage/encodemeta", "\x02\x01m\x11\x12\x04\x17\r\x02H./"},
{"internal/coverage/pods", "\x04}-\x85\x01\x06\x05\n\x02\x01"},
{"internal/coverage/rtcov", "\xe2\x02"},
{"internal/coverage/slicereader", "p\x11\x84\x01]"},
{"internal/coverage/slicewriter", "\x81\x01\x84\x01"},
{"internal/coverage/stringtab", "\x81\x018\x04H"},
{"internal/coverage/cfile", "u\r\x16\x17\x01\x02\x01\x01\x01\x01\x01\x01\x01$\x02'.\x06\a\n\x01\x03\x0e\x06"},
{"internal/coverage/cformat", "\x04~-\x04S\v8\x01\x02\x0e"},
{"internal/coverage/cmerge", "\x82\x01-c"},
{"internal/coverage/decodecounter", "q\x11-\v\x02J.\x17\x18"},
{"internal/coverage/decodemeta", "\x02o\x11\x16\x17\v\x02J."},
{"internal/coverage/encodecounter", "\x02o\x11-\f\x01\x02H\v#\x15"},
{"internal/coverage/encodemeta", "\x02\x01n\x11\x12\x04\x17\r\x02H./"},
{"internal/coverage/pods", "\x04~-\x85\x01\x06\x05\n\x02\x01"},
{"internal/coverage/rtcov", "\xe3\x02"},
{"internal/coverage/slicereader", "q\x11\x84\x01]"},
{"internal/coverage/slicewriter", "\x82\x01\x84\x01"},
{"internal/coverage/stringtab", "\x82\x018\x04H"},
{"internal/coverage/test", ""},
{"internal/coverage/uleb128", ""},
{"internal/cpu", "\xe2\x02"},
{"internal/dag", "\x04}\xc7\x01\x03"},
{"internal/diff", "\x03~\xc8\x01\x02"},
{"internal/exportdata", "\x02\x01{\x03\x02f\x1c.\x01\x05\x11\x01\x02"},
{"internal/filepathlite", "~*D\x1aB"},
{"internal/fmtsort", "\x04\xb7\x02\r"},
{"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/cpu", "\xe3\x02"},
{"internal/dag", "\x04~\xc7\x01\x03"},
{"internal/diff", "\x03\x7f\xc8\x01\x02"},
{"internal/exportdata", "\x02\x01|\x03\x02f\x1c.\x01\x05\x11\x01\x02"},
{"internal/filepathlite", "\x7f*D\x1aB"},
{"internal/fmtsort", "\x04\xb8\x02\r"},
{"internal/fuzz", "\x03\nK\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/godebug", "\xa6\x01\"\x85\x01\x01\x14"},
{"internal/godebug", "\xa7\x01\"\x85\x01\x01\x14"},
{"internal/godebugs", ""},
{"internal/goexperiment", ""},
{"internal/goos", ""},
{"internal/goroot", "\xb3\x02\x01\x05\x12\x02"},
{"internal/goroot", "\xb4\x02\x01\x05\x12\x02"},
{"internal/gover", "\x04"},
{"internal/goversion", ""},
{"internal/lazyregexp", "\xb3\x02\v\r\x02"},
{"internal/lazytemplate", "\x85\x02.\x18\x02\r"},
{"internal/msan", "\xe2\x02"},
{"internal/nettest", "\x03\nqG@\f\n\x12\x06\x15\x05\x0f"},
{"internal/lazyregexp", "\xb4\x02\v\r\x02"},
{"internal/lazytemplate", "\x86\x02.\x18\x02\r"},
{"internal/msan", "\xe3\x02"},
{"internal/nettest", "\x03\nrG@\f\n\x12\x06\x15\x05\x0f"},
{"internal/nettrace", ""},
{"internal/obscuretestdata", "o\x96\x01."},
{"internal/oserror", "~"},
{"internal/pkgbits", "\x03T\x19\x0e\x03\x04\vu\r!\r\n\x01"},
{"internal/obscuretestdata", "p\x96\x01."},
{"internal/oserror", "\x7f"},
{"internal/pkgbits", "\x03U\x19\x0e\x03\x04\vu\r!\r\n\x01"},
{"internal/platform", ""},
{"internal/poll", "~m\x05\x15;\r\x01\x01\r\x06"},
{"internal/profile", "\x03\x04w\x03\x84\x019\n\x01\x01\x01\x11"},
{"internal/poll", "\x7fm\x05\x15;\r\x01\x01\r\x06"},
{"internal/profile", "\x03\x04x\x03\x84\x019\n\x01\x01\x01\x11"},
{"internal/profilerecord", ""},
{"internal/race", "\xa4\x01\xbe\x01"},
{"internal/reflectlite", "\xa4\x01\"<>\""},
{"internal/runtime/atomic", "\xc6\x01\x9c\x01"},
{"internal/runtime/cgroup", "\xa8\x01?\x04w"},
{"internal/runtime/exithook", "\xdc\x01\x86\x01"},
{"internal/runtime/gc", "\xc6\x01"},
{"internal/runtime/gc/internal/gen", "\nf\x11\x17m\x04\v\x1f\b\x10\x02"},
{"internal/runtime/gc/scan", "\xbe\x01\b\x19\a|"},
{"internal/runtime/maps", "\xa4\x01\x01\x04\x15\b\x03\a\n\t\x03.N"},
{"internal/runtime/math", "\xc6\x01"},
{"internal/race", "\xa5\x01\xbe\x01"},
{"internal/reflectlite", "\xa5\x01\"<>\""},
{"internal/runtime/atomic", "\xc7\x01\x9c\x01"},
{"internal/runtime/cgroup", "\xa9\x01?\x04w"},
{"internal/runtime/exithook", "\xdd\x01\x86\x01"},
{"internal/runtime/gc", "\xc7\x01"},
{"internal/runtime/gc/internal/gen", "\ng\x11\x17m\x04\v\x1f\b\x10\x02"},
{"internal/runtime/gc/scan", "\xbf\x01\b\x19\a|"},
{"internal/runtime/maps", "\xa5\x01\x01\x04\x15\b\x03\a\n\t\x03.N"},
{"internal/runtime/math", "\xc7\x01"},
{"internal/runtime/pprof/label", ""},
{"internal/runtime/startlinetest", ""},
{"internal/runtime/sys", "\xc6\x01\x04"},
{"internal/runtime/syscall/linux", "\xc6\x01\x9c\x01"},
{"internal/runtime/sys", "\xc7\x01\x04"},
{"internal/runtime/syscall/linux", "\xc7\x01\x9c\x01"},
{"internal/runtime/wasitest", ""},
{"internal/saferio", "\x85\x02]"},
{"internal/singleflight", "\xcd\x02"},
{"internal/strconv", "\x94\x02N"},
{"internal/stringslite", "\xa8\x01\xba\x01"},
{"internal/sync", "\xa4\x01\"\x14t\x14"},
{"internal/synctest", "\xa4\x01\xbe\x01"},
{"internal/syscall/execenv", "\xcf\x02"},
{"internal/syscall/unix", "\xeb\x01U\x0e\x01\x13"},
{"internal/sysinfo", "\x02\x01\xbb\x01G.\x18\x02"},
{"internal/saferio", "\x86\x02]"},
{"internal/singleflight", "\xce\x02"},
{"internal/strconv", "\x95\x02N"},
{"internal/stringslite", "\xa9\x01\xba\x01"},
{"internal/sync", "\xa5\x01\"\x14t\x14"},
{"internal/synctest", "\xa5\x01\xbe\x01"},
{"internal/syscall/execenv", "\xd0\x02"},
{"internal/syscall/unix", "\xec\x01U\x0e\x01\x13"},
{"internal/sysinfo", "\x02\x01\xbc\x01G.\x18\x02"},
{"internal/syslist", ""},
{"internal/testenv", "\x03\nq\x02\x01)\x1c\x100-\x01\x05\a\n\x01\x02\x02\x01\f"},
{"internal/testhash", "\x03\x90\x01r\x11:\f"},
{"internal/testlog", "\xcd\x02\x01\x14"},
{"internal/testpty", "~\x03\xb2\x01"},
{"internal/trace", "\x02\x01\x01\x06f\x0e\x03x\x03\x03\x06\x03\t-\n\x01\x01\x01\x11\x06"},
{"internal/trace/internal/testgen", "\x03m\x11v\x03\x02\x03\x013\v\r\x11"},
{"internal/trace/internal/tracev1", "\x03\x01l\x0e\x03~\x06\f7\x01"},
{"internal/trace/raw", "\x02n\x11{\x03\x06E\x01\x13"},
{"internal/trace/testtrace", "\x02\x01{\x03r\x04\x03\x05\x01\x05.\v\x02\b\x02\x01\x05"},
{"internal/testenv", "\x03\nr\x02\x01)\x1c\x100-\x01\x05\a\n\x01\x02\x02\x01\f"},
{"internal/testhash", "\x03\x91\x01r\x11:\f"},
{"internal/testlog", "\xce\x02\x01\x14"},
{"internal/testpty", "\x7f\x03\xb2\x01"},
{"internal/trace", "\x02\x01\x01\x06g\x0e\x03x\x03\x03\x06\x03\t-\n\x01\x01\x01\x11\x06"},
{"internal/trace/internal/testgen", "\x03n\x11v\x03\x02\x03\x013\v\r\x11"},
{"internal/trace/internal/tracev1", "\x03\x01m\x0e\x03~\x06\f7\x01"},
{"internal/trace/raw", "\x02o\x11{\x03\x06E\x01\x13"},
{"internal/trace/testtrace", "\x02\x01|\x03r\x04\x03\x05\x01\x05.\v\x02\b\x02\x01\x05"},
{"internal/trace/tracev2", ""},
{"internal/trace/traceviewer", "\x02g\v\r\x19>\x1f\a\a\x04\b\v\x17\x01\x05\a\n\x01\x02\x0f"},
{"internal/trace/traceviewer", "\x02h\v\r\x19>\x1f\a\a\x04\b\v\x17\x01\x05\a\n\x01\x02\x0f"},
{"internal/trace/traceviewer/format", ""},
{"internal/trace/version", "\x81\x01{\t"},
{"internal/txtar", "\x03~\xb2\x01\x18"},
{"internal/types/errors", "\xca\x02"},
{"internal/unsafeheader", "\xe2\x02"},
{"internal/xcoff", "c\r\x0e\x03h\x1c.\x17\x01"},
{"internal/zstd", "p\x0e\x03\x84\x01\x0f"},
{"io", "~\xcf\x01"},
{"io/fs", "~*,13\x10\x14\x04"},
{"io/ioutil", "\x85\x02\x01-\x15\x03"},
{"iter", "\xda\x01f\""},
{"log", "\x81\x01\x84\x01\x05)\r\r\x01\x0e"},
{"internal/trace/version", "\x82\x01{\t"},
{"internal/txtar", "\x03\x7f\xb2\x01\x18"},
{"internal/types/errors", "\xcb\x02"},
{"internal/unsafeheader", "\xe3\x02"},
{"internal/xcoff", "d\r\x0e\x03h\x1c.\x17\x01"},
{"internal/zstd", "q\x0e\x03\x84\x01\x0f"},
{"io", "\x7f\xcf\x01"},
{"io/fs", "\x7f*,13\x10\x14\x04"},
{"io/ioutil", "\x86\x02\x01-\x15\x03"},
{"iter", "\xdb\x01f\""},
{"log", "\x82\x01\x84\x01\x05)\r\r\x01\x0e"},
{"log/internal", ""},
{"log/slog", "\x03\n^\t\n\x03H<\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/benchmarks", "\rq\x03\x84\x01\x06\x03<\x12"},
{"log/slog/internal/buffer", "\xcd\x02"},
{"log/syslog", "~\x03\x88\x01\x12\x18\x18\x02\x0f"},
{"maps", "\x88\x02Z"},
{"math", "\xbe\x01VN"},
{"math/big", "\x03{\x03(\x15G\f\x03\x022\x02\x01\x02\x15"},
{"math/big/internal/asmgen", "\x03\x01}\x93\x014\x03"},
{"math/bits", "\xe2\x02"},
{"math/cmplx", "\x91\x02\x03"},
{"math/rand", "\xc7\x01J<\x01\x14"},
{"math/rand/v2", "~+\x03e\x03N"},
{"mime", "\x02\x01l\x0f\x03\x84\x01\v#\x15\x03\x02\x11\x02"},
{"mime/multipart", "\x02\x01P+\x03F>\v\x01\a\x02\x17\x02\x06\x0f\x02\x01\x17"},
{"mime/quotedprintable", "\x02\x01~\x84\x01"},
{"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\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", "\x02Y#\x03\x84\x01\x04\a\v\x01\x15\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x11\x10"},
{"net/http/cookiejar", "\x04z\x03\x9a\x01\x01\b\t\x05\x16\x03\x02\x0f\x04"},
{"net/http/fcgi", "\x02\x01\nc\x0e\x03\x84\x01\x16\x01\x01\x16\x18\x02\x0f"},
{"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", "\rNwI\x16+"},
{"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\x01m\x0e\x03\x84\x01"},
{"net/http/internal/ascii", "\xcb\x02\x13"},
{"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/httpcommon", "\rq\x03\xa0\x01\x10\x01\x17\x01\x01\x02\x1f\x02"},
{"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"},
{"log/slog/internal/benchmarks", "\rr\x03\x84\x01\x06\x03<\x12"},
{"log/slog/internal/buffer", "\xce\x02"},
{"log/syslog", "\x7f\x03\x88\x01\x12\x18\x18\x02\x0f"},
{"maps", "\x89\x02Z"},
{"math", "\xbf\x01VN"},
{"math/big", "\x03|\x03(\x15G\f\x03\x022\x02\x01\x02\x15"},
{"math/big/internal/asmgen", "\x03\x01~\x93\x014\x03"},
{"math/bits", "\xe3\x02"},
{"math/cmplx", "\x92\x02\x03"},
{"math/rand", "\xc8\x01J<\x01\x14"},
{"math/rand/v2", "\x7f+\x03e\x03N"},
{"mime", "\x02\x01m\x0f\x03\x84\x01\v#\x15\x03\x02\x11\x02"},
{"mime/multipart", "\x02\x01Q+\x03F>\v\x01\a\x02\x17\x02\x06\x0f\x02\x01\x17"},
{"mime/quotedprintable", "\x02\x01\x7f\x84\x01"},
{"net", "\x04\tr*\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\x02O\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", "\x02Z#\x03\x84\x01\x04\a\v\x01\x15\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x11\x10"},
{"net/http/cookiejar", "\x04{\x03\x9a\x01\x01\b\t\x05\x16\x03\x02\x0f\x04"},
{"net/http/fcgi", "\x02\x01\nd\x0e\x03\x84\x01\x16\x01\x01\x16\x18\x02\x0f"},
{"net/http/httptest", "\x02\x01\nO\x02#\x01P4\x04\x12\x01\f\t\x02\r\n\x01\x02\x03\f\x06\n"},
{"net/http/httptrace", "\rOwI\x16+"},
{"net/http/httputil", "\x02\x01\nr\x03F>\x04\x0f\x03\x01\x05\x02\x01\r\x01\x19\x02\x0f\x10"},
{"net/http/internal", "\x02\x01n\x0e\x03\x84\x01"},
{"net/http/internal/ascii", "\xcc\x02\x13"},
{"net/http/internal/http2", "\x02\x01\x03\x01\x06G\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/httpcommon", "\rr\x03\xa0\x01\x10\x01\x17\x01\x01\x02\x1f\x02"},
{"net/http/internal/httpsfv", "\xc9\x02\x02\x01\x11\x04"},
{"net/http/internal/testcert", "\xcc\x02"},
{"net/http/pprof", "\x02\x01\nu\x18.\x11-\x04\x13\x16\x01\r\x04\x03\x01\x02\x01\x11"},
{"net/internal/cgotest", ""},
{"net/internal/socktest", "\x81\x01\xcc\x01\x02"},
{"net/mail", "\x02|\x03\x84\x01\x04\x0f\x03\x16\x1a\x02\x0f\x04"},
{"net/netip", "\x04z*\x01h\x036\x17"},
{"net/rpc", "\x02p\f\x03\x0f\nk\x04\x12\x01\x1f\r\x03\x02"},
{"net/rpc/jsonrpc", "t\n\x03\x84\x01\x16\x13\x1f"},
{"net/smtp", "\x195\r\x14\x0f\x03\x84\x01\x16\x16\x1a"},
{"net/textproto", "\x02\x01{\x03\x84\x01\f\n/\x01\x02\x15"},
{"net/url", "~\x03Ff\v\x10\x02\x01\x17"},
{"os", "~*\x01\x19\x04\x11\x14\x01\x03\x01\x05\x10\x01:\b\x05\x01\x01\r\x06"},
{"os/exec", "\x03\nqI(\x01\x15\x01-\x06\a\n\x01\x03\x01\r"},
{"os/exec/internal/fdtest", "\xcf\x02"},
{"os/signal", "\r\xa6\x02\x15\x05\x02"},
{"os/user", "\x02\x01{\x03\x84\x01.\r\n\x01\x02"},
{"path", "~*\xb8\x01"},
{"path/filepath", "~*\x1aD-\r\b\x03\x04\x11"},
{"plugin", "~"},
{"reflect", "~&\x04\x1e\x03\x11\b\x04\x05\x17\x06\t/\n\x03\x11\x02\x02"},
{"net/internal/socktest", "\x82\x01\xcc\x01\x02"},
{"net/mail", "\x02}\x03\x84\x01\x04\x0f\x03\x16\x1a\x02\x0f\x04"},
{"net/netip", "\x04{*\x01h\x036\x17"},
{"net/rpc", "\x02q\f\x03\x0f\nk\x04\x12\x01\x1f\r\x03\x02"},
{"net/rpc/jsonrpc", "u\n\x03\x84\x01\x16\x13\x1f"},
{"net/smtp", "\x196\r\x14\x0f\x03\x84\x01\x16\x16\x1a"},
{"net/textproto", "\x02\x01|\x03\x84\x01\f\n/\x01\x02\x15"},
{"net/url", "\x7f\x03Ff\v\x10\x02\x01\x17"},
{"os", "\x7f*\x01\x19\x04\x11\x14\x01\x03\x01\x05\x10\x01:\b\x05\x01\x01\r\x06"},
{"os/exec", "\x03\nrI(\x01\x15\x01-\x06\a\n\x01\x03\x01\r"},
{"os/exec/internal/fdtest", "\xd0\x02"},
{"os/signal", "\r\xa7\x02\x15\x05\x02"},
{"os/user", "\x02\x01|\x03\x84\x01.\r\n\x01\x02"},
{"path", "\x7f*\xb8\x01"},
{"path/filepath", "\x7f*\x1aD-\r\b\x03\x04\x11"},
{"plugin", "\x7f"},
{"reflect", "\x7f&\x04\x1e\x03\x11\b\x04\x05\x17\x06\t/\n\x03\x11\x02\x02"},
{"reflect/internal/example1", ""},
{"reflect/internal/example2", ""},
{"regexp", "\x03\x82\x02\x037\t\x02\x01\x02\x11\x02"},
{"regexp/syntax", "\xc8\x02\x01\x01\x01\x02\x11\x02"},
{"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", "\xb0\x01U"},
{"runtime/debug", "\x81\x01V\\\r\b\x02\x01\x11\x06"},
{"runtime/metrics", "\xc8\x01I/\""},
{"runtime/pprof", "\x02\x01\x01\x03\x06c\x0e\x03#5\v!\f\"\r\b\x01\x01\x01\x02\x02\n\x03\x06"},
{"runtime/race", "\xc6\x02"},
{"regexp", "\x03\x83\x02\x037\t\x02\x01\x02\x11\x02"},
{"regexp/syntax", "\xc9\x02\x01\x01\x01\x02\x11\x02"},
{"runtime", "\xa5\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", "\xb1\x01U"},
{"runtime/debug", "\x82\x01V\\\r\b\x02\x01\x11\x06"},
{"runtime/metrics", "\xc9\x01I/\""},
{"runtime/pprof", "\x02\x01\x01\x03\x06d\x0e\x03#5\v!\f\"\r\b\x01\x01\x01\x02\x02\n\x03\x06"},
{"runtime/race", "\xc7\x02"},
{"runtime/race/internal/amd64v1", ""},
{"runtime/trace", "\rq\x03{\t;\b\x05\x01\x0e\x06"},
{"slices", "\x04\x84\x02\fN"},
{"sort", "\xdb\x0194"},
{"strconv", "~*C\x01t"},
{"strings", "~&\x04D\x19\x03\f9\x11\x02\x02"},
{"runtime/trace", "\rr\x03{\t;\b\x05\x01\x0e\x06"},
{"slices", "\x04\x85\x02\fN"},
{"sort", "\xdc\x0194"},
{"strconv", "\x7f*C\x01t"},
{"strings", "\x7f&\x04D\x19\x03\f9\x11\x02\x02"},
{"structs", ""},
{"sync", "\xda\x01\x02\x11\x01R\x0e\x14"},
{"sync/atomic", "\xe2\x02"},
{"syscall", "~'\x03\x01\x1d\n\x04\x06\r\x04U\b\x05\x01\x14"},
{"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", "SV\\\x126\x03\x12"},
{"testing/fstest", "~\x03\x84\x01\x01\n(\x10\x03\t\b"},
{"testing/internal/testdeps", "\x02\v\xb7\x011\x10.\x03\x05\x03\x06\a\x02\x0f"},
{"testing/iotest", "\x03{\x03\x84\x01\x04"},
{"testing/quick", "\x80\x01\x01\x90\x01\x05%\x10\x11"},
{"testing/slogtest", "\rq\x03\x8a\x010\x05\x10\f"},
{"testing/synctest", "\xee\x01b\f\x06"},
{"text/scanner", "\x03~\x84\x01.+\x02"},
{"text/tabwriter", "\x81\x01\x84\x01["},
{"text/template", "~\x03BB\x01\n\"\x01\x05\x01\x02\x05\v\x02\x0e\x03\x02"},
{"text/template/parse", "\x03~\xbf\x01\n\x01\x13\x02"},
{"time", "~*D(,\r\x02\x13"},
{"time/tzdata", "~\xd1\x01\x13"},
{"sync", "\xdb\x01\x02\x11\x01R\x0e\x14"},
{"sync/atomic", "\xe3\x02"},
{"syscall", "\x7f'\x03\x01\x1d\n\x04\x06\r\x04U\b\x05\x01\x14"},
{"testing", "\x03\nr\x02\x01Y\x17\x14\f\x05\x1d\x06\x02\x05\x02\x05\x01\x02\x01\x02\x01\x0e\x02\x04"},
{"testing/cryptotest", "TV\\\x126\x03\x12"},
{"testing/fstest", "\x7f\x03\x84\x01\x01\n(\x10\x03\t\b"},
{"testing/internal/testdeps", "\x02\v\xb8\x011\x10.\x03\x05\x03\x06\a\x02\x0f"},
{"testing/iotest", "\x03|\x03\x84\x01\x04"},
{"testing/quick", "\x81\x01\x01\x90\x01\x05%\x10\x11"},
{"testing/slogtest", "\rr\x03\x8a\x010\x05\x10\f"},
{"testing/synctest", "\xef\x01b\f\x06"},
{"text/scanner", "\x03\x7f\x84\x01.+\x02"},
{"text/tabwriter", "\x82\x01\x84\x01["},
{"text/template", "\x7f\x03BB\x01\n\"\x01\x05\x01\x02\x05\v\x02\x0e\x03\x02"},
{"text/template/parse", "\x03\x7f\xbf\x01\n\x01\x13\x02"},
{"time", "\x7f*D(,\r\x02\x13"},
{"time/tzdata", "\x7f\xd1\x01\x13"},
{"unicode", ""},
{"unicode/utf16", ""},
{"unicode/utf8", ""},
{"unique", "\xa4\x01\"&\x01S\r\x01\x14\x19"},
{"unique", "\xa5\x01\"&\x01S\r\x01\x14\x19"},
{"unsafe", ""},
{"uuid", "\x03\x01O\x1d\x03\v\xcf\x01\x0f"},
{"vendor/golang.org/x/crypto/chacha20", "\x10`\x0e\x96\x01,)"},
{"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"},
{"uuid", "\x03\x01P\x1d\x03\v\xcf\x01\x0f"},
{"vendor/golang.org/x/crypto/chacha20", "\x10a\x0e\x96\x01,)"},
{"vendor/golang.org/x/crypto/chacha20poly1305", "\x10\aZ\x0e\xe6\x01\x05\x01\f"},
{"vendor/golang.org/x/crypto/cryptobyte", "n\x11\x03\x91\x01)!\v"},
{"vendor/golang.org/x/crypto/cryptobyte/asn1", ""},
{"vendor/golang.org/x/crypto/hkdf", "\x18\x01e\x15r"},
{"vendor/golang.org/x/crypto/internal/alias", "\xe2\x02"},
{"vendor/golang.org/x/crypto/internal/poly1305", "Z\x16\xa4\x01"},
{"vendor/golang.org/x/net/dns/dnsmessage", "~\xca\x01"},
{"vendor/golang.org/x/net/http/httpguts", "\x9b\x02\x16\x1a\x15\x10"},
{"vendor/golang.org/x/net/http/httpproxy", "~\x03\x9a\x01\x12\x05\x01\x18\x15\x10"},
{"vendor/golang.org/x/net/http2/hpack", "\x03{\x03\x84\x01H"},
{"vendor/golang.org/x/net/http3", "\x9c\x02@\x06\x0f\x04"},
{"vendor/golang.org/x/net/idna", "\x81\x01\x90\x01:\x13\x02\x17\x02\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/net/internal/httpcommon", "\rq\x03\xa0\x01\x10\x01\x17\x01\x01\x02\x1f\x02"},
{"vendor/golang.org/x/net/internal/quic/quicwire", "p"},
{"vendor/golang.org/x/net/nettest", "\x03m\x0e\x03\x84\x01\x11\x05\x18\x01\f\n\x01\x02\x02\x01\f"},
{"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\""},
{"vendor/golang.org/x/crypto/hkdf", "\x18\x01f\x15r"},
{"vendor/golang.org/x/crypto/internal/alias", "\xe3\x02"},
{"vendor/golang.org/x/crypto/internal/poly1305", "[\x16\xa4\x01"},
{"vendor/golang.org/x/net/dns/dnsmessage", "\x7f\xca\x01"},
{"vendor/golang.org/x/net/http/httpguts", "\x9c\x02\x16\x1a\x15\x10"},
{"vendor/golang.org/x/net/http/httpproxy", "\x7f\x03\x9a\x01\x12\x05\x01\x18\x15\x10"},
{"vendor/golang.org/x/net/http2/hpack", "\x03|\x03\x84\x01H"},
{"vendor/golang.org/x/net/http3", "\x9d\x02@\x06\x0f\x04"},
{"vendor/golang.org/x/net/idna", "\x82\x01\x90\x01:\x13\x02\x17\x02\x01"},
{"vendor/golang.org/x/net/internal/http3", "\rO#\x03\x84\x01\v\x04\a\x01\x05\x10\x01\x16\x02\x01\x02\x0f\x10\x02\x04\x03"},
{"vendor/golang.org/x/net/internal/httpcommon", "\rr\x03\xa0\x01\x10\x01\x17\x01\x01\x02\x1f\x02"},
{"vendor/golang.org/x/net/internal/quic/quicwire", "q"},
{"vendor/golang.org/x/net/nettest", "\x03n\x0e\x03\x84\x01\x11\x05\x18\x01\f\n\x01\x02\x02\x01\f"},
{"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", "\xb4\x02\r\n\x01\x17"},
{"vendor/golang.org/x/text/secure/bidirule", "\x7f\xe2\x01\x18\x01"},
{"vendor/golang.org/x/text/transform", "\x03|\x87\x01["},
{"vendor/golang.org/x/text/unicode/bidi", "\x03\bw\x88\x01@\x17"},
{"vendor/golang.org/x/text/unicode/norm", "q\x11\x84\x01H\x13\x18"},
{"weak", "\xa5\x01\x9c\x01\""},
}
// bootstrap is the list of bootstrap packages extracted from cmd/dist.
+2
View File
@@ -9153,6 +9153,7 @@ var PackageSymbols = map[string][]Symbol{
{"CrossOriginProtection", Type, 25, ""},
{"DefaultClient", Var, 0, ""},
{"DefaultMaxHeaderBytes", Const, 0, ""},
{"DefaultMaxHeaderValueCount", Const, 27, ""},
{"DefaultMaxIdleConnsPerHost", Const, 0, ""},
{"DefaultServeMux", Var, 0, ""},
{"DefaultTransport", Var, 0, ""},
@@ -9317,6 +9318,7 @@ var PackageSymbols = map[string][]Symbol{
{"Server.Handler", Field, 0, ""},
{"Server.IdleTimeout", Field, 8, ""},
{"Server.MaxHeaderBytes", Field, 0, ""},
{"Server.MaxHeaderValueCount", Field, 27, ""},
{"Server.Protocols", Field, 24, ""},
{"Server.ReadHeaderTimeout", Field, 8, ""},
{"Server.ReadTimeout", Field, 0, ""},
+6 -5
View File
@@ -1365,7 +1365,7 @@ github.com/opencloud-eu/icap-client
# github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260818063016-69f82a7dde55
## explicit; go 1.23
github.com/opencloud-eu/libre-graph-api-go
# github.com/opencloud-eu/reva/v2 v2.48.1-0.20260818072644-485a511e30c2
# github.com/opencloud-eu/reva/v2 v2.48.1-0.20260819103057-5d7976d4bed3
## explicit; go 1.25.8
github.com/opencloud-eu/reva/v2/cmd/revad/internal/grace
github.com/opencloud-eu/reva/v2/cmd/revad/runtime
@@ -2405,7 +2405,7 @@ go.yaml.in/yaml/v2
# go.yaml.in/yaml/v3 v3.0.4
## explicit; go 1.16
go.yaml.in/yaml/v3
# golang.org/x/crypto v0.54.0
# golang.org/x/crypto v0.55.0
## explicit; go 1.25.0
golang.org/x/crypto/argon2
golang.org/x/crypto/bcrypt
@@ -2458,7 +2458,7 @@ golang.org/x/image/vector
golang.org/x/image/vp8
golang.org/x/image/vp8l
golang.org/x/image/webp
# golang.org/x/mod v0.37.0
# golang.org/x/mod v0.38.0
## explicit; go 1.25.0
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/module
@@ -2511,7 +2511,7 @@ golang.org/x/sys/windows/svc/mgr
# golang.org/x/term v0.45.0
## explicit; go 1.25.0
golang.org/x/term
# golang.org/x/text v0.40.0
# golang.org/x/text v0.41.0
## explicit; go 1.25.0
golang.org/x/text/cases
golang.org/x/text/collate
@@ -2541,7 +2541,7 @@ golang.org/x/text/width
# golang.org/x/time v0.15.0
## explicit; go 1.25.0
golang.org/x/time/rate
# golang.org/x/tools v0.47.0
# golang.org/x/tools v0.48.0
## explicit; go 1.25.0
golang.org/x/tools/cover
golang.org/x/tools/go/ast/astutil
@@ -2561,6 +2561,7 @@ golang.org/x/tools/internal/gcimporter
golang.org/x/tools/internal/gocommand
golang.org/x/tools/internal/gopathwalk
golang.org/x/tools/internal/imports
golang.org/x/tools/internal/modindex
golang.org/x/tools/internal/packagesinternal
golang.org/x/tools/internal/pkgbits
golang.org/x/tools/internal/stdlib