mirror of
https://github.com/DNSCrypt/dnscrypt-proxy.git
synced 2026-10-12 02:01:53 +00:00
Update deps
quic-g0 0.57.1 fixes a panic when using Go 1.26
This commit is contained in:
@@ -15,7 +15,7 @@ require (
|
||||
github.com/hectane/go-acl v0.0.0-20230122075934-ca0b05cb1adb
|
||||
github.com/jedisct1/dlog v0.0.0-20241212093805-3c5fd791b405
|
||||
github.com/jedisct1/go-clocksmith v0.0.0-20250224222044-e151f21a353a
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20240423203910-07a0735c7774
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20251112173516-191fc465df31
|
||||
github.com/jedisct1/go-hpke-compact v0.0.0-20241212093903-5caa4621366f
|
||||
github.com/jedisct1/go-ipcrypt v0.1.1
|
||||
github.com/jedisct1/go-minisign v0.0.0-20241212093149-d2f9f49435c7
|
||||
@@ -26,9 +26,9 @@ require (
|
||||
github.com/lifenjoiner/dhcpdns v0.0.7
|
||||
github.com/miekg/dns v1.1.68
|
||||
github.com/powerman/check v1.9.0
|
||||
github.com/quic-go/quic-go v0.56.0
|
||||
golang.org/x/crypto v0.43.0
|
||||
golang.org/x/net v0.46.0
|
||||
github.com/quic-go/quic-go v0.57.1
|
||||
golang.org/x/crypto v0.45.0
|
||||
golang.org/x/net v0.47.0
|
||||
golang.org/x/sys v0.38.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
)
|
||||
@@ -40,12 +40,12 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/powerman/deepequal v0.1.0 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/smartystreets/goconvey v1.8.1 // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
golang.org/x/tools v0.39.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect
|
||||
google.golang.org/grpc v1.76.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
|
||||
@@ -33,8 +33,8 @@ github.com/jedisct1/dlog v0.0.0-20241212093805-3c5fd791b405 h1:6j/0utSiy3KhZSpFJ
|
||||
github.com/jedisct1/dlog v0.0.0-20241212093805-3c5fd791b405/go.mod h1:OO1HpQNlMCMaPdHPuI00fhChZQZ8npbVTTjMvJUxUqQ=
|
||||
github.com/jedisct1/go-clocksmith v0.0.0-20250224222044-e151f21a353a h1:8z8OvuZGZYGuvTeT5RD80ii6B6LftADl0EQr2z5asCg=
|
||||
github.com/jedisct1/go-clocksmith v0.0.0-20250224222044-e151f21a353a/go.mod h1:SAINchklztk2jcLWJ4bpNF4KnwDUSUTX+cJbspWC2Rw=
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20240423203910-07a0735c7774 h1:DobL5d8UxrYzlD0PbU/EVBAGHuDiFyH46gr6povMw50=
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20240423203910-07a0735c7774/go.mod h1:mEGEFZsGe4sG5Mb3Xi89pmsy+TZ0946ArbYMGKAM5uA=
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20251112173516-191fc465df31 h1:O2qUxpVUeJxoBU5FJ0vGD03g5bY9uRrouaLlJeVOHr8=
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20251112173516-191fc465df31/go.mod h1:mEGEFZsGe4sG5Mb3Xi89pmsy+TZ0946ArbYMGKAM5uA=
|
||||
github.com/jedisct1/go-hpke-compact v0.0.0-20241212093903-5caa4621366f h1:h5/HKrLaDfrb/Zi1y8eCsPGQpcOnKIslT/OpFc81i4c=
|
||||
github.com/jedisct1/go-hpke-compact v0.0.0-20241212093903-5caa4621366f/go.mod h1:IjVYCPbDciyDZpJpUIYodX+FvctxGmnHVZ/ZwGBCjNA=
|
||||
github.com/jedisct1/go-ipcrypt v0.1.1 h1:ZTcnCphIGyF5gePcq5x1+S/1JO1iavO2D3FSnIq5Zks=
|
||||
@@ -63,35 +63,35 @@ github.com/powerman/check v1.9.0 h1:ppv0i78Gpd5P7phxfryPtSXZmUWiJxLyccusKWMG+Xk=
|
||||
github.com/powerman/check v1.9.0/go.mod h1:i+FJaMwkYxByGnZ786ZBLiHMG78psGIQcV7UhCtwkUY=
|
||||
github.com/powerman/deepequal v0.1.0 h1:sVwtyTsBuYIvdbLR1O2wzRY63YgPqdGZmk/o80l+C/U=
|
||||
github.com/powerman/deepequal v0.1.0/go.mod h1:3k7aG/slufBhUANdN67o/UPg8i5YaiJ6FmibWX0cn04=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.56.0 h1:q/TW+OLismmXAehgFLczhCDTYB3bFmua4D9lsNBWxvY=
|
||||
github.com/quic-go/quic-go v0.56.0/go.mod h1:9gx5KsFQtw2oZ6GZTyh+7YEvOxWCL9WZAepnHxgAo6c=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
|
||||
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
|
||||
github.com/smarty/assertions v1.16.0 h1:EvHNkdRA4QHMrn75NZSoUQ/mAUXAYWfatfB01yTCzfY=
|
||||
github.com/smarty/assertions v1.16.0/go.mod h1:duaaFdCS0K9dnoM50iyek/eYINOZ64gbh1Xlf6LG7AI=
|
||||
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
|
||||
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
|
||||
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
||||
|
||||
+380
-1
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
const (
|
||||
DefaultPort = 443
|
||||
DefaultDoTPort = 853
|
||||
DefaultDNSPort = 53
|
||||
StampScheme = "sdns://"
|
||||
)
|
||||
@@ -69,6 +70,7 @@ type ServerStamp struct {
|
||||
Path string
|
||||
Props ServerInformalProperties
|
||||
Proto StampProtoType
|
||||
BootstrapIPs []string
|
||||
}
|
||||
|
||||
func NewDNSCryptServerStampFromLegacy(serverAddrStr string, serverPkStr string, providerName string, props ServerInformalProperties) (ServerStamp, error) {
|
||||
@@ -108,6 +110,10 @@ func NewServerStampFromString(stampStr string) (ServerStamp, error) {
|
||||
return newDNSCryptServerStamp(bin)
|
||||
} else if bin[0] == uint8(StampProtoTypeDoH) {
|
||||
return newDoHServerStamp(bin)
|
||||
} else if bin[0] == uint8(StampProtoTypeTLS) {
|
||||
return newDoTServerStamp(bin)
|
||||
} else if bin[0] == uint8(StampProtoTypeDoQ) {
|
||||
return newDoQServerStamp(bin)
|
||||
} else if bin[0] == uint8(StampProtoTypeODoHTarget) {
|
||||
return newODoHTargetStamp(bin)
|
||||
} else if bin[0] == uint8(StampProtoTypeDNSCryptRelay) {
|
||||
@@ -275,6 +281,9 @@ func newDoHServerStamp(bin []byte) (ServerStamp, error) {
|
||||
}
|
||||
pos++
|
||||
if length > 0 {
|
||||
if length != 32 {
|
||||
return stamp, errors.New("Invalid stamp (certificate hash must be 32 bytes)")
|
||||
}
|
||||
stamp.Hashes = append(stamp.Hashes, bin[pos:pos+length])
|
||||
}
|
||||
pos += length
|
||||
@@ -299,6 +308,29 @@ func newDoHServerStamp(bin []byte) (ServerStamp, error) {
|
||||
stamp.Path = string(bin[pos : pos+length])
|
||||
pos += length
|
||||
|
||||
// Parse optional bootstrap IP addresses (VLP format)
|
||||
if pos < binLen {
|
||||
for {
|
||||
if pos >= binLen {
|
||||
break
|
||||
}
|
||||
vlen := int(bin[pos])
|
||||
length = vlen & ^0x80
|
||||
if 1+length > binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
if length > 0 {
|
||||
bootstrapIP := string(bin[pos : pos+length])
|
||||
stamp.BootstrapIPs = append(stamp.BootstrapIPs, bootstrapIP)
|
||||
}
|
||||
pos += length
|
||||
if vlen&0x80 != 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if pos != binLen {
|
||||
return stamp, errors.New("Invalid stamp (garbage after end)")
|
||||
}
|
||||
@@ -328,6 +360,202 @@ func newDoHServerStamp(bin []byte) (ServerStamp, error) {
|
||||
return stamp, nil
|
||||
}
|
||||
|
||||
// id(u8)=0x03 props addrLen(1) serverAddr hashLen(1) hash hostNameLen(1) hostName [ bootstrapLen(1) bootstrap ]
|
||||
|
||||
func newDoTServerStamp(bin []byte) (ServerStamp, error) {
|
||||
stamp := ServerStamp{Proto: StampProtoTypeTLS}
|
||||
if len(bin) < 13 {
|
||||
return stamp, errors.New("Stamp is too short")
|
||||
}
|
||||
stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
|
||||
binLen := len(bin)
|
||||
pos := 9
|
||||
|
||||
length := int(bin[pos])
|
||||
if 1+length >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
stamp.ServerAddrStr = string(bin[pos : pos+length])
|
||||
pos += length
|
||||
|
||||
for {
|
||||
vlen := int(bin[pos])
|
||||
length = vlen & ^0x80
|
||||
if 1+length >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
if length > 0 {
|
||||
if length != 32 {
|
||||
return stamp, errors.New("Invalid stamp (certificate hash must be 32 bytes)")
|
||||
}
|
||||
stamp.Hashes = append(stamp.Hashes, bin[pos:pos+length])
|
||||
}
|
||||
pos += length
|
||||
if vlen&0x80 != 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
length = int(bin[pos])
|
||||
if length >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
stamp.ProviderName = string(bin[pos : pos+length])
|
||||
pos += length
|
||||
|
||||
// Parse optional bootstrap IP addresses (VLP format)
|
||||
if pos < binLen {
|
||||
for {
|
||||
if pos >= binLen {
|
||||
break
|
||||
}
|
||||
vlen := int(bin[pos])
|
||||
length = vlen & ^0x80
|
||||
if 1+length > binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
if length > 0 {
|
||||
bootstrapIP := string(bin[pos : pos+length])
|
||||
stamp.BootstrapIPs = append(stamp.BootstrapIPs, bootstrapIP)
|
||||
}
|
||||
pos += length
|
||||
if vlen&0x80 != 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if pos != binLen {
|
||||
return stamp, errors.New("Invalid stamp (garbage after end)")
|
||||
}
|
||||
|
||||
if len(stamp.ServerAddrStr) > 0 {
|
||||
colIndex := strings.LastIndex(stamp.ServerAddrStr, ":")
|
||||
bracketIndex := strings.LastIndex(stamp.ServerAddrStr, "]")
|
||||
if colIndex < bracketIndex {
|
||||
colIndex = -1
|
||||
}
|
||||
if colIndex < 0 {
|
||||
colIndex = len(stamp.ServerAddrStr)
|
||||
stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultDoTPort)
|
||||
}
|
||||
if colIndex >= len(stamp.ServerAddrStr)-1 {
|
||||
return stamp, errors.New("Invalid stamp (empty port)")
|
||||
}
|
||||
ipOnly := stamp.ServerAddrStr[:colIndex]
|
||||
if err := validatePort(stamp.ServerAddrStr[colIndex+1:]); err != nil {
|
||||
return stamp, errors.New("Invalid stamp (port range)")
|
||||
}
|
||||
if ipOnly != "" && net.ParseIP(strings.TrimRight(strings.TrimLeft(ipOnly, "["), "]")) == nil {
|
||||
return stamp, errors.New("Invalid stamp (IP address)")
|
||||
}
|
||||
}
|
||||
|
||||
return stamp, nil
|
||||
}
|
||||
|
||||
// id(u8)=0x04 props addrLen(1) serverAddr hashLen(1) hash hostNameLen(1) hostName [ bootstrapLen(1) bootstrap ]
|
||||
|
||||
func newDoQServerStamp(bin []byte) (ServerStamp, error) {
|
||||
stamp := ServerStamp{Proto: StampProtoTypeDoQ}
|
||||
if len(bin) < 13 {
|
||||
return stamp, errors.New("Stamp is too short")
|
||||
}
|
||||
stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
|
||||
binLen := len(bin)
|
||||
pos := 9
|
||||
|
||||
length := int(bin[pos])
|
||||
if 1+length >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
stamp.ServerAddrStr = string(bin[pos : pos+length])
|
||||
pos += length
|
||||
|
||||
for {
|
||||
vlen := int(bin[pos])
|
||||
length = vlen & ^0x80
|
||||
if 1+length >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
if length > 0 {
|
||||
if length != 32 {
|
||||
return stamp, errors.New("Invalid stamp (certificate hash must be 32 bytes)")
|
||||
}
|
||||
stamp.Hashes = append(stamp.Hashes, bin[pos:pos+length])
|
||||
}
|
||||
pos += length
|
||||
if vlen&0x80 != 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
length = int(bin[pos])
|
||||
if length >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
stamp.ProviderName = string(bin[pos : pos+length])
|
||||
pos += length
|
||||
|
||||
// Parse optional bootstrap IP addresses (VLP format)
|
||||
if pos < binLen {
|
||||
for {
|
||||
if pos >= binLen {
|
||||
break
|
||||
}
|
||||
vlen := int(bin[pos])
|
||||
length = vlen & ^0x80
|
||||
if 1+length > binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
if length > 0 {
|
||||
bootstrapIP := string(bin[pos : pos+length])
|
||||
stamp.BootstrapIPs = append(stamp.BootstrapIPs, bootstrapIP)
|
||||
}
|
||||
pos += length
|
||||
if vlen&0x80 != 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if pos != binLen {
|
||||
return stamp, errors.New("Invalid stamp (garbage after end)")
|
||||
}
|
||||
|
||||
if len(stamp.ServerAddrStr) > 0 {
|
||||
colIndex := strings.LastIndex(stamp.ServerAddrStr, ":")
|
||||
bracketIndex := strings.LastIndex(stamp.ServerAddrStr, "]")
|
||||
if colIndex < bracketIndex {
|
||||
colIndex = -1
|
||||
}
|
||||
if colIndex < 0 {
|
||||
colIndex = len(stamp.ServerAddrStr)
|
||||
stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultDoTPort)
|
||||
}
|
||||
if colIndex >= len(stamp.ServerAddrStr)-1 {
|
||||
return stamp, errors.New("Invalid stamp (empty port)")
|
||||
}
|
||||
ipOnly := stamp.ServerAddrStr[:colIndex]
|
||||
if err := validatePort(stamp.ServerAddrStr[colIndex+1:]); err != nil {
|
||||
return stamp, errors.New("Invalid stamp (port range)")
|
||||
}
|
||||
if ipOnly != "" && net.ParseIP(strings.TrimRight(strings.TrimLeft(ipOnly, "["), "]")) == nil {
|
||||
return stamp, errors.New("Invalid stamp (IP address)")
|
||||
}
|
||||
}
|
||||
|
||||
return stamp, nil
|
||||
}
|
||||
|
||||
// id(u8)=0x05 props hostNameLen(1) hostName pathLen(1) path
|
||||
|
||||
func newODoHTargetStamp(bin []byte) (ServerStamp, error) {
|
||||
@@ -431,6 +659,9 @@ func newODoHRelayStamp(bin []byte) (ServerStamp, error) {
|
||||
}
|
||||
pos++
|
||||
if length > 0 {
|
||||
if length != 32 {
|
||||
return stamp, errors.New("Invalid stamp (certificate hash must be 32 bytes)")
|
||||
}
|
||||
stamp.Hashes = append(stamp.Hashes, bin[pos:pos+length])
|
||||
}
|
||||
pos += length
|
||||
@@ -455,6 +686,29 @@ func newODoHRelayStamp(bin []byte) (ServerStamp, error) {
|
||||
stamp.Path = string(bin[pos : pos+length])
|
||||
pos += length
|
||||
|
||||
// Parse optional bootstrap IP addresses (VLP format)
|
||||
if pos < binLen {
|
||||
for {
|
||||
if pos >= binLen {
|
||||
break
|
||||
}
|
||||
vlen := int(bin[pos])
|
||||
length = vlen & ^0x80
|
||||
if 1+length > binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
if length > 0 {
|
||||
bootstrapIP := string(bin[pos : pos+length])
|
||||
stamp.BootstrapIPs = append(stamp.BootstrapIPs, bootstrapIP)
|
||||
}
|
||||
pos += length
|
||||
if vlen&0x80 != 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if pos != binLen {
|
||||
return stamp, errors.New("Invalid stamp (garbage after end)")
|
||||
}
|
||||
@@ -485,7 +739,8 @@ func newODoHRelayStamp(bin []byte) (ServerStamp, error) {
|
||||
}
|
||||
|
||||
func validatePort(port string) error {
|
||||
if _, err := strconv.ParseUint(port, 10, 16); err != nil {
|
||||
p, err := strconv.ParseUint(port, 10, 16)
|
||||
if err != nil || p == 0 {
|
||||
return errors.New("Invalid port")
|
||||
}
|
||||
return nil
|
||||
@@ -498,6 +753,10 @@ func (stamp *ServerStamp) String() string {
|
||||
return stamp.dnsCryptString()
|
||||
} else if stamp.Proto == StampProtoTypeDoH {
|
||||
return stamp.dohString()
|
||||
} else if stamp.Proto == StampProtoTypeTLS {
|
||||
return stamp.dotString()
|
||||
} else if stamp.Proto == StampProtoTypeDoQ {
|
||||
return stamp.doqString()
|
||||
} else if stamp.Proto == StampProtoTypeODoHTarget {
|
||||
return stamp.oDohTargetString()
|
||||
} else if stamp.Proto == StampProtoTypeDNSCryptRelay {
|
||||
@@ -579,6 +838,113 @@ func (stamp *ServerStamp) dohString() string {
|
||||
bin = append(bin, uint8(len(stamp.Path)))
|
||||
bin = append(bin, []uint8(stamp.Path)...)
|
||||
|
||||
// Serialize optional bootstrap IP addresses (VLP format)
|
||||
if len(stamp.BootstrapIPs) > 0 {
|
||||
last := len(stamp.BootstrapIPs) - 1
|
||||
for i, bootstrapIP := range stamp.BootstrapIPs {
|
||||
vlen := len(bootstrapIP)
|
||||
if i < last {
|
||||
vlen |= 0x80
|
||||
}
|
||||
bin = append(bin, uint8(vlen))
|
||||
bin = append(bin, []uint8(bootstrapIP)...)
|
||||
}
|
||||
}
|
||||
|
||||
str := base64.RawURLEncoding.EncodeToString(bin)
|
||||
|
||||
return StampScheme + str
|
||||
}
|
||||
|
||||
func (stamp *ServerStamp) dotString() string {
|
||||
bin := make([]uint8, 9)
|
||||
bin[0] = uint8(StampProtoTypeTLS)
|
||||
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.Props))
|
||||
|
||||
serverAddrStr := stamp.ServerAddrStr
|
||||
if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultDoTPort)) {
|
||||
serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultDoTPort))]
|
||||
}
|
||||
bin = append(bin, uint8(len(serverAddrStr)))
|
||||
bin = append(bin, []uint8(serverAddrStr)...)
|
||||
|
||||
if len(stamp.Hashes) == 0 {
|
||||
bin = append(bin, uint8(0))
|
||||
} else {
|
||||
last := len(stamp.Hashes) - 1
|
||||
for i, hash := range stamp.Hashes {
|
||||
vlen := len(hash)
|
||||
if i < last {
|
||||
vlen |= 0x80
|
||||
}
|
||||
bin = append(bin, uint8(vlen))
|
||||
bin = append(bin, hash...)
|
||||
}
|
||||
}
|
||||
|
||||
bin = append(bin, uint8(len(stamp.ProviderName)))
|
||||
bin = append(bin, []uint8(stamp.ProviderName)...)
|
||||
|
||||
// Serialize optional bootstrap IP addresses (VLP format)
|
||||
if len(stamp.BootstrapIPs) > 0 {
|
||||
last := len(stamp.BootstrapIPs) - 1
|
||||
for i, bootstrapIP := range stamp.BootstrapIPs {
|
||||
vlen := len(bootstrapIP)
|
||||
if i < last {
|
||||
vlen |= 0x80
|
||||
}
|
||||
bin = append(bin, uint8(vlen))
|
||||
bin = append(bin, []uint8(bootstrapIP)...)
|
||||
}
|
||||
}
|
||||
|
||||
str := base64.RawURLEncoding.EncodeToString(bin)
|
||||
|
||||
return StampScheme + str
|
||||
}
|
||||
|
||||
func (stamp *ServerStamp) doqString() string {
|
||||
bin := make([]uint8, 9)
|
||||
bin[0] = uint8(StampProtoTypeDoQ)
|
||||
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.Props))
|
||||
|
||||
serverAddrStr := stamp.ServerAddrStr
|
||||
if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultDoTPort)) {
|
||||
serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultDoTPort))]
|
||||
}
|
||||
bin = append(bin, uint8(len(serverAddrStr)))
|
||||
bin = append(bin, []uint8(serverAddrStr)...)
|
||||
|
||||
if len(stamp.Hashes) == 0 {
|
||||
bin = append(bin, uint8(0))
|
||||
} else {
|
||||
last := len(stamp.Hashes) - 1
|
||||
for i, hash := range stamp.Hashes {
|
||||
vlen := len(hash)
|
||||
if i < last {
|
||||
vlen |= 0x80
|
||||
}
|
||||
bin = append(bin, uint8(vlen))
|
||||
bin = append(bin, hash...)
|
||||
}
|
||||
}
|
||||
|
||||
bin = append(bin, uint8(len(stamp.ProviderName)))
|
||||
bin = append(bin, []uint8(stamp.ProviderName)...)
|
||||
|
||||
// Serialize optional bootstrap IP addresses (VLP format)
|
||||
if len(stamp.BootstrapIPs) > 0 {
|
||||
last := len(stamp.BootstrapIPs) - 1
|
||||
for i, bootstrapIP := range stamp.BootstrapIPs {
|
||||
vlen := len(bootstrapIP)
|
||||
if i < last {
|
||||
vlen |= 0x80
|
||||
}
|
||||
bin = append(bin, uint8(vlen))
|
||||
bin = append(bin, []uint8(bootstrapIP)...)
|
||||
}
|
||||
}
|
||||
|
||||
str := base64.RawURLEncoding.EncodeToString(bin)
|
||||
|
||||
return StampScheme + str
|
||||
@@ -648,6 +1014,19 @@ func (stamp *ServerStamp) oDohRelayString() string {
|
||||
bin = append(bin, uint8(len(stamp.Path)))
|
||||
bin = append(bin, []uint8(stamp.Path)...)
|
||||
|
||||
// Serialize optional bootstrap IP addresses (VLP format)
|
||||
if len(stamp.BootstrapIPs) > 0 {
|
||||
last := len(stamp.BootstrapIPs) - 1
|
||||
for i, bootstrapIP := range stamp.BootstrapIPs {
|
||||
vlen := len(bootstrapIP)
|
||||
if i < last {
|
||||
vlen |= 0x80
|
||||
}
|
||||
bin = append(bin, uint8(vlen))
|
||||
bin = append(bin, []uint8(bootstrapIP)...)
|
||||
}
|
||||
}
|
||||
|
||||
str := base64.RawURLEncoding.EncodeToString(bin)
|
||||
|
||||
return StampScheme + str
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
[submodule "integrationtests/interop/qifs"]
|
||||
path = integrationtests/interop/qifs
|
||||
[submodule "interop/qifs"]
|
||||
path = interop/qifs
|
||||
url = https://github.com/qpackers/qifs.git
|
||||
|
||||
+9
-10
@@ -1,23 +1,22 @@
|
||||
run:
|
||||
linters-settings:
|
||||
version: "2"
|
||||
linters:
|
||||
disable-all: true
|
||||
default: none
|
||||
enable:
|
||||
- asciicheck
|
||||
- copyloopvar
|
||||
- exhaustive
|
||||
- goconst
|
||||
- gofmt # redundant, since gofmt *should* be a no-op after gofumpt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
|
||||
- usetesting
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@
|
||||
[](https://codecov.io/gh/quic-go/qpack)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:quic-go)
|
||||
|
||||
This is a minimal QPACK ([RFC 9204](https://datatracker.ietf.org/doc/html/rfc9204)) implementation in Go. It is minimal in the sense that it doesn't use the dynamic table at all, but just the static table and (Huffman encoded) string literals. Wherever possible, it reuses code from the [HPACK implementation in the Go standard library](https://github.com/golang/net/tree/master/http2/hpack).
|
||||
This is a minimal QPACK ([RFC 9204](https://datatracker.ietf.org/doc/html/rfc9204)) implementation in Go. It reuses the Huffman encoder / decoder code from the [HPACK implementation in the Go standard library](https://github.com/golang/net/tree/master/http2/hpack).
|
||||
|
||||
It is interoperable with other QPACK implementations (both encoders and decoders), however it won't achieve a high compression efficiency. If you're interested in dynamic table support, please comment on [the issue](https://github.com/quic-go/qpack/issues/33).
|
||||
It is fully interoperable with other QPACK implementations (both encoders and decoders). However, it does not support the dynamic table and relies solely on the static table and string literals (including Huffman encoding), which limits compression efficiency. If you're interested in dynamic table support, please comment on [issue #33](https://github.com/quic-go/qpack/issues/33).
|
||||
|
||||
## Running the Interop Tests
|
||||
|
||||
@@ -17,5 +17,5 @@ git submodule update --init --recursive
|
||||
|
||||
Then run the tests:
|
||||
```bash
|
||||
go test -v ./integrationtests/interop/
|
||||
go test -v ./interop
|
||||
```
|
||||
|
||||
+84
-176
@@ -1,248 +1,157 @@
|
||||
package qpack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"io"
|
||||
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
||||
// A decodingError is something the spec defines as a decoding error.
|
||||
type decodingError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (de decodingError) Error() string {
|
||||
return fmt.Sprintf("decoding error: %v", de.err)
|
||||
}
|
||||
|
||||
// An invalidIndexError is returned when an encoder references a table
|
||||
// entry before the static table or after the end of the dynamic table.
|
||||
// An invalidIndexError is returned when decoding encounters an invalid index
|
||||
// (e.g., an index that is out of bounds for the static table).
|
||||
type invalidIndexError int
|
||||
|
||||
func (e invalidIndexError) Error() string {
|
||||
return fmt.Sprintf("invalid indexed representation index %d", int(e))
|
||||
}
|
||||
|
||||
var errNoDynamicTable = decodingError{errors.New("no dynamic table")}
|
||||
var errNoDynamicTable = errors.New("no dynamic table")
|
||||
|
||||
// errNeedMore is an internal sentinel error value that means the
|
||||
// buffer is truncated and we need to read more data before we can
|
||||
// continue parsing.
|
||||
var errNeedMore = errors.New("need more data")
|
||||
// A Decoder decodes QPACK header blocks.
|
||||
// A Decoder can be reused to decode multiple header blocks on different streams
|
||||
// on the same connection (e.g., headers then trailers).
|
||||
// This will be useful when dynamic table support is added.
|
||||
type Decoder struct{}
|
||||
|
||||
// A Decoder is the decoding context for incremental processing of
|
||||
// header blocks.
|
||||
type Decoder struct {
|
||||
mutex sync.Mutex
|
||||
// DecodeFunc is a function that decodes the next header field from a header block.
|
||||
// It should be called repeatedly until it returns io.EOF.
|
||||
// It returns io.EOF when all header fields have been decoded.
|
||||
// Any error other than io.EOF indicates a decoding error.
|
||||
type DecodeFunc func() (HeaderField, error)
|
||||
|
||||
emitFunc func(f HeaderField)
|
||||
|
||||
readRequiredInsertCount bool
|
||||
readDeltaBase bool
|
||||
|
||||
// buf is the unparsed buffer. It's only written to
|
||||
// saveBuf if it was truncated in the middle of a header
|
||||
// block. Because it's usually not owned, we can only
|
||||
// process it under Write.
|
||||
buf []byte // not owned; only valid during Write
|
||||
|
||||
// saveBuf is previous data passed to Write which we weren't able
|
||||
// to fully parse before. Unlike buf, we own this data.
|
||||
saveBuf bytes.Buffer
|
||||
// NewDecoder returns a new Decoder.
|
||||
func NewDecoder() *Decoder {
|
||||
return &Decoder{}
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder
|
||||
// The emitFunc will be called for each valid field parsed,
|
||||
// in the same goroutine as calls to Write, before Write returns.
|
||||
func NewDecoder(emitFunc func(f HeaderField)) *Decoder {
|
||||
return &Decoder{emitFunc: emitFunc}
|
||||
}
|
||||
// Decode returns a function that decodes header fields from the given header block.
|
||||
// It does not copy the slice; the caller must ensure it remains valid during decoding.
|
||||
func (d *Decoder) Decode(p []byte) DecodeFunc {
|
||||
var readRequiredInsertCount bool
|
||||
var readDeltaBase bool
|
||||
|
||||
func (d *Decoder) Write(p []byte) (int, error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
d.mutex.Lock()
|
||||
n, err := d.writeLocked(p)
|
||||
d.mutex.Unlock()
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (d *Decoder) writeLocked(p []byte) (int, error) {
|
||||
// Only copy the data if we have to. Optimistically assume
|
||||
// that p will contain a complete header block.
|
||||
if d.saveBuf.Len() == 0 {
|
||||
d.buf = p
|
||||
} else {
|
||||
d.saveBuf.Write(p)
|
||||
d.buf = d.saveBuf.Bytes()
|
||||
d.saveBuf.Reset()
|
||||
}
|
||||
|
||||
if err := d.decode(); err != nil {
|
||||
if err != errNeedMore {
|
||||
return 0, err
|
||||
return func() (HeaderField, error) {
|
||||
if !readRequiredInsertCount {
|
||||
requiredInsertCount, rest, err := readVarInt(8, p)
|
||||
if err != nil {
|
||||
return HeaderField{}, err
|
||||
}
|
||||
p = rest
|
||||
readRequiredInsertCount = true
|
||||
if requiredInsertCount != 0 {
|
||||
return HeaderField{}, errors.New("expected Required Insert Count to be zero")
|
||||
}
|
||||
}
|
||||
// TODO: limit the size of the buffer
|
||||
d.saveBuf.Write(d.buf)
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// DecodeFull decodes an entire block.
|
||||
func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
|
||||
if len(p) == 0 {
|
||||
return []HeaderField{}, nil
|
||||
}
|
||||
|
||||
d.mutex.Lock()
|
||||
defer d.mutex.Unlock()
|
||||
|
||||
saveFunc := d.emitFunc
|
||||
defer func() { d.emitFunc = saveFunc }()
|
||||
|
||||
var hf []HeaderField
|
||||
d.emitFunc = func(f HeaderField) { hf = append(hf, f) }
|
||||
if _, err := d.writeLocked(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := d.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hf, nil
|
||||
}
|
||||
|
||||
// Close declares that the decoding is complete and resets the Decoder
|
||||
// to be reused again for a new header block. If there is any remaining
|
||||
// data in the decoder's buffer, Close returns an error.
|
||||
func (d *Decoder) Close() error {
|
||||
if d.saveBuf.Len() > 0 {
|
||||
d.saveBuf.Reset()
|
||||
return decodingError{errors.New("truncated headers")}
|
||||
}
|
||||
d.readRequiredInsertCount = false
|
||||
d.readDeltaBase = false
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decode() error {
|
||||
if !d.readRequiredInsertCount {
|
||||
requiredInsertCount, rest, err := readVarInt(8, d.buf)
|
||||
if err != nil {
|
||||
return err
|
||||
if !readDeltaBase {
|
||||
base, rest, err := readVarInt(7, p)
|
||||
if err != nil {
|
||||
return HeaderField{}, err
|
||||
}
|
||||
p = rest
|
||||
readDeltaBase = true
|
||||
if base != 0 {
|
||||
return HeaderField{}, errors.New("expected Base to be zero")
|
||||
}
|
||||
}
|
||||
d.readRequiredInsertCount = true
|
||||
if requiredInsertCount != 0 {
|
||||
return decodingError{errors.New("expected Required Insert Count to be zero")}
|
||||
}
|
||||
d.buf = rest
|
||||
}
|
||||
if !d.readDeltaBase {
|
||||
base, rest, err := readVarInt(7, d.buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.readDeltaBase = true
|
||||
if base != 0 {
|
||||
return decodingError{errors.New("expected Base to be zero")}
|
||||
}
|
||||
d.buf = rest
|
||||
}
|
||||
if len(d.buf) == 0 {
|
||||
return errNeedMore
|
||||
}
|
||||
|
||||
for len(d.buf) > 0 {
|
||||
b := d.buf[0]
|
||||
if len(p) == 0 {
|
||||
return HeaderField{}, io.EOF
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
var hf HeaderField
|
||||
var rest []byte
|
||||
var err error
|
||||
switch {
|
||||
case b&0x80 > 0: // 1xxxxxxx
|
||||
err = d.parseIndexedHeaderField()
|
||||
case b&0xc0 == 0x40: // 01xxxxxx
|
||||
err = d.parseLiteralHeaderField()
|
||||
case b&0xe0 == 0x20: // 001xxxxx
|
||||
err = d.parseLiteralHeaderFieldWithoutNameReference()
|
||||
case (b & 0x80) > 0: // 1xxxxxxx
|
||||
hf, rest, err = d.parseIndexedHeaderField(p)
|
||||
case (b & 0xc0) == 0x40: // 01xxxxxx
|
||||
hf, rest, err = d.parseLiteralHeaderField(p)
|
||||
case (b & 0xe0) == 0x20: // 001xxxxx
|
||||
hf, rest, err = d.parseLiteralHeaderFieldWithoutNameReference(p)
|
||||
default:
|
||||
err = fmt.Errorf("unexpected type byte: %#x", b)
|
||||
}
|
||||
p = rest
|
||||
if err != nil {
|
||||
return err
|
||||
return HeaderField{}, err
|
||||
}
|
||||
return hf, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) parseIndexedHeaderField() error {
|
||||
buf := d.buf
|
||||
func (d *Decoder) parseIndexedHeaderField(buf []byte) (_ HeaderField, rest []byte, _ error) {
|
||||
if buf[0]&0x40 == 0 {
|
||||
return errNoDynamicTable
|
||||
return HeaderField{}, buf, errNoDynamicTable
|
||||
}
|
||||
index, buf, err := readVarInt(6, buf)
|
||||
index, rest, err := readVarInt(6, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
return HeaderField{}, buf, err
|
||||
}
|
||||
hf, ok := d.at(index)
|
||||
if !ok {
|
||||
return decodingError{invalidIndexError(index)}
|
||||
return HeaderField{}, buf, invalidIndexError(index)
|
||||
}
|
||||
d.emitFunc(hf)
|
||||
d.buf = buf
|
||||
return nil
|
||||
return hf, rest, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) parseLiteralHeaderField() error {
|
||||
buf := d.buf
|
||||
func (d *Decoder) parseLiteralHeaderField(buf []byte) (_ HeaderField, rest []byte, _ error) {
|
||||
if buf[0]&0x10 == 0 {
|
||||
return errNoDynamicTable
|
||||
return HeaderField{}, buf, errNoDynamicTable
|
||||
}
|
||||
// We don't need to check the value of the N-bit here.
|
||||
// It's only relevant when re-encoding header fields,
|
||||
// and determines whether the header field can be added to the dynamic table.
|
||||
// Since we don't support the dynamic table, we can ignore it.
|
||||
index, buf, err := readVarInt(4, buf)
|
||||
index, rest, err := readVarInt(4, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
return HeaderField{}, buf, err
|
||||
}
|
||||
hf, ok := d.at(index)
|
||||
if !ok {
|
||||
return decodingError{invalidIndexError(index)}
|
||||
return HeaderField{}, buf, invalidIndexError(index)
|
||||
}
|
||||
buf = rest
|
||||
if len(buf) == 0 {
|
||||
return errNeedMore
|
||||
return HeaderField{}, buf, io.ErrUnexpectedEOF
|
||||
}
|
||||
usesHuffman := buf[0]&0x80 > 0
|
||||
val, buf, err := d.readString(buf, 7, usesHuffman)
|
||||
val, rest, err := d.readString(rest, 7, usesHuffman)
|
||||
if err != nil {
|
||||
return err
|
||||
return HeaderField{}, rest, err
|
||||
}
|
||||
hf.Value = val
|
||||
d.emitFunc(hf)
|
||||
d.buf = buf
|
||||
return nil
|
||||
return hf, rest, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) parseLiteralHeaderFieldWithoutNameReference() error {
|
||||
buf := d.buf
|
||||
func (d *Decoder) parseLiteralHeaderFieldWithoutNameReference(buf []byte) (_ HeaderField, rest []byte, _ error) {
|
||||
usesHuffmanForName := buf[0]&0x8 > 0
|
||||
name, buf, err := d.readString(buf, 3, usesHuffmanForName)
|
||||
name, rest, err := d.readString(buf, 3, usesHuffmanForName)
|
||||
if err != nil {
|
||||
return err
|
||||
return HeaderField{}, rest, err
|
||||
}
|
||||
buf = rest
|
||||
if len(buf) == 0 {
|
||||
return errNeedMore
|
||||
return HeaderField{}, rest, io.ErrUnexpectedEOF
|
||||
}
|
||||
usesHuffmanForVal := buf[0]&0x80 > 0
|
||||
val, buf, err := d.readString(buf, 7, usesHuffmanForVal)
|
||||
val, rest, err := d.readString(buf, 7, usesHuffmanForVal)
|
||||
if err != nil {
|
||||
return err
|
||||
return HeaderField{}, rest, err
|
||||
}
|
||||
d.emitFunc(HeaderField{Name: name, Value: val})
|
||||
d.buf = buf
|
||||
return nil
|
||||
return HeaderField{Name: name, Value: val}, rest, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) readString(buf []byte, n uint8, usesHuffman bool) (string, []byte, error) {
|
||||
@@ -251,11 +160,10 @@ func (d *Decoder) readString(buf []byte, n uint8, usesHuffman bool) (string, []b
|
||||
return "", nil, err
|
||||
}
|
||||
if uint64(len(buf)) < l {
|
||||
return "", nil, errNeedMore
|
||||
return "", nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
var val string
|
||||
if usesHuffman {
|
||||
var err error
|
||||
val, err = hpack.HuffmanDecodeToString(buf[:l])
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ var staticTableEntries = [...]HeaderField{
|
||||
// Only needed for tests.
|
||||
// use go:linkname to retrieve the static table.
|
||||
//
|
||||
//nolint:deadcode,unused
|
||||
//nolint:unused
|
||||
func getStaticTable() []HeaderField {
|
||||
return staticTableEntries[:]
|
||||
}
|
||||
|
||||
+7
-4
@@ -2,7 +2,10 @@ package qpack
|
||||
|
||||
// copied from the Go standard library HPACK implementation
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
var errVarintOverflow = errors.New("varint integer overflow")
|
||||
|
||||
@@ -31,13 +34,13 @@ func appendVarInt(dst []byte, n byte, i uint64) []byte {
|
||||
// n must always be between 1 and 8.
|
||||
//
|
||||
// The returned remain buffer is either a smaller suffix of p, or err != nil.
|
||||
// The error is errNeedMore if p doesn't contain a complete integer.
|
||||
// The error is io.ErrUnexpectedEOF if p doesn't contain a complete integer.
|
||||
func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
|
||||
if n < 1 || n > 8 {
|
||||
panic("bad n")
|
||||
}
|
||||
if len(p) == 0 {
|
||||
return 0, p, errNeedMore
|
||||
return 0, p, io.ErrUnexpectedEOF
|
||||
}
|
||||
i = uint64(p[0])
|
||||
if n < 8 {
|
||||
@@ -62,5 +65,5 @@ func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
|
||||
return 0, origP, errVarintOverflow
|
||||
}
|
||||
}
|
||||
return 0, origP, errNeedMore
|
||||
return 0, origP, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
+1
@@ -34,6 +34,7 @@ Detailed documentation can be found on [quic-go.net](https://quic-go.net/docs/).
|
||||
| [gost](https://github.com/go-gost/gost) | A simple security tunnel written in Go |  |
|
||||
| [Hysteria](https://github.com/apernet/hysteria) | A powerful, lightning fast and censorship resistant proxy |  |
|
||||
| [Mercure](https://github.com/dunglas/mercure) | An open, easy, fast, reliable and battery-efficient solution for real-time communications |  |
|
||||
| [nodepass](https://github.com/yosebyte/nodepass) | A secure, efficient TCP/UDP tunneling solution that delivers fast, reliable access across network restrictions using pre-established TCP/QUIC connections |  |
|
||||
| [OONI Probe](https://github.com/ooni/probe-cli) | Next generation OONI Probe. Library and CLI tool. |  |
|
||||
| [reverst](https://github.com/flipt-io/reverst) | Reverse Tunnels in Go over HTTP/3 and QUIC |  |
|
||||
| [RoadRunner](https://github.com/roadrunner-server/roadrunner) | High-performance PHP application server, process manager written in Go and powered with plugins |  |
|
||||
|
||||
-7
@@ -157,13 +157,6 @@ func (m *connIDGenerator) SetHandshakeComplete(connIDExpiry monotime.Time) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *connIDGenerator) NextRetireTime() monotime.Time {
|
||||
if len(m.connIDsToRetire) == 0 {
|
||||
return 0
|
||||
}
|
||||
return m.connIDsToRetire[0].t
|
||||
}
|
||||
|
||||
func (m *connIDGenerator) RemoveRetiredConnIDs(now monotime.Time) {
|
||||
if len(m.connIDsToRetire) == 0 {
|
||||
return
|
||||
|
||||
+7
-3
@@ -885,9 +885,6 @@ func (c *Conn) maybeResetTimer() {
|
||||
return
|
||||
}
|
||||
|
||||
if t := c.connIDGenerator.NextRetireTime(); !t.IsZero() && t.Before(deadline) {
|
||||
deadline = t
|
||||
}
|
||||
if !c.pacingDeadline.IsZero() && c.pacingDeadline.Before(deadline) {
|
||||
deadline = c.pacingDeadline
|
||||
}
|
||||
@@ -3082,6 +3079,13 @@ func (c *Conn) QlogTrace() qlogwriter.Trace {
|
||||
return c.qlogTrace
|
||||
}
|
||||
|
||||
// NextConnection transitions a connection to be usable after a 0-RTT rejection.
|
||||
// It waits for the handshake to complete and then enables the connection for normal use.
|
||||
// This should be called when the server rejects 0-RTT and the application receives
|
||||
// [Err0RTTRejected] errors.
|
||||
//
|
||||
// Note that 0-RTT rejection invalidates all data sent in 0-RTT packets. It is the
|
||||
// application's responsibility to handle this (for example by resending the data).
|
||||
func (c *Conn) NextConnection(ctx context.Context) (*Conn, error) {
|
||||
// The handshake might fail after the server rejected 0-RTT.
|
||||
// This could happen if the Finished message is malformed or never received.
|
||||
|
||||
+38
-27
@@ -59,7 +59,7 @@ type ClientConn struct {
|
||||
|
||||
// maxResponseHeaderBytes specifies a limit on how many response bytes are
|
||||
// allowed in the server's response header.
|
||||
maxResponseHeaderBytes uint64
|
||||
maxResponseHeaderBytes int
|
||||
|
||||
// disableCompression, if true, prevents the Transport from requesting compression with an
|
||||
// "Accept-Encoding: gzip" request header when the Request contains no existing Accept-Encoding value.
|
||||
@@ -82,7 +82,7 @@ func newClientConn(
|
||||
additionalSettings map[uint64]uint64,
|
||||
streamHijacker func(FrameType, quic.ConnectionTracingID, *quic.Stream, error) (hijacked bool, err error),
|
||||
uniStreamHijacker func(StreamType, quic.ConnectionTracingID, *quic.ReceiveStream, error) (hijacked bool),
|
||||
maxResponseHeaderBytes int64,
|
||||
maxResponseHeaderBytes int,
|
||||
disableCompression bool,
|
||||
logger *slog.Logger,
|
||||
) *ClientConn {
|
||||
@@ -95,9 +95,9 @@ func newClientConn(
|
||||
if maxResponseHeaderBytes <= 0 {
|
||||
c.maxResponseHeaderBytes = defaultMaxResponseHeaderBytes
|
||||
} else {
|
||||
c.maxResponseHeaderBytes = uint64(maxResponseHeaderBytes)
|
||||
c.maxResponseHeaderBytes = maxResponseHeaderBytes
|
||||
}
|
||||
c.decoder = qpack.NewDecoder(func(hf qpack.HeaderField) {})
|
||||
c.decoder = qpack.NewDecoder()
|
||||
c.requestWriter = newRequestWriter()
|
||||
c.conn = newConnection(
|
||||
conn.Context(),
|
||||
@@ -137,10 +137,15 @@ func (c *ClientConn) setupConn() error {
|
||||
b := make([]byte, 0, 64)
|
||||
b = quicvarint.Append(b, streamTypeControlStream)
|
||||
// send the SETTINGS frame
|
||||
b = (&settingsFrame{Datagram: c.enableDatagrams, Other: c.additionalSettings}).Append(b)
|
||||
b = (&settingsFrame{
|
||||
Datagram: c.enableDatagrams,
|
||||
Other: c.additionalSettings,
|
||||
MaxFieldSectionSize: int64(c.maxResponseHeaderBytes),
|
||||
}).Append(b)
|
||||
if c.conn.qlogger != nil {
|
||||
sf := qlog.SettingsFrame{
|
||||
Other: maps.Clone(c.additionalSettings),
|
||||
MaxFieldSectionSize: int64(c.maxResponseHeaderBytes),
|
||||
Other: maps.Clone(c.additionalSettings),
|
||||
}
|
||||
if c.enableDatagrams {
|
||||
sf.Datagram = pointer(true)
|
||||
@@ -332,31 +337,37 @@ func (c *ClientConn) sendRequestBody(str *RequestStream, body io.ReadCloser, con
|
||||
|
||||
func (c *ClientConn) doRequest(req *http.Request, str *RequestStream) (*http.Response, error) {
|
||||
trace := httptrace.ContextClientTrace(req.Context())
|
||||
var sendingReqFailed bool
|
||||
if err := str.sendRequestHeader(req); err != nil {
|
||||
traceWroteRequest(trace, err)
|
||||
return nil, err
|
||||
if c.logger != nil {
|
||||
c.logger.Debug("error writing request", "error", err)
|
||||
}
|
||||
sendingReqFailed = true
|
||||
}
|
||||
if req.Body == nil {
|
||||
traceWroteRequest(trace, nil)
|
||||
str.Close()
|
||||
} else {
|
||||
// send the request body asynchronously
|
||||
go func() {
|
||||
contentLength := int64(-1)
|
||||
// According to the documentation for http.Request.ContentLength,
|
||||
// a value of 0 with a non-nil Body is also treated as unknown content length.
|
||||
if req.ContentLength > 0 {
|
||||
contentLength = req.ContentLength
|
||||
}
|
||||
err := c.sendRequestBody(str, req.Body, contentLength)
|
||||
traceWroteRequest(trace, err)
|
||||
if err != nil {
|
||||
if c.logger != nil {
|
||||
c.logger.Debug("error writing request", "error", err)
|
||||
}
|
||||
}
|
||||
if !sendingReqFailed {
|
||||
if req.Body == nil {
|
||||
traceWroteRequest(trace, nil)
|
||||
str.Close()
|
||||
}()
|
||||
} else {
|
||||
// send the request body asynchronously
|
||||
go func() {
|
||||
contentLength := int64(-1)
|
||||
// According to the documentation for http.Request.ContentLength,
|
||||
// a value of 0 with a non-nil Body is also treated as unknown content length.
|
||||
if req.ContentLength > 0 {
|
||||
contentLength = req.ContentLength
|
||||
}
|
||||
err := c.sendRequestBody(str, req.Body, contentLength)
|
||||
traceWroteRequest(trace, err)
|
||||
if err != nil {
|
||||
if c.logger != nil {
|
||||
c.logger.Debug("error writing request", "error", err)
|
||||
}
|
||||
}
|
||||
str.Close()
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// copy from net/http: support 1xx responses
|
||||
|
||||
+12
-7
@@ -76,7 +76,7 @@ func newConnection(
|
||||
logger: logger,
|
||||
idleTimeout: idleTimeout,
|
||||
enableDatagrams: enableDatagrams,
|
||||
decoder: qpack.NewDecoder(func(hf qpack.HeaderField) {}),
|
||||
decoder: qpack.NewDecoder(),
|
||||
receivedSettings: make(chan struct{}),
|
||||
streams: make(map[quic.StreamID]*stateTrackingStream),
|
||||
maxStreamID: invalidStreamID,
|
||||
@@ -147,7 +147,7 @@ func (c *Conn) openRequestStream(
|
||||
requestWriter *requestWriter,
|
||||
reqDone chan<- struct{},
|
||||
disableCompression bool,
|
||||
maxHeaderBytes uint64,
|
||||
maxHeaderBytes int,
|
||||
) (*RequestStream, error) {
|
||||
c.streamMx.Lock()
|
||||
maxStreamID := c.maxStreamID
|
||||
@@ -193,17 +193,22 @@ func (c *Conn) openRequestStream(
|
||||
), nil
|
||||
}
|
||||
|
||||
func (c *Conn) decodeTrailers(r io.Reader, streamID quic.StreamID, hf *headersFrame, maxHeaderBytes uint64) (http.Header, error) {
|
||||
if hf.Length > maxHeaderBytes {
|
||||
func (c *Conn) decodeTrailers(r io.Reader, streamID quic.StreamID, hf *headersFrame, maxHeaderBytes int) (http.Header, error) {
|
||||
if hf.Length > uint64(maxHeaderBytes) {
|
||||
maybeQlogInvalidHeadersFrame(c.qlogger, streamID, hf.Length)
|
||||
return nil, fmt.Errorf("HEADERS frame too large: %d bytes (max: %d)", hf.Length, maxHeaderBytes)
|
||||
return nil, fmt.Errorf("http3: HEADERS frame too large: %d bytes (max: %d)", hf.Length, maxHeaderBytes)
|
||||
}
|
||||
|
||||
b := make([]byte, hf.Length)
|
||||
if _, err := io.ReadFull(r, b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fields, err := c.decoder.DecodeFull(b)
|
||||
decodeFn := c.decoder.Decode(b)
|
||||
var fields []qpack.HeaderField
|
||||
if c.qlogger != nil {
|
||||
fields = make([]qpack.HeaderField, 0, 16)
|
||||
}
|
||||
trailers, err := parseTrailers(decodeFn, &fields)
|
||||
if err != nil {
|
||||
maybeQlogInvalidHeadersFrame(c.qlogger, streamID, hf.Length)
|
||||
return nil, err
|
||||
@@ -211,7 +216,7 @@ func (c *Conn) decodeTrailers(r io.Reader, streamID quic.StreamID, hf *headersFr
|
||||
if c.qlogger != nil {
|
||||
qlogParsedHeadersFrame(c.qlogger, streamID, hf, fields)
|
||||
}
|
||||
return parseTrailers(fields)
|
||||
return trailers, nil
|
||||
}
|
||||
|
||||
// only used by the server
|
||||
|
||||
+21
-18
@@ -9,24 +9,25 @@ import (
|
||||
type ErrCode quic.ApplicationErrorCode
|
||||
|
||||
const (
|
||||
ErrCodeNoError ErrCode = 0x100
|
||||
ErrCodeGeneralProtocolError ErrCode = 0x101
|
||||
ErrCodeInternalError ErrCode = 0x102
|
||||
ErrCodeStreamCreationError ErrCode = 0x103
|
||||
ErrCodeClosedCriticalStream ErrCode = 0x104
|
||||
ErrCodeFrameUnexpected ErrCode = 0x105
|
||||
ErrCodeFrameError ErrCode = 0x106
|
||||
ErrCodeExcessiveLoad ErrCode = 0x107
|
||||
ErrCodeIDError ErrCode = 0x108
|
||||
ErrCodeSettingsError ErrCode = 0x109
|
||||
ErrCodeMissingSettings ErrCode = 0x10a
|
||||
ErrCodeRequestRejected ErrCode = 0x10b
|
||||
ErrCodeRequestCanceled ErrCode = 0x10c
|
||||
ErrCodeRequestIncomplete ErrCode = 0x10d
|
||||
ErrCodeMessageError ErrCode = 0x10e
|
||||
ErrCodeConnectError ErrCode = 0x10f
|
||||
ErrCodeVersionFallback ErrCode = 0x110
|
||||
ErrCodeDatagramError ErrCode = 0x33
|
||||
ErrCodeNoError ErrCode = 0x100
|
||||
ErrCodeGeneralProtocolError ErrCode = 0x101
|
||||
ErrCodeInternalError ErrCode = 0x102
|
||||
ErrCodeStreamCreationError ErrCode = 0x103
|
||||
ErrCodeClosedCriticalStream ErrCode = 0x104
|
||||
ErrCodeFrameUnexpected ErrCode = 0x105
|
||||
ErrCodeFrameError ErrCode = 0x106
|
||||
ErrCodeExcessiveLoad ErrCode = 0x107
|
||||
ErrCodeIDError ErrCode = 0x108
|
||||
ErrCodeSettingsError ErrCode = 0x109
|
||||
ErrCodeMissingSettings ErrCode = 0x10a
|
||||
ErrCodeRequestRejected ErrCode = 0x10b
|
||||
ErrCodeRequestCanceled ErrCode = 0x10c
|
||||
ErrCodeRequestIncomplete ErrCode = 0x10d
|
||||
ErrCodeMessageError ErrCode = 0x10e
|
||||
ErrCodeConnectError ErrCode = 0x10f
|
||||
ErrCodeVersionFallback ErrCode = 0x110
|
||||
ErrCodeDatagramError ErrCode = 0x33
|
||||
ErrCodeQPACKDecompressionFailed ErrCode = 0x200
|
||||
)
|
||||
|
||||
func (e ErrCode) String() string {
|
||||
@@ -75,6 +76,8 @@ func (e ErrCode) string() string {
|
||||
return "H3_VERSION_FALLBACK"
|
||||
case ErrCodeDatagramError:
|
||||
return "H3_DATAGRAM_ERROR"
|
||||
case ErrCodeQPACKDecompressionFailed:
|
||||
return "QPACK_DECOMPRESSION_FAILED"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
+23
-6
@@ -179,6 +179,8 @@ func (f *headersFrame) Append(b []byte) []byte {
|
||||
}
|
||||
|
||||
const (
|
||||
// SETTINGS_MAX_FIELD_SECTION_SIZE
|
||||
settingMaxFieldSectionSize = 0x6
|
||||
// Extended CONNECT, RFC 9220
|
||||
settingExtendedConnect = 0x8
|
||||
// HTTP Datagrams, RFC 9297
|
||||
@@ -186,10 +188,11 @@ const (
|
||||
)
|
||||
|
||||
type settingsFrame struct {
|
||||
Datagram bool // HTTP Datagrams, RFC 9297
|
||||
ExtendedConnect bool // Extended CONNECT, RFC 9220
|
||||
MaxFieldSectionSize int64 // SETTINGS_MAX_FIELD_SECTION_SIZE, -1 if not set
|
||||
|
||||
Other map[uint64]uint64 // all settings that we don't explicitly recognize
|
||||
Datagram bool // HTTP Datagrams, RFC 9297
|
||||
ExtendedConnect bool // Extended CONNECT, RFC 9220
|
||||
Other map[uint64]uint64 // all settings that we don't explicitly recognize
|
||||
}
|
||||
|
||||
func pointer[T any](v T) *T {
|
||||
@@ -207,10 +210,10 @@ func parseSettingsFrame(r *countingByteReader, l uint64, streamID quic.StreamID,
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
frame := &settingsFrame{}
|
||||
frame := &settingsFrame{MaxFieldSectionSize: -1}
|
||||
b := bytes.NewReader(buf)
|
||||
var settingsFrame qlog.SettingsFrame
|
||||
var readDatagram, readExtendedConnect bool
|
||||
settingsFrame := qlog.SettingsFrame{MaxFieldSectionSize: -1}
|
||||
var readMaxFieldSectionSize, readDatagram, readExtendedConnect bool
|
||||
for b.Len() > 0 {
|
||||
id, err := quicvarint.Read(b)
|
||||
if err != nil { // should not happen. We allocated the whole frame already.
|
||||
@@ -222,6 +225,13 @@ func parseSettingsFrame(r *countingByteReader, l uint64, streamID quic.StreamID,
|
||||
}
|
||||
|
||||
switch id {
|
||||
case settingMaxFieldSectionSize:
|
||||
if readMaxFieldSectionSize {
|
||||
return nil, fmt.Errorf("duplicate setting: %d", id)
|
||||
}
|
||||
readMaxFieldSectionSize = true
|
||||
frame.MaxFieldSectionSize = int64(val)
|
||||
settingsFrame.MaxFieldSectionSize = int64(val)
|
||||
case settingExtendedConnect:
|
||||
if readExtendedConnect {
|
||||
return nil, fmt.Errorf("duplicate setting: %d", id)
|
||||
@@ -274,6 +284,9 @@ func parseSettingsFrame(r *countingByteReader, l uint64, streamID quic.StreamID,
|
||||
func (f *settingsFrame) Append(b []byte) []byte {
|
||||
b = quicvarint.Append(b, 0x4)
|
||||
var l int
|
||||
if f.MaxFieldSectionSize >= 0 {
|
||||
l += quicvarint.Len(settingMaxFieldSectionSize) + quicvarint.Len(uint64(f.MaxFieldSectionSize))
|
||||
}
|
||||
for id, val := range f.Other {
|
||||
l += quicvarint.Len(id) + quicvarint.Len(val)
|
||||
}
|
||||
@@ -284,6 +297,10 @@ func (f *settingsFrame) Append(b []byte) []byte {
|
||||
l += quicvarint.Len(settingExtendedConnect) + quicvarint.Len(1)
|
||||
}
|
||||
b = quicvarint.Append(b, uint64(l))
|
||||
if f.MaxFieldSectionSize >= 0 {
|
||||
b = quicvarint.Append(b, settingMaxFieldSectionSize)
|
||||
b = quicvarint.Append(b, uint64(f.MaxFieldSectionSize))
|
||||
}
|
||||
if f.Datagram {
|
||||
b = quicvarint.Append(b, settingDatagram)
|
||||
b = quicvarint.Append(b, 1)
|
||||
|
||||
+48
-13
@@ -3,6 +3,7 @@ package http3
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
@@ -14,6 +15,13 @@ import (
|
||||
"github.com/quic-go/qpack"
|
||||
)
|
||||
|
||||
type qpackError struct{ err error }
|
||||
|
||||
func (e *qpackError) Error() string { return fmt.Sprintf("qpack: %v", e.err) }
|
||||
func (e *qpackError) Unwrap() error { return e.err }
|
||||
|
||||
var errHeaderTooLarge = errors.New("http3: headers too large")
|
||||
|
||||
type header struct {
|
||||
// Pseudo header fields defined in RFC 9114
|
||||
Path string
|
||||
@@ -38,11 +46,28 @@ var invalidHeaderFields = [...]string{
|
||||
"upgrade",
|
||||
}
|
||||
|
||||
func parseHeaders(headers []qpack.HeaderField, isRequest bool) (header, error) {
|
||||
hdr := header{Headers: make(http.Header, len(headers))}
|
||||
func parseHeaders(decodeFn qpack.DecodeFunc, isRequest bool, sizeLimit int, headerFields *[]qpack.HeaderField) (header, error) {
|
||||
hdr := header{Headers: make(http.Header)}
|
||||
var readFirstRegularHeader, readContentLength bool
|
||||
var contentLengthStr string
|
||||
for _, h := range headers {
|
||||
for {
|
||||
h, err := decodeFn()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return header{}, &qpackError{err}
|
||||
}
|
||||
if headerFields != nil {
|
||||
*headerFields = append(*headerFields, h)
|
||||
}
|
||||
// RFC 9114, section 4.2.2:
|
||||
// The size of a field list is calculated based on the uncompressed size of fields,
|
||||
// including the length of the name and value in bytes plus an overhead of 32 bytes for each field.
|
||||
sizeLimit -= len(h.Name) + len(h.Value) + 32
|
||||
if sizeLimit < 0 {
|
||||
return header{}, errHeaderTooLarge
|
||||
}
|
||||
// field names need to be lowercase, see section 4.2 of RFC 9114
|
||||
if strings.ToLower(h.Name) != h.Name {
|
||||
return header{}, fmt.Errorf("header field is not lower-case: %s", h.Name)
|
||||
@@ -130,19 +155,29 @@ func parseHeaders(headers []qpack.HeaderField, isRequest bool) (header, error) {
|
||||
return hdr, nil
|
||||
}
|
||||
|
||||
func parseTrailers(headers []qpack.HeaderField) (http.Header, error) {
|
||||
h := make(http.Header, len(headers))
|
||||
for _, field := range headers {
|
||||
if field.IsPseudo() {
|
||||
return nil, fmt.Errorf("http3: received pseudo header in trailer: %s", field.Name)
|
||||
func parseTrailers(decodeFn qpack.DecodeFunc, headerFields *[]qpack.HeaderField) (http.Header, error) {
|
||||
h := make(http.Header)
|
||||
for {
|
||||
hf, err := decodeFn()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, &qpackError{err}
|
||||
}
|
||||
h.Add(field.Name, field.Value)
|
||||
if headerFields != nil {
|
||||
*headerFields = append(*headerFields, hf)
|
||||
}
|
||||
if hf.IsPseudo() {
|
||||
return nil, fmt.Errorf("http3: received pseudo header in trailer: %s", hf.Name)
|
||||
}
|
||||
h.Add(hf.Name, hf.Value)
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func requestFromHeaders(headerFields []qpack.HeaderField) (*http.Request, error) {
|
||||
hdr, err := parseHeaders(headerFields, true)
|
||||
func requestFromHeaders(decodeFn qpack.DecodeFunc, sizeLimit int, headerFields *[]qpack.HeaderField) (*http.Request, error) {
|
||||
hdr, err := parseHeaders(decodeFn, true, sizeLimit, headerFields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -215,8 +250,8 @@ func requestFromHeaders(headerFields []qpack.HeaderField) (*http.Request, error)
|
||||
// using the decoded qpack header filed.
|
||||
// It is only called for the HTTP header (and not the HTTP trailer).
|
||||
// It takes an http.Response as an argument to allow the caller to set the trailer later on.
|
||||
func updateResponseFromHeaders(rsp *http.Response, headerFields []qpack.HeaderField) error {
|
||||
hdr, err := parseHeaders(headerFields, false)
|
||||
func updateResponseFromHeaders(rsp *http.Response, decodeFn qpack.DecodeFunc, sizeLimit int, headerFields *[]qpack.HeaderField) error {
|
||||
hdr, err := parseHeaders(decodeFn, false, sizeLimit, headerFields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+12
-3
@@ -97,9 +97,10 @@ func (f *GoAwayFrame) encode(enc *jsontext.Encoder) error {
|
||||
}
|
||||
|
||||
type SettingsFrame struct {
|
||||
Datagram *bool
|
||||
ExtendedConnect *bool
|
||||
Other map[uint64]uint64
|
||||
MaxFieldSectionSize int64
|
||||
Datagram *bool
|
||||
ExtendedConnect *bool
|
||||
Other map[uint64]uint64
|
||||
}
|
||||
|
||||
func (f *SettingsFrame) encode(enc *jsontext.Encoder) error {
|
||||
@@ -109,6 +110,14 @@ func (f *SettingsFrame) encode(enc *jsontext.Encoder) error {
|
||||
h.WriteToken(jsontext.String("settings"))
|
||||
h.WriteToken(jsontext.String("settings"))
|
||||
h.WriteToken(jsontext.BeginArray)
|
||||
if f.MaxFieldSectionSize >= 0 {
|
||||
h.WriteToken(jsontext.BeginObject)
|
||||
h.WriteToken(jsontext.String("name"))
|
||||
h.WriteToken(jsontext.String("settings_max_field_section_size"))
|
||||
h.WriteToken(jsontext.String("value"))
|
||||
h.WriteToken(jsontext.Uint(uint64(f.MaxFieldSectionSize)))
|
||||
h.WriteToken(jsontext.EndObject)
|
||||
}
|
||||
if f.Datagram != nil {
|
||||
h.WriteToken(jsontext.BeginObject)
|
||||
h.WriteToken(jsontext.String("name"))
|
||||
|
||||
+43
-19
@@ -454,14 +454,16 @@ func (s *Server) handleConn(conn *quic.Conn) error {
|
||||
b := make([]byte, 0, 64)
|
||||
b = quicvarint.Append(b, streamTypeControlStream) // stream type
|
||||
b = (&settingsFrame{
|
||||
Datagram: s.EnableDatagrams,
|
||||
ExtendedConnect: true,
|
||||
Other: s.AdditionalSettings,
|
||||
MaxFieldSectionSize: int64(s.maxHeaderBytes()),
|
||||
Datagram: s.EnableDatagrams,
|
||||
ExtendedConnect: true,
|
||||
Other: s.AdditionalSettings,
|
||||
}).Append(b)
|
||||
if qlogger != nil {
|
||||
sf := qlog.SettingsFrame{
|
||||
ExtendedConnect: pointer(true),
|
||||
Other: maps.Clone(s.AdditionalSettings),
|
||||
MaxFieldSectionSize: int64(s.maxHeaderBytes()),
|
||||
ExtendedConnect: pointer(true),
|
||||
Other: maps.Clone(s.AdditionalSettings),
|
||||
}
|
||||
if s.EnableDatagrams {
|
||||
sf.Datagram = pointer(true)
|
||||
@@ -570,16 +572,16 @@ func (s *Server) handleConn(conn *quic.Conn) error {
|
||||
return handleErr
|
||||
}
|
||||
|
||||
func (s *Server) maxHeaderBytes() uint64 {
|
||||
func (s *Server) maxHeaderBytes() int {
|
||||
if s.MaxHeaderBytes <= 0 {
|
||||
return http.DefaultMaxHeaderBytes
|
||||
}
|
||||
return uint64(s.MaxHeaderBytes)
|
||||
return s.MaxHeaderBytes
|
||||
}
|
||||
|
||||
func (s *Server) handleRequest(
|
||||
conn *Conn,
|
||||
str datagramStream,
|
||||
str *stateTrackingStream,
|
||||
decoder *qpack.Decoder,
|
||||
qlogger qlogwriter.Recorder,
|
||||
) {
|
||||
@@ -608,10 +610,12 @@ func (s *Server) handleRequest(
|
||||
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameUnexpected), "expected first frame to be a HEADERS frame")
|
||||
return
|
||||
}
|
||||
if hf.Length > s.maxHeaderBytes() {
|
||||
if hf.Length > uint64(s.maxHeaderBytes()) {
|
||||
maybeQlogInvalidHeadersFrame(qlogger, str.StreamID(), hf.Length)
|
||||
str.CancelRead(quic.StreamErrorCode(ErrCodeFrameError))
|
||||
str.CancelWrite(quic.StreamErrorCode(ErrCodeFrameError))
|
||||
// stop the client from sending more data
|
||||
str.CancelRead(quic.StreamErrorCode(ErrCodeExcessiveLoad))
|
||||
// send a 431 Response (Request Header Fields Too Large)
|
||||
s.rejectWithHeaderFieldsTooLarge(str, conn, qlogger)
|
||||
return
|
||||
}
|
||||
headerBlock := make([]byte, hf.Length)
|
||||
@@ -621,19 +625,31 @@ func (s *Server) handleRequest(
|
||||
str.CancelWrite(quic.StreamErrorCode(ErrCodeRequestIncomplete))
|
||||
return
|
||||
}
|
||||
hfs, err := decoder.DecodeFull(headerBlock)
|
||||
if err != nil {
|
||||
// TODO: use the right error code
|
||||
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeGeneralProtocolError), "expected first frame to be a HEADERS frame")
|
||||
return
|
||||
decodeFn := decoder.Decode(headerBlock)
|
||||
var hfs []qpack.HeaderField
|
||||
if qlogger != nil {
|
||||
hfs = make([]qpack.HeaderField, 0, 16)
|
||||
}
|
||||
req, err := requestFromHeaders(decodeFn, s.maxHeaderBytes(), &hfs)
|
||||
if qlogger != nil {
|
||||
qlogParsedHeadersFrame(qlogger, str.StreamID(), hf, hfs)
|
||||
}
|
||||
req, err := requestFromHeaders(hfs)
|
||||
if err != nil {
|
||||
str.CancelRead(quic.StreamErrorCode(ErrCodeMessageError))
|
||||
str.CancelWrite(quic.StreamErrorCode(ErrCodeMessageError))
|
||||
if errors.Is(err, errHeaderTooLarge) {
|
||||
// stop the client from sending more data
|
||||
str.CancelRead(quic.StreamErrorCode(ErrCodeExcessiveLoad))
|
||||
// send a 431 Response (Request Header Fields Too Large)
|
||||
s.rejectWithHeaderFieldsTooLarge(str, conn, qlogger)
|
||||
return
|
||||
}
|
||||
|
||||
errCode := ErrCodeMessageError
|
||||
var qpackErr *qpackError
|
||||
if errors.As(err, &qpackErr) {
|
||||
errCode = ErrCodeQPACKDecompressionFailed
|
||||
}
|
||||
str.CancelRead(quic.StreamErrorCode(errCode))
|
||||
str.CancelWrite(quic.StreamErrorCode(errCode))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -713,6 +729,14 @@ func (s *Server) handleRequest(
|
||||
str.Close()
|
||||
}
|
||||
|
||||
func (s *Server) rejectWithHeaderFieldsTooLarge(str *stateTrackingStream, conn *Conn, qlogger qlogwriter.Recorder) {
|
||||
hstr := newStream(str, conn, nil, nil, qlogger)
|
||||
defer hstr.Close()
|
||||
r := newResponseWriter(hstr, conn, false, s.Logger)
|
||||
r.WriteHeader(http.StatusRequestHeaderFieldsTooLarge)
|
||||
r.Flush()
|
||||
}
|
||||
|
||||
// Close the server immediately, aborting requests and sending CONNECTION_CLOSE frames to connected clients.
|
||||
// Close in combination with ListenAndServe() (instead of Serve()) may race if it is called before a UDP socket is established.
|
||||
// It is the caller's responsibility to close any connection passed to ServeQUICConn.
|
||||
|
||||
+17
-13
@@ -170,7 +170,7 @@ type RequestStream struct {
|
||||
|
||||
decoder *qpack.Decoder
|
||||
requestWriter *requestWriter
|
||||
maxHeaderBytes uint64
|
||||
maxHeaderBytes int
|
||||
reqDone chan<- struct{}
|
||||
disableCompression bool
|
||||
response *http.Response
|
||||
@@ -186,7 +186,7 @@ func newRequestStream(
|
||||
reqDone chan<- struct{},
|
||||
decoder *qpack.Decoder,
|
||||
disableCompression bool,
|
||||
maxHeaderBytes uint64,
|
||||
maxHeaderBytes int,
|
||||
rsp *http.Response,
|
||||
) *RequestStream {
|
||||
return &RequestStream{
|
||||
@@ -329,7 +329,7 @@ func (s *RequestStream) ReadResponse() (*http.Response, error) {
|
||||
s.str.conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameUnexpected), "expected first frame to be a HEADERS frame")
|
||||
return nil, errors.New("http3: expected first frame to be a HEADERS frame")
|
||||
}
|
||||
if hf.Length > s.maxHeaderBytes {
|
||||
if hf.Length > uint64(s.maxHeaderBytes) {
|
||||
maybeQlogInvalidHeadersFrame(s.str.qlogger, s.str.StreamID(), hf.Length)
|
||||
s.str.CancelRead(quic.StreamErrorCode(ErrCodeFrameError))
|
||||
s.str.CancelWrite(quic.StreamErrorCode(ErrCodeFrameError))
|
||||
@@ -342,20 +342,24 @@ func (s *RequestStream) ReadResponse() (*http.Response, error) {
|
||||
s.str.CancelWrite(quic.StreamErrorCode(ErrCodeRequestIncomplete))
|
||||
return nil, fmt.Errorf("http3: failed to read response headers: %w", err)
|
||||
}
|
||||
hfs, err := s.decoder.DecodeFull(headerBlock)
|
||||
if err != nil {
|
||||
maybeQlogInvalidHeadersFrame(s.str.qlogger, s.str.StreamID(), hf.Length)
|
||||
// TODO: use the right error code
|
||||
s.str.conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeGeneralProtocolError), "")
|
||||
return nil, fmt.Errorf("http3: failed to decode response headers: %w", err)
|
||||
decodeFn := s.decoder.Decode(headerBlock)
|
||||
var hfs []qpack.HeaderField
|
||||
if s.str.qlogger != nil {
|
||||
hfs = make([]qpack.HeaderField, 0, 16)
|
||||
}
|
||||
res := s.response
|
||||
err = updateResponseFromHeaders(res, decodeFn, s.maxHeaderBytes, &hfs)
|
||||
if s.str.qlogger != nil {
|
||||
qlogParsedHeadersFrame(s.str.qlogger, s.str.StreamID(), hf, hfs)
|
||||
}
|
||||
res := s.response
|
||||
if err := updateResponseFromHeaders(res, hfs); err != nil {
|
||||
s.str.CancelRead(quic.StreamErrorCode(ErrCodeMessageError))
|
||||
s.str.CancelWrite(quic.StreamErrorCode(ErrCodeMessageError))
|
||||
if err != nil {
|
||||
errCode := ErrCodeMessageError
|
||||
var qpackErr *qpackError
|
||||
if errors.As(err, &qpackErr) {
|
||||
errCode = ErrCodeQPACKDecompressionFailed
|
||||
}
|
||||
s.str.CancelRead(quic.StreamErrorCode(errCode))
|
||||
s.str.CancelWrite(quic.StreamErrorCode(errCode))
|
||||
return nil, fmt.Errorf("http3: invalid response: %w", err)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ type Transport struct {
|
||||
// MaxResponseHeaderBytes specifies a limit on how many response bytes are
|
||||
// allowed in the server's response header.
|
||||
// Zero means to use a default limit.
|
||||
MaxResponseHeaderBytes int64
|
||||
MaxResponseHeaderBytes int
|
||||
|
||||
// DisableCompression, if true, prevents the Transport from requesting compression with an
|
||||
// "Accept-Encoding: gzip" request header when the Request contains no existing Accept-Encoding value.
|
||||
|
||||
+3
-6
@@ -155,6 +155,9 @@ func (h *appDataReceivedPacketTracker) isMissing(p protocol.PacketNumber) bool {
|
||||
}
|
||||
|
||||
func (h *appDataReceivedPacketTracker) hasNewMissingPackets() bool {
|
||||
if h.lastAck == nil {
|
||||
return false
|
||||
}
|
||||
if h.largestObserved < reorderingThreshold {
|
||||
return false
|
||||
}
|
||||
@@ -170,12 +173,6 @@ func (h *appDataReceivedPacketTracker) hasNewMissingPackets() bool {
|
||||
}
|
||||
|
||||
func (h *appDataReceivedPacketTracker) shouldQueueACK(pn protocol.PacketNumber, ecn protocol.ECN, wasMissing bool) bool {
|
||||
// always acknowledge the first packet
|
||||
if h.lastAck == nil {
|
||||
h.logger.Debugf("\tQueueing ACK because the first packet should be acknowledged.")
|
||||
return true
|
||||
}
|
||||
|
||||
// Send an ACK if this packet was reported missing in an ACK sent before.
|
||||
// Ack decimation with reordering relies on the timer to send an ACK, but if
|
||||
// missing packets we reported in the previous ACK, send an ACK immediately.
|
||||
|
||||
+18
-8
@@ -387,19 +387,29 @@ func (h *cryptoSetup) GetSessionTicket() ([]byte, error) {
|
||||
// We can't check h.tlsConfig here, since the actual config might have been obtained from
|
||||
// the GetConfigForClient callback.
|
||||
// See https://github.com/golang/go/issues/62032.
|
||||
// Once that issue is resolved, this error assertion can be removed.
|
||||
// This error assertion can be removed once we drop support for Go 1.25.
|
||||
if strings.Contains(err.Error(), "session ticket keys unavailable") {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
ev := h.conn.NextEvent()
|
||||
if ev.Kind != tls.QUICWriteData || ev.Level != tls.QUICEncryptionLevelApplication {
|
||||
panic("crypto/tls bug: where's my session ticket?")
|
||||
}
|
||||
ticket := ev.Data
|
||||
if ev := h.conn.NextEvent(); ev.Kind != tls.QUICNoEvent {
|
||||
panic("crypto/tls bug: why more than one ticket?")
|
||||
// If session tickets are disabled, NextEvent will immediately return QUICNoEvent,
|
||||
// and we will return a nil ticket.
|
||||
var ticket []byte
|
||||
for {
|
||||
ev := h.conn.NextEvent()
|
||||
if ev.Kind == tls.QUICNoEvent {
|
||||
break
|
||||
}
|
||||
if ev.Kind == tls.QUICWriteData && ev.Level == tls.QUICEncryptionLevelApplication {
|
||||
if ticket != nil {
|
||||
h.logger.Errorf("unexpected multiple session tickets")
|
||||
continue
|
||||
}
|
||||
ticket = ev.Data
|
||||
} else {
|
||||
h.logger.Errorf("unexpected event: %v", ev.Kind)
|
||||
}
|
||||
}
|
||||
return ticket, nil
|
||||
}
|
||||
|
||||
+1
@@ -115,6 +115,7 @@ func newFileSeq(w io.WriteCloser, pers string, odcid *ConnectionID, eventSchemas
|
||||
runStopped: make(chan struct{}),
|
||||
encodeErr: encodeErr,
|
||||
events: make(chan event, eventChanSize),
|
||||
eventSchemas: eventSchemas,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ loop:
|
||||
MOVD $NUM_ROUNDS, R21
|
||||
VLD1 (R11), [V30.S4, V31.S4]
|
||||
|
||||
// load contants
|
||||
// load constants
|
||||
// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4]
|
||||
WORD $0x4D60E940
|
||||
|
||||
|
||||
+8
-2
@@ -56,7 +56,10 @@ func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []
|
||||
|
||||
ret, out := sliceForAppend(dst, len(plaintext)+16)
|
||||
if alias.InexactOverlap(out, plaintext) {
|
||||
panic("chacha20poly1305: invalid buffer overlap")
|
||||
panic("chacha20poly1305: invalid buffer overlap of output and input")
|
||||
}
|
||||
if alias.AnyOverlap(out, additionalData) {
|
||||
panic("chacha20poly1305: invalid buffer overlap of output and additional data")
|
||||
}
|
||||
chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
|
||||
return ret
|
||||
@@ -73,7 +76,10 @@ func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) (
|
||||
ciphertext = ciphertext[:len(ciphertext)-16]
|
||||
ret, out := sliceForAppend(dst, len(ciphertext))
|
||||
if alias.InexactOverlap(out, ciphertext) {
|
||||
panic("chacha20poly1305: invalid buffer overlap")
|
||||
panic("chacha20poly1305: invalid buffer overlap of output and input")
|
||||
}
|
||||
if alias.AnyOverlap(out, additionalData) {
|
||||
panic("chacha20poly1305: invalid buffer overlap of output and additional data")
|
||||
}
|
||||
if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
|
||||
for i := range out {
|
||||
|
||||
+8
-2
@@ -31,7 +31,10 @@ func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []b
|
||||
ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
|
||||
ciphertext, tag := out[:len(plaintext)], out[len(plaintext):]
|
||||
if alias.InexactOverlap(out, plaintext) {
|
||||
panic("chacha20poly1305: invalid buffer overlap")
|
||||
panic("chacha20poly1305: invalid buffer overlap of output and input")
|
||||
}
|
||||
if alias.AnyOverlap(out, additionalData) {
|
||||
panic("chacha20poly1305: invalid buffer overlap of output and additional data")
|
||||
}
|
||||
|
||||
var polyKey [32]byte
|
||||
@@ -67,7 +70,10 @@ func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []
|
||||
|
||||
ret, out := sliceForAppend(dst, len(ciphertext))
|
||||
if alias.InexactOverlap(out, ciphertext) {
|
||||
panic("chacha20poly1305: invalid buffer overlap")
|
||||
panic("chacha20poly1305: invalid buffer overlap of output and input")
|
||||
}
|
||||
if alias.AnyOverlap(out, additionalData) {
|
||||
panic("chacha20poly1305: invalid buffer overlap of output and additional data")
|
||||
}
|
||||
if !p.Verify(tag) {
|
||||
for i := range out {
|
||||
|
||||
+2
-2
@@ -45,8 +45,8 @@ func IsValid(v string) bool {
|
||||
|
||||
// Canonical returns the canonical formatting of the semantic version v.
|
||||
// It fills in any missing .MINOR or .PATCH and discards build metadata.
|
||||
// Two semantic versions compare equal only if their canonical formattings
|
||||
// are identical strings.
|
||||
// Two semantic versions compare equal only if their canonical formatting
|
||||
// is an identical string.
|
||||
// The canonical invalid semantic version is the empty string.
|
||||
func Canonical(v string) string {
|
||||
p, ok := parse(v)
|
||||
|
||||
+52
-24
@@ -280,6 +280,8 @@ type Framer struct {
|
||||
// lastHeaderStream is non-zero if the last frame was an
|
||||
// unfinished HEADERS/CONTINUATION.
|
||||
lastHeaderStream uint32
|
||||
// lastFrameType holds the type of the last frame for verifying frame order.
|
||||
lastFrameType FrameType
|
||||
|
||||
maxReadSize uint32
|
||||
headerBuf [frameHeaderLen]byte
|
||||
@@ -488,30 +490,41 @@ func terminalReadFrameError(err error) bool {
|
||||
return err != nil
|
||||
}
|
||||
|
||||
// ReadFrame reads a single frame. The returned Frame is only valid
|
||||
// until the next call to ReadFrame.
|
||||
// ReadFrameHeader reads the header of the next frame.
|
||||
// It reads the 9-byte fixed frame header, and does not read any portion of the
|
||||
// frame payload. The caller is responsible for consuming the payload, either
|
||||
// with ReadFrameForHeader or directly from the Framer's io.Reader.
|
||||
//
|
||||
// If the frame is larger than previously set with SetMaxReadFrameSize, the
|
||||
// returned error is ErrFrameTooLarge. Other errors may be of type
|
||||
// ConnectionError, StreamError, or anything else from the underlying
|
||||
// reader.
|
||||
// If the frame is larger than previously set with SetMaxReadFrameSize, it
|
||||
// returns the frame header and ErrFrameTooLarge.
|
||||
//
|
||||
// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
|
||||
// indicates the stream responsible for the error.
|
||||
func (fr *Framer) ReadFrame() (Frame, error) {
|
||||
// If the returned FrameHeader.StreamID is non-zero, it indicates the stream
|
||||
// responsible for the error.
|
||||
func (fr *Framer) ReadFrameHeader() (FrameHeader, error) {
|
||||
fr.errDetail = nil
|
||||
if fr.lastFrame != nil {
|
||||
fr.lastFrame.invalidate()
|
||||
}
|
||||
fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return fh, err
|
||||
}
|
||||
if fh.Length > fr.maxReadSize {
|
||||
if fh == invalidHTTP1LookingFrameHeader() {
|
||||
return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge)
|
||||
return fh, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge)
|
||||
}
|
||||
return nil, ErrFrameTooLarge
|
||||
return fh, ErrFrameTooLarge
|
||||
}
|
||||
if err := fr.checkFrameOrder(fh); err != nil {
|
||||
return fh, err
|
||||
}
|
||||
return fh, nil
|
||||
}
|
||||
|
||||
// ReadFrameForHeader reads the payload for the frame with the given FrameHeader.
|
||||
//
|
||||
// It behaves identically to ReadFrame, other than not checking the maximum
|
||||
// frame size.
|
||||
func (fr *Framer) ReadFrameForHeader(fh FrameHeader) (Frame, error) {
|
||||
if fr.lastFrame != nil {
|
||||
fr.lastFrame.invalidate()
|
||||
}
|
||||
payload := fr.getReadBuf(fh.Length)
|
||||
if _, err := io.ReadFull(fr.r, payload); err != nil {
|
||||
@@ -527,9 +540,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if err := fr.checkFrameOrder(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fr.lastFrame = f
|
||||
if fr.logReads {
|
||||
fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f))
|
||||
}
|
||||
@@ -539,6 +550,24 @@ func (fr *Framer) ReadFrame() (Frame, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// ReadFrame reads a single frame. The returned Frame is only valid
|
||||
// until the next call to ReadFrame or ReadFrameBodyForHeader.
|
||||
//
|
||||
// If the frame is larger than previously set with SetMaxReadFrameSize, the
|
||||
// returned error is ErrFrameTooLarge. Other errors may be of type
|
||||
// ConnectionError, StreamError, or anything else from the underlying
|
||||
// reader.
|
||||
//
|
||||
// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
|
||||
// indicates the stream responsible for the error.
|
||||
func (fr *Framer) ReadFrame() (Frame, error) {
|
||||
fh, err := fr.ReadFrameHeader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fr.ReadFrameForHeader(fh)
|
||||
}
|
||||
|
||||
// connError returns ConnectionError(code) but first
|
||||
// stashes away a public reason to the caller can optionally relay it
|
||||
// to the peer before hanging up on them. This might help others debug
|
||||
@@ -551,20 +580,19 @@ func (fr *Framer) connError(code ErrCode, reason string) error {
|
||||
// checkFrameOrder reports an error if f is an invalid frame to return
|
||||
// next from ReadFrame. Mostly it checks whether HEADERS and
|
||||
// CONTINUATION frames are contiguous.
|
||||
func (fr *Framer) checkFrameOrder(f Frame) error {
|
||||
last := fr.lastFrame
|
||||
fr.lastFrame = f
|
||||
func (fr *Framer) checkFrameOrder(fh FrameHeader) error {
|
||||
lastType := fr.lastFrameType
|
||||
fr.lastFrameType = fh.Type
|
||||
if fr.AllowIllegalReads {
|
||||
return nil
|
||||
}
|
||||
|
||||
fh := f.Header()
|
||||
if fr.lastHeaderStream != 0 {
|
||||
if fh.Type != FrameContinuation {
|
||||
return fr.connError(ErrCodeProtocol,
|
||||
fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
|
||||
fh.Type, fh.StreamID,
|
||||
last.Header().Type, fr.lastHeaderStream))
|
||||
lastType, fr.lastHeaderStream))
|
||||
}
|
||||
if fh.StreamID != fr.lastHeaderStream {
|
||||
return fr.connError(ErrCodeProtocol,
|
||||
@@ -1161,7 +1189,7 @@ var defaultRFC9218Priority = PriorityParam{
|
||||
// PriorityParam struct below is a superset of both schemes. The exported
|
||||
// symbols are from RFC 7540 and the non-exported ones are from RFC 9218.
|
||||
|
||||
// PriorityParam are the stream prioritzation parameters.
|
||||
// PriorityParam are the stream prioritization parameters.
|
||||
type PriorityParam struct {
|
||||
// StreamDep is a 31-bit stream identifier for the
|
||||
// stream that this stream depends on. Zero means no
|
||||
|
||||
+86
-18
@@ -9,6 +9,7 @@ package http2
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
@@ -3076,35 +3077,102 @@ type erringRoundTripper struct{ err error }
|
||||
func (rt erringRoundTripper) RoundTripErr() error { return rt.err }
|
||||
func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err }
|
||||
|
||||
var errConcurrentReadOnResBody = errors.New("http2: concurrent read on response body")
|
||||
|
||||
// gzipReader wraps a response body so it can lazily
|
||||
// call gzip.NewReader on the first call to Read
|
||||
// get gzip.Reader from the pool on the first call to Read.
|
||||
// After Close is called it puts gzip.Reader to the pool immediately
|
||||
// if there is no Read in progress or later when Read completes.
|
||||
type gzipReader struct {
|
||||
_ incomparable
|
||||
body io.ReadCloser // underlying Response.Body
|
||||
zr *gzip.Reader // lazily-initialized gzip reader
|
||||
zerr error // sticky error
|
||||
mu sync.Mutex // guards zr and zerr
|
||||
zr *gzip.Reader // stores gzip reader from the pool between reads
|
||||
zerr error // sticky gzip reader init error or sentinel value to detect concurrent read and read after close
|
||||
}
|
||||
|
||||
type eofReader struct{}
|
||||
|
||||
func (eofReader) Read([]byte) (int, error) { return 0, io.EOF }
|
||||
func (eofReader) ReadByte() (byte, error) { return 0, io.EOF }
|
||||
|
||||
var gzipPool = sync.Pool{New: func() any { return new(gzip.Reader) }}
|
||||
|
||||
// gzipPoolGet gets a gzip.Reader from the pool and resets it to read from r.
|
||||
func gzipPoolGet(r io.Reader) (*gzip.Reader, error) {
|
||||
zr := gzipPool.Get().(*gzip.Reader)
|
||||
if err := zr.Reset(r); err != nil {
|
||||
gzipPoolPut(zr)
|
||||
return nil, err
|
||||
}
|
||||
return zr, nil
|
||||
}
|
||||
|
||||
// gzipPoolPut puts a gzip.Reader back into the pool.
|
||||
func gzipPoolPut(zr *gzip.Reader) {
|
||||
// Reset will allocate bufio.Reader if we pass it anything
|
||||
// other than a flate.Reader, so ensure that it's getting one.
|
||||
var r flate.Reader = eofReader{}
|
||||
zr.Reset(r)
|
||||
gzipPool.Put(zr)
|
||||
}
|
||||
|
||||
// acquire returns a gzip.Reader for reading response body.
|
||||
// The reader must be released after use.
|
||||
func (gz *gzipReader) acquire() (*gzip.Reader, error) {
|
||||
gz.mu.Lock()
|
||||
defer gz.mu.Unlock()
|
||||
if gz.zerr != nil {
|
||||
return nil, gz.zerr
|
||||
}
|
||||
if gz.zr == nil {
|
||||
gz.zr, gz.zerr = gzipPoolGet(gz.body)
|
||||
if gz.zerr != nil {
|
||||
return nil, gz.zerr
|
||||
}
|
||||
}
|
||||
ret := gz.zr
|
||||
gz.zr, gz.zerr = nil, errConcurrentReadOnResBody
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// release returns the gzip.Reader to the pool if Close was called during Read.
|
||||
func (gz *gzipReader) release(zr *gzip.Reader) {
|
||||
gz.mu.Lock()
|
||||
defer gz.mu.Unlock()
|
||||
if gz.zerr == errConcurrentReadOnResBody {
|
||||
gz.zr, gz.zerr = zr, nil
|
||||
} else { // fs.ErrClosed
|
||||
gzipPoolPut(zr)
|
||||
}
|
||||
}
|
||||
|
||||
// close returns the gzip.Reader to the pool immediately or
|
||||
// signals release to do so after Read completes.
|
||||
func (gz *gzipReader) close() {
|
||||
gz.mu.Lock()
|
||||
defer gz.mu.Unlock()
|
||||
if gz.zerr == nil && gz.zr != nil {
|
||||
gzipPoolPut(gz.zr)
|
||||
gz.zr = nil
|
||||
}
|
||||
gz.zerr = fs.ErrClosed
|
||||
}
|
||||
|
||||
func (gz *gzipReader) Read(p []byte) (n int, err error) {
|
||||
if gz.zerr != nil {
|
||||
return 0, gz.zerr
|
||||
zr, err := gz.acquire()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if gz.zr == nil {
|
||||
gz.zr, err = gzip.NewReader(gz.body)
|
||||
if err != nil {
|
||||
gz.zerr = err
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return gz.zr.Read(p)
|
||||
defer gz.release(zr)
|
||||
|
||||
return zr.Read(p)
|
||||
}
|
||||
|
||||
func (gz *gzipReader) Close() error {
|
||||
if err := gz.body.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
gz.zerr = fs.ErrClosed
|
||||
return nil
|
||||
gz.close()
|
||||
|
||||
return gz.body.Close()
|
||||
}
|
||||
|
||||
type errorReader struct{ err error }
|
||||
|
||||
+50
-15
@@ -185,45 +185,75 @@ func (wr *FrameWriteRequest) replyToWriter(err error) {
|
||||
}
|
||||
|
||||
// writeQueue is used by implementations of WriteScheduler.
|
||||
//
|
||||
// Each writeQueue contains a queue of FrameWriteRequests, meant to store all
|
||||
// FrameWriteRequests associated with a given stream. This is implemented as a
|
||||
// two-stage queue: currQueue[currPos:] and nextQueue. Removing an item is done
|
||||
// by incrementing currPos of currQueue. Adding an item is done by appending it
|
||||
// to the nextQueue. If currQueue is empty when trying to remove an item, we
|
||||
// can swap currQueue and nextQueue to remedy the situation.
|
||||
// This two-stage queue is analogous to the use of two lists in Okasaki's
|
||||
// purely functional queue but without the overhead of reversing the list when
|
||||
// swapping stages.
|
||||
//
|
||||
// writeQueue also contains prev and next, this can be used by implementations
|
||||
// of WriteScheduler to construct data structures that represent the order of
|
||||
// writing between different streams (e.g. circular linked list).
|
||||
type writeQueue struct {
|
||||
s []FrameWriteRequest
|
||||
currQueue []FrameWriteRequest
|
||||
nextQueue []FrameWriteRequest
|
||||
currPos int
|
||||
|
||||
prev, next *writeQueue
|
||||
}
|
||||
|
||||
func (q *writeQueue) empty() bool { return len(q.s) == 0 }
|
||||
func (q *writeQueue) empty() bool {
|
||||
return (len(q.currQueue) - q.currPos + len(q.nextQueue)) == 0
|
||||
}
|
||||
|
||||
func (q *writeQueue) push(wr FrameWriteRequest) {
|
||||
q.s = append(q.s, wr)
|
||||
q.nextQueue = append(q.nextQueue, wr)
|
||||
}
|
||||
|
||||
func (q *writeQueue) shift() FrameWriteRequest {
|
||||
if len(q.s) == 0 {
|
||||
if q.empty() {
|
||||
panic("invalid use of queue")
|
||||
}
|
||||
wr := q.s[0]
|
||||
// TODO: less copy-happy queue.
|
||||
copy(q.s, q.s[1:])
|
||||
q.s[len(q.s)-1] = FrameWriteRequest{}
|
||||
q.s = q.s[:len(q.s)-1]
|
||||
if q.currPos >= len(q.currQueue) {
|
||||
q.currQueue, q.currPos, q.nextQueue = q.nextQueue, 0, q.currQueue[:0]
|
||||
}
|
||||
wr := q.currQueue[q.currPos]
|
||||
q.currQueue[q.currPos] = FrameWriteRequest{}
|
||||
q.currPos++
|
||||
return wr
|
||||
}
|
||||
|
||||
func (q *writeQueue) peek() *FrameWriteRequest {
|
||||
if q.currPos < len(q.currQueue) {
|
||||
return &q.currQueue[q.currPos]
|
||||
}
|
||||
if len(q.nextQueue) > 0 {
|
||||
return &q.nextQueue[0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// consume consumes up to n bytes from q.s[0]. If the frame is
|
||||
// entirely consumed, it is removed from the queue. If the frame
|
||||
// is partially consumed, the frame is kept with the consumed
|
||||
// bytes removed. Returns true iff any bytes were consumed.
|
||||
func (q *writeQueue) consume(n int32) (FrameWriteRequest, bool) {
|
||||
if len(q.s) == 0 {
|
||||
if q.empty() {
|
||||
return FrameWriteRequest{}, false
|
||||
}
|
||||
consumed, rest, numresult := q.s[0].Consume(n)
|
||||
consumed, rest, numresult := q.peek().Consume(n)
|
||||
switch numresult {
|
||||
case 0:
|
||||
return FrameWriteRequest{}, false
|
||||
case 1:
|
||||
q.shift()
|
||||
case 2:
|
||||
q.s[0] = rest
|
||||
*q.peek() = rest
|
||||
}
|
||||
return consumed, true
|
||||
}
|
||||
@@ -232,10 +262,15 @@ type writeQueuePool []*writeQueue
|
||||
|
||||
// put inserts an unused writeQueue into the pool.
|
||||
func (p *writeQueuePool) put(q *writeQueue) {
|
||||
for i := range q.s {
|
||||
q.s[i] = FrameWriteRequest{}
|
||||
for i := range q.currQueue {
|
||||
q.currQueue[i] = FrameWriteRequest{}
|
||||
}
|
||||
q.s = q.s[:0]
|
||||
for i := range q.nextQueue {
|
||||
q.nextQueue[i] = FrameWriteRequest{}
|
||||
}
|
||||
q.currQueue = q.currQueue[:0]
|
||||
q.nextQueue = q.nextQueue[:0]
|
||||
q.currPos = 0
|
||||
*p = append(*p, q)
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -214,8 +214,8 @@ func (z sortPriorityNodeSiblingsRFC7540) Swap(i, k int) { z[i], z[k] = z[k], z[i
|
||||
func (z sortPriorityNodeSiblingsRFC7540) Less(i, k int) bool {
|
||||
// Prefer the subtree that has sent fewer bytes relative to its weight.
|
||||
// See sections 5.3.2 and 5.3.4.
|
||||
wi, bi := float64(z[i].weight+1), float64(z[i].subtreeBytes)
|
||||
wk, bk := float64(z[k].weight+1), float64(z[k].subtreeBytes)
|
||||
wi, bi := float64(z[i].weight)+1, float64(z[i].subtreeBytes)
|
||||
wk, bk := float64(z[k].weight)+1, float64(z[k].subtreeBytes)
|
||||
if bi == 0 && bk == 0 {
|
||||
return wi >= wk
|
||||
}
|
||||
@@ -302,7 +302,6 @@ func (ws *priorityWriteSchedulerRFC7540) CloseStream(streamID uint32) {
|
||||
|
||||
q := n.q
|
||||
ws.queuePool.put(&q)
|
||||
n.q.s = nil
|
||||
if ws.maxClosedNodesInTree > 0 {
|
||||
ws.addClosedOrIdleNode(&ws.closedNodes, ws.maxClosedNodesInTree, n)
|
||||
} else {
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -39,7 +39,7 @@ type priorityWriteSchedulerRFC9218 struct {
|
||||
prioritizeIncremental bool
|
||||
}
|
||||
|
||||
func newPriorityWriteSchedulerRFC9128() WriteScheduler {
|
||||
func newPriorityWriteSchedulerRFC9218() WriteScheduler {
|
||||
ws := &priorityWriteSchedulerRFC9218{
|
||||
streams: make(map[uint32]streamMetadata),
|
||||
}
|
||||
+16
-1
@@ -467,7 +467,9 @@ func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) {
|
||||
// This algorithm could be implemented using c.Inspect,
|
||||
// but it is about 2.5x slower.
|
||||
|
||||
best := int32(-1) // push index of latest (=innermost) node containing range
|
||||
// best is the push-index of the latest (=innermost) node containing range.
|
||||
// (Beware: latest is not always innermost because FuncDecl.{Name,Type} overlap.)
|
||||
best := int32(-1)
|
||||
for i, limit := c.indices(); i < limit; i++ {
|
||||
ev := events[i]
|
||||
if ev.index > i { // push?
|
||||
@@ -481,6 +483,19 @@ func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// Edge case: FuncDecl.Name and .Type overlap:
|
||||
// Don't update best from Name to FuncDecl.Type.
|
||||
//
|
||||
// The condition can be read as:
|
||||
// - n is FuncType
|
||||
// - n.parent is FuncDecl
|
||||
// - best is strictly beneath the FuncDecl
|
||||
if ev.typ == 1<<nFuncType &&
|
||||
events[ev.parent].typ == 1<<nFuncDecl &&
|
||||
best > ev.parent {
|
||||
continue
|
||||
}
|
||||
|
||||
nodeEnd = n.End()
|
||||
if n.Pos() > start {
|
||||
break // disjoint, after; stop
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ func PrintErrors(pkgs []*Package) int {
|
||||
return n
|
||||
}
|
||||
|
||||
// Postorder returns an iterator over the the packages in
|
||||
// Postorder returns an iterator over the packages in
|
||||
// the import graph whose roots are pkg.
|
||||
// Packages are enumerated in dependencies-first order.
|
||||
func Postorder(pkgs []*Package) iter.Seq[*Package] {
|
||||
|
||||
+2
-2
@@ -249,7 +249,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
|
||||
|
||||
case *types.Func:
|
||||
// A func, if not package-level, must be a method.
|
||||
if recv := obj.Type().(*types.Signature).Recv(); recv == nil {
|
||||
if recv := obj.Signature().Recv(); recv == nil {
|
||||
return "", fmt.Errorf("func is not a method: %v", obj)
|
||||
}
|
||||
|
||||
@@ -405,7 +405,7 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
_, named := typesinternal.ReceiverNamed(meth.Type().(*types.Signature).Recv())
|
||||
_, named := typesinternal.ReceiverNamed(meth.Signature().Recv())
|
||||
if named == nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
+1
-2
@@ -304,8 +304,7 @@ func (h hasher) hash(t types.Type) uint32 {
|
||||
case *types.Named:
|
||||
hash := h.hashTypeName(t.Obj())
|
||||
targs := t.TypeArgs()
|
||||
for i := 0; i < targs.Len(); i++ {
|
||||
targ := targs.At(i)
|
||||
for targ := range targs.Types() {
|
||||
hash += 2 * h.hash(targ)
|
||||
}
|
||||
return hash
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ type fileInfo struct {
|
||||
const maxlines = 64 * 1024
|
||||
|
||||
func (s *fakeFileSet) pos(file string, line, column int) token.Pos {
|
||||
// TODO(mdempsky): Make use of column.
|
||||
_ = column // TODO(mdempsky): Make use of column.
|
||||
|
||||
// Since we don't know the set of needed file positions, we reserve maxlines
|
||||
// positions per file. We delay calling token.File.SetLines until all
|
||||
|
||||
+22
-14
@@ -829,8 +829,7 @@ func (p *iexporter) doDecl(obj types.Object) {
|
||||
// their name must be qualified before exporting recv.
|
||||
if rparams := sig.RecvTypeParams(); rparams.Len() > 0 {
|
||||
prefix := obj.Name() + "." + m.Name()
|
||||
for i := 0; i < rparams.Len(); i++ {
|
||||
rparam := rparams.At(i)
|
||||
for rparam := range rparams.TypeParams() {
|
||||
name := tparamExportName(prefix, rparam)
|
||||
w.p.tparamNames[rparam.Obj()] = name
|
||||
}
|
||||
@@ -944,6 +943,13 @@ func (w *exportWriter) posV0(pos token.Pos) {
|
||||
}
|
||||
|
||||
func (w *exportWriter) pkg(pkg *types.Package) {
|
||||
if pkg == nil {
|
||||
// [exportWriter.typ] accepts a nil pkg only for types
|
||||
// of constants, which cannot contain named objects
|
||||
// such as fields or methods and thus should never
|
||||
// reach this method (#76222).
|
||||
panic("nil package")
|
||||
}
|
||||
// Ensure any referenced packages are declared in the main index.
|
||||
w.p.allPkgs[pkg] = true
|
||||
|
||||
@@ -959,9 +965,11 @@ func (w *exportWriter) qualifiedType(obj *types.TypeName) {
|
||||
w.pkg(obj.Pkg())
|
||||
}
|
||||
|
||||
// TODO(rfindley): what does 'pkg' even mean here? It would be better to pass
|
||||
// it in explicitly into signatures and structs that may use it for
|
||||
// constructing fields.
|
||||
// typ emits the specified type.
|
||||
//
|
||||
// Objects within the type (struct fields and interface methods) are
|
||||
// qualified by pkg. It may be nil if the type cannot contain objects,
|
||||
// such as the type of a constant.
|
||||
func (w *exportWriter) typ(t types.Type, pkg *types.Package) {
|
||||
w.data.uint64(w.p.typOff(t, pkg))
|
||||
}
|
||||
@@ -991,6 +999,7 @@ func (w *exportWriter) startType(k itag) {
|
||||
w.data.uint64(uint64(k))
|
||||
}
|
||||
|
||||
// doTyp is the implementation of [exportWriter.typ].
|
||||
func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
||||
if trace {
|
||||
w.p.trace("exporting type %s (%T)", t, t)
|
||||
@@ -1064,7 +1073,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
||||
|
||||
case *types.Signature:
|
||||
w.startType(signatureType)
|
||||
w.pkg(pkg)
|
||||
w.pkg(pkg) // qualifies param/result vars
|
||||
w.signature(t)
|
||||
|
||||
case *types.Struct:
|
||||
@@ -1110,19 +1119,19 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
||||
|
||||
case *types.Interface:
|
||||
w.startType(interfaceType)
|
||||
w.pkg(pkg)
|
||||
w.pkg(pkg) // qualifies unexported method funcs
|
||||
|
||||
n := t.NumEmbeddeds()
|
||||
w.uint64(uint64(n))
|
||||
for i := 0; i < n; i++ {
|
||||
ft := t.EmbeddedType(i)
|
||||
tPkg := pkg
|
||||
if named, _ := types.Unalias(ft).(*types.Named); named != nil {
|
||||
w.pos(named.Obj().Pos())
|
||||
} else {
|
||||
// e.g. ~int
|
||||
w.pos(token.NoPos)
|
||||
}
|
||||
w.typ(ft, tPkg)
|
||||
w.typ(ft, pkg)
|
||||
}
|
||||
|
||||
// See comment for struct fields. In shallow mode we change the encoding
|
||||
@@ -1223,20 +1232,19 @@ func (w *exportWriter) signature(sig *types.Signature) {
|
||||
|
||||
func (w *exportWriter) typeList(ts *types.TypeList, pkg *types.Package) {
|
||||
w.uint64(uint64(ts.Len()))
|
||||
for i := 0; i < ts.Len(); i++ {
|
||||
w.typ(ts.At(i), pkg)
|
||||
for t := range ts.Types() {
|
||||
w.typ(t, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *exportWriter) tparamList(prefix string, list *types.TypeParamList, pkg *types.Package) {
|
||||
ll := uint64(list.Len())
|
||||
w.uint64(ll)
|
||||
for i := 0; i < list.Len(); i++ {
|
||||
tparam := list.At(i)
|
||||
for tparam := range list.TypeParams() {
|
||||
// Set the type parameter exportName before exporting its type.
|
||||
exportName := tparamExportName(prefix, tparam)
|
||||
w.p.tparamNames[tparam.Obj()] = exportName
|
||||
w.typ(list.At(i), pkg)
|
||||
w.typ(tparam, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+30
-30
@@ -432,10 +432,10 @@ func (p *iimporter) doDecl(pkg *types.Package, name string) {
|
||||
errorf("%v.%v not in index", pkg, name)
|
||||
}
|
||||
|
||||
r := &importReader{p: p, currPkg: pkg}
|
||||
r := &importReader{p: p}
|
||||
r.declReader.Reset(p.declData[off:])
|
||||
|
||||
r.obj(name)
|
||||
r.obj(pkg, name)
|
||||
}
|
||||
|
||||
func (p *iimporter) stringAt(off uint64) string {
|
||||
@@ -551,7 +551,6 @@ func canReuse(def *types.Named, rhs types.Type) bool {
|
||||
type importReader struct {
|
||||
p *iimporter
|
||||
declReader bytes.Reader
|
||||
currPkg *types.Package
|
||||
prevFile string
|
||||
prevLine int64
|
||||
prevColumn int64
|
||||
@@ -565,7 +564,8 @@ type importReader struct {
|
||||
// for 1.24, but the fix was not worth back-porting).
|
||||
var markBlack = func(name *types.TypeName) {}
|
||||
|
||||
func (r *importReader) obj(name string) {
|
||||
// obj decodes and declares the package-level object denoted by (pkg, name).
|
||||
func (r *importReader) obj(pkg *types.Package, name string) {
|
||||
tag := r.byte()
|
||||
pos := r.pos()
|
||||
|
||||
@@ -576,27 +576,27 @@ func (r *importReader) obj(name string) {
|
||||
tparams = r.tparamList()
|
||||
}
|
||||
typ := r.typ()
|
||||
obj := aliases.NewAlias(r.p.aliases, pos, r.currPkg, name, typ, tparams)
|
||||
obj := aliases.NewAlias(r.p.aliases, pos, pkg, name, typ, tparams)
|
||||
markBlack(obj) // workaround for golang/go#69912
|
||||
r.declare(obj)
|
||||
|
||||
case constTag:
|
||||
typ, val := r.value()
|
||||
|
||||
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
|
||||
r.declare(types.NewConst(pos, pkg, name, typ, val))
|
||||
|
||||
case funcTag, genericFuncTag:
|
||||
var tparams []*types.TypeParam
|
||||
if tag == genericFuncTag {
|
||||
tparams = r.tparamList()
|
||||
}
|
||||
sig := r.signature(nil, nil, tparams)
|
||||
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
|
||||
sig := r.signature(pkg, nil, nil, tparams)
|
||||
r.declare(types.NewFunc(pos, pkg, name, sig))
|
||||
|
||||
case typeTag, genericTypeTag:
|
||||
// Types can be recursive. We need to setup a stub
|
||||
// declaration before recursing.
|
||||
obj := types.NewTypeName(pos, r.currPkg, name, nil)
|
||||
obj := types.NewTypeName(pos, pkg, name, nil)
|
||||
named := types.NewNamed(obj, nil, nil)
|
||||
|
||||
markBlack(obj) // workaround for golang/go#69912
|
||||
@@ -616,7 +616,7 @@ func (r *importReader) obj(name string) {
|
||||
for n := r.uint64(); n > 0; n-- {
|
||||
mpos := r.pos()
|
||||
mname := r.ident()
|
||||
recv := r.param()
|
||||
recv := r.param(pkg)
|
||||
|
||||
// If the receiver has any targs, set those as the
|
||||
// rparams of the method (since those are the
|
||||
@@ -630,9 +630,9 @@ func (r *importReader) obj(name string) {
|
||||
rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam)
|
||||
}
|
||||
}
|
||||
msig := r.signature(recv, rparams, nil)
|
||||
msig := r.signature(pkg, recv, rparams, nil)
|
||||
|
||||
named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
|
||||
named.AddMethod(types.NewFunc(mpos, pkg, mname, msig))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,12 +644,12 @@ func (r *importReader) obj(name string) {
|
||||
errorf("unexpected type param type")
|
||||
}
|
||||
name0 := tparamName(name)
|
||||
tn := types.NewTypeName(pos, r.currPkg, name0, nil)
|
||||
tn := types.NewTypeName(pos, pkg, name0, nil)
|
||||
t := types.NewTypeParam(tn, nil)
|
||||
|
||||
// To handle recursive references to the typeparam within its
|
||||
// bound, save the partial type in tparamIndex before reading the bounds.
|
||||
id := ident{r.currPkg, name}
|
||||
id := ident{pkg, name}
|
||||
r.p.tparamIndex[id] = t
|
||||
var implicit bool
|
||||
if r.p.version >= iexportVersionGo1_18 {
|
||||
@@ -672,7 +672,7 @@ func (r *importReader) obj(name string) {
|
||||
case varTag:
|
||||
typ := r.typ()
|
||||
|
||||
v := types.NewVar(pos, r.currPkg, name, typ)
|
||||
v := types.NewVar(pos, pkg, name, typ)
|
||||
typesinternal.SetVarKind(v, typesinternal.PackageVar)
|
||||
r.declare(v)
|
||||
|
||||
@@ -905,11 +905,11 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
||||
case mapType:
|
||||
return types.NewMap(r.typ(), r.typ())
|
||||
case signatureType:
|
||||
r.currPkg = r.pkg()
|
||||
return r.signature(nil, nil, nil)
|
||||
paramPkg := r.pkg()
|
||||
return r.signature(paramPkg, nil, nil, nil)
|
||||
|
||||
case structType:
|
||||
r.currPkg = r.pkg()
|
||||
fieldPkg := r.pkg()
|
||||
|
||||
fields := make([]*types.Var, r.uint64())
|
||||
tags := make([]string, len(fields))
|
||||
@@ -932,7 +932,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
||||
// discussed in iexport.go, this is not correct, but mostly works and is
|
||||
// preferable to failing (for now at least).
|
||||
if field == nil {
|
||||
field = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
|
||||
field = types.NewField(fpos, fieldPkg, fname, ftyp, emb)
|
||||
}
|
||||
|
||||
fields[i] = field
|
||||
@@ -941,7 +941,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
||||
return types.NewStruct(fields, tags)
|
||||
|
||||
case interfaceType:
|
||||
r.currPkg = r.pkg()
|
||||
methodPkg := r.pkg() // qualifies methods and their param/result vars
|
||||
|
||||
embeddeds := make([]types.Type, r.uint64())
|
||||
for i := range embeddeds {
|
||||
@@ -963,12 +963,12 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
||||
// don't agree with this.
|
||||
var recv *types.Var
|
||||
if base != nil {
|
||||
recv = types.NewVar(token.NoPos, r.currPkg, "", base)
|
||||
recv = types.NewVar(token.NoPos, methodPkg, "", base)
|
||||
}
|
||||
msig := r.signature(recv, nil, nil)
|
||||
msig := r.signature(methodPkg, recv, nil, nil)
|
||||
|
||||
if method == nil {
|
||||
method = types.NewFunc(mpos, r.currPkg, mname, msig)
|
||||
method = types.NewFunc(mpos, methodPkg, mname, msig)
|
||||
}
|
||||
methods[i] = method
|
||||
}
|
||||
@@ -1049,9 +1049,9 @@ func (r *importReader) objectPathObject() types.Object {
|
||||
return obj
|
||||
}
|
||||
|
||||
func (r *importReader) signature(recv *types.Var, rparams []*types.TypeParam, tparams []*types.TypeParam) *types.Signature {
|
||||
params := r.paramList()
|
||||
results := r.paramList()
|
||||
func (r *importReader) signature(paramPkg *types.Package, recv *types.Var, rparams []*types.TypeParam, tparams []*types.TypeParam) *types.Signature {
|
||||
params := r.paramList(paramPkg)
|
||||
results := r.paramList(paramPkg)
|
||||
variadic := params.Len() > 0 && r.bool()
|
||||
return types.NewSignatureType(recv, rparams, tparams, params, results, variadic)
|
||||
}
|
||||
@@ -1070,19 +1070,19 @@ func (r *importReader) tparamList() []*types.TypeParam {
|
||||
return xs
|
||||
}
|
||||
|
||||
func (r *importReader) paramList() *types.Tuple {
|
||||
func (r *importReader) paramList(pkg *types.Package) *types.Tuple {
|
||||
xs := make([]*types.Var, r.uint64())
|
||||
for i := range xs {
|
||||
xs[i] = r.param()
|
||||
xs[i] = r.param(pkg)
|
||||
}
|
||||
return types.NewTuple(xs...)
|
||||
}
|
||||
|
||||
func (r *importReader) param() *types.Var {
|
||||
func (r *importReader) param(pkg *types.Package) *types.Var {
|
||||
pos := r.pos()
|
||||
name := r.ident()
|
||||
typ := r.typ()
|
||||
return types.NewParam(pos, r.currPkg, name, typ)
|
||||
return types.NewParam(pos, pkg, name, typ)
|
||||
}
|
||||
|
||||
func (r *importReader) bool() bool {
|
||||
|
||||
+462
-308
@@ -12,354 +12,508 @@ type pkginfo struct {
|
||||
}
|
||||
|
||||
var deps = [...]pkginfo{
|
||||
{"archive/tar", "\x03k\x03E;\x01\n\x01$\x01\x01\x02\x05\b\x02\x01\x02\x02\f"},
|
||||
{"archive/zip", "\x02\x04a\a\x03\x12\x021;\x01+\x05\x01\x0f\x03\x02\x0e\x04"},
|
||||
{"bufio", "\x03k\x83\x01D\x14"},
|
||||
{"bytes", "n*Y\x03\fG\x02\x02"},
|
||||
{"archive/tar", "\x03n\x03E<\x01\n\x01$\x01\x01\x02\x05\b\x02\x01\x02\x02\f"},
|
||||
{"archive/zip", "\x02\x04d\a\x03\x12\x021<\x01+\x05\x01\x0f\x03\x02\x0e\x04"},
|
||||
{"bufio", "\x03n\x84\x01D\x14"},
|
||||
{"bytes", "q*Z\x03\fG\x02\x02"},
|
||||
{"cmp", ""},
|
||||
{"compress/bzip2", "\x02\x02\xed\x01A"},
|
||||
{"compress/flate", "\x02l\x03\x80\x01\f\x033\x01\x03"},
|
||||
{"compress/gzip", "\x02\x04a\a\x03\x14lT"},
|
||||
{"compress/lzw", "\x02l\x03\x80\x01"},
|
||||
{"compress/zlib", "\x02\x04a\a\x03\x12\x01m"},
|
||||
{"container/heap", "\xb3\x02"},
|
||||
{"compress/bzip2", "\x02\x02\xf1\x01A"},
|
||||
{"compress/flate", "\x02o\x03\x81\x01\f\x033\x01\x03"},
|
||||
{"compress/gzip", "\x02\x04d\a\x03\x14mT"},
|
||||
{"compress/lzw", "\x02o\x03\x81\x01"},
|
||||
{"compress/zlib", "\x02\x04d\a\x03\x12\x01n"},
|
||||
{"container/heap", "\xb7\x02"},
|
||||
{"container/list", ""},
|
||||
{"container/ring", ""},
|
||||
{"context", "n\\m\x01\r"},
|
||||
{"crypto", "\x83\x01nC"},
|
||||
{"crypto/aes", "\x10\n\a\x93\x02"},
|
||||
{"crypto/cipher", "\x03\x1e\x01\x01\x1e\x11\x1c+X"},
|
||||
{"crypto/des", "\x10\x13\x1e-+\x9b\x01\x03"},
|
||||
{"crypto/dsa", "A\x04)\x83\x01\r"},
|
||||
{"crypto/ecdh", "\x03\v\f\x0e\x04\x15\x04\r\x1c\x83\x01"},
|
||||
{"crypto/ecdsa", "\x0e\x05\x03\x04\x01\x0e\a\v\x05\x01\x04\f\x01\x1c\x83\x01\r\x05K\x01"},
|
||||
{"crypto/ed25519", "\x0e\x1c\x11\x06\n\a\x1c\x83\x01C"},
|
||||
{"crypto/elliptic", "0>\x83\x01\r9"},
|
||||
{"crypto/fips140", " \x05"},
|
||||
{"crypto/hkdf", "-\x13\x01-\x15"},
|
||||
{"crypto/hmac", "\x1a\x14\x12\x01\x111"},
|
||||
{"crypto/internal/boring", "\x0e\x02\rf"},
|
||||
{"crypto/internal/boring/bbig", "\x1a\xe4\x01M"},
|
||||
{"crypto/internal/boring/bcache", "\xb8\x02\x13"},
|
||||
{"context", "q[o\x01\r"},
|
||||
{"crypto", "\x86\x01oC"},
|
||||
{"crypto/aes", "\x10\n\t\x95\x02"},
|
||||
{"crypto/cipher", "\x03 \x01\x01\x1f\x11\x1c+Y"},
|
||||
{"crypto/des", "\x10\x15\x1f-+\x9c\x01\x03"},
|
||||
{"crypto/dsa", "D\x04)\x84\x01\r"},
|
||||
{"crypto/ecdh", "\x03\v\f\x10\x04\x16\x04\r\x1c\x84\x01"},
|
||||
{"crypto/ecdsa", "\x0e\x05\x03\x04\x01\x10\a\v\x06\x01\x04\f\x01\x1c\x84\x01\r\x05K\x01"},
|
||||
{"crypto/ed25519", "\x0e\x1e\x11\a\n\a\x1c\x84\x01C"},
|
||||
{"crypto/elliptic", "2?\x84\x01\r9"},
|
||||
{"crypto/fips140", "\"\x05"},
|
||||
{"crypto/hkdf", "/\x14\x01-\x15"},
|
||||
{"crypto/hmac", "\x1a\x16\x13\x01\x111"},
|
||||
{"crypto/internal/boring", "\x0e\x02\ri"},
|
||||
{"crypto/internal/boring/bbig", "\x1a\xe8\x01M"},
|
||||
{"crypto/internal/boring/bcache", "\xbc\x02\x13"},
|
||||
{"crypto/internal/boring/sig", ""},
|
||||
{"crypto/internal/cryptotest", "\x03\r\n\x06$\x0e\x19\x06\x12\x12 \x04\a\t\x16\x01\x11\x11\x1b\x01\a\x05\b\x03\x05\v"},
|
||||
{"crypto/internal/entropy", "F"},
|
||||
{"crypto/internal/fips140", "?/\x15\xa7\x01\v\x16"},
|
||||
{"crypto/internal/fips140/aes", "\x03\x1d\x03\x02\x13\x05\x01\x01\x05*\x92\x014"},
|
||||
{"crypto/internal/fips140/aes/gcm", " \x01\x02\x02\x02\x11\x05\x01\x06*\x8f\x01"},
|
||||
{"crypto/internal/fips140/alias", "\xcb\x02"},
|
||||
{"crypto/internal/fips140/bigmod", "%\x18\x01\x06*\x92\x01"},
|
||||
{"crypto/internal/fips140/check", " \x0e\x06\t\x02\xb2\x01Z"},
|
||||
{"crypto/internal/fips140/check/checktest", "%\x85\x02!"},
|
||||
{"crypto/internal/fips140/drbg", "\x03\x1c\x01\x01\x04\x13\x05\b\x01(\x83\x01\x0f7"},
|
||||
{"crypto/internal/fips140/ecdh", "\x03\x1d\x05\x02\t\r1\x83\x01\x0f7"},
|
||||
{"crypto/internal/fips140/ecdsa", "\x03\x1d\x04\x01\x02\a\x02\x068\x15nF"},
|
||||
{"crypto/internal/fips140/ed25519", "\x03\x1d\x05\x02\x04\v8\xc6\x01\x03"},
|
||||
{"crypto/internal/fips140/edwards25519", "%\a\f\x051\x92\x017"},
|
||||
{"crypto/internal/fips140/edwards25519/field", "%\x13\x051\x92\x01"},
|
||||
{"crypto/internal/fips140/hkdf", "\x03\x1d\x05\t\x06:\x15"},
|
||||
{"crypto/internal/fips140/hmac", "\x03\x1d\x14\x01\x018\x15"},
|
||||
{"crypto/internal/fips140/mlkem", "\x03\x1d\x05\x02\x0e\x03\x051"},
|
||||
{"crypto/internal/fips140/nistec", "%\f\a\x051\x92\x01*\r\x14"},
|
||||
{"crypto/internal/fips140/nistec/fiat", "%\x136\x92\x01"},
|
||||
{"crypto/internal/fips140/pbkdf2", "\x03\x1d\x05\t\x06:\x15"},
|
||||
{"crypto/internal/fips140/rsa", "\x03\x1d\x04\x01\x02\r\x01\x01\x026\x15nF"},
|
||||
{"crypto/internal/fips140/sha256", "\x03\x1d\x1d\x01\x06*\x15}"},
|
||||
{"crypto/internal/fips140/sha3", "\x03\x1d\x18\x05\x010\x92\x01K"},
|
||||
{"crypto/internal/fips140/sha512", "\x03\x1d\x1d\x01\x06*\x15}"},
|
||||
{"crypto/internal/fips140/ssh", "%^"},
|
||||
{"crypto/internal/fips140/subtle", "#\x1a\xc3\x01"},
|
||||
{"crypto/internal/fips140/tls12", "\x03\x1d\x05\t\x06\x028\x15"},
|
||||
{"crypto/internal/fips140/tls13", "\x03\x1d\x05\b\a\t1\x15"},
|
||||
{"crypto/internal/fips140cache", "\xaa\x02\r&"},
|
||||
{"crypto/internal/constanttime", ""},
|
||||
{"crypto/internal/cryptotest", "\x03\r\n\b%\x0e\x19\x06\x12\x12 \x04\x06\t\x18\x01\x11\x11\x1b\x01\a\x05\b\x03\x05\v"},
|
||||
{"crypto/internal/entropy", "I"},
|
||||
{"crypto/internal/entropy/v1.0.0", "B/\x93\x018\x13"},
|
||||
{"crypto/internal/fips140", "A0\xbd\x01\v\x16"},
|
||||
{"crypto/internal/fips140/aes", "\x03\x1f\x03\x02\x13\x05\x01\x01\x06*\x93\x014"},
|
||||
{"crypto/internal/fips140/aes/gcm", "\"\x01\x02\x02\x02\x11\x05\x01\a*\x90\x01"},
|
||||
{"crypto/internal/fips140/alias", "\xcf\x02"},
|
||||
{"crypto/internal/fips140/bigmod", "'\x18\x01\a*\x93\x01"},
|
||||
{"crypto/internal/fips140/check", "\"\x0e\x06\t\x02\xb4\x01Z"},
|
||||
{"crypto/internal/fips140/check/checktest", "'\x87\x02!"},
|
||||
{"crypto/internal/fips140/drbg", "\x03\x1e\x01\x01\x04\x13\x05\t\x01(\x84\x01\x0f7\x01"},
|
||||
{"crypto/internal/fips140/ecdh", "\x03\x1f\x05\x02\t\r2\x84\x01\x0f7"},
|
||||
{"crypto/internal/fips140/ecdsa", "\x03\x1f\x04\x01\x02\a\x02\x069\x15oF"},
|
||||
{"crypto/internal/fips140/ed25519", "\x03\x1f\x05\x02\x04\v9\xc7\x01\x03"},
|
||||
{"crypto/internal/fips140/edwards25519", "\x1e\t\a\x112\x93\x017"},
|
||||
{"crypto/internal/fips140/edwards25519/field", "'\x13\x052\x93\x01"},
|
||||
{"crypto/internal/fips140/hkdf", "\x03\x1f\x05\t\x06;\x15"},
|
||||
{"crypto/internal/fips140/hmac", "\x03\x1f\x14\x01\x019\x15"},
|
||||
{"crypto/internal/fips140/mlkem", "\x03\x1f\x05\x02\x0e\x03\x052\xca\x01"},
|
||||
{"crypto/internal/fips140/nistec", "\x1e\t\f\f2\x93\x01*\r\x14"},
|
||||
{"crypto/internal/fips140/nistec/fiat", "'\x137\x93\x01"},
|
||||
{"crypto/internal/fips140/pbkdf2", "\x03\x1f\x05\t\x06;\x15"},
|
||||
{"crypto/internal/fips140/rsa", "\x03\x1b\x04\x04\x01\x02\r\x01\x01\x027\x15oF"},
|
||||
{"crypto/internal/fips140/sha256", "\x03\x1f\x1d\x01\a*\x15~"},
|
||||
{"crypto/internal/fips140/sha3", "\x03\x1f\x18\x05\x011\x93\x01K"},
|
||||
{"crypto/internal/fips140/sha512", "\x03\x1f\x1d\x01\a*\x15~"},
|
||||
{"crypto/internal/fips140/ssh", "'_"},
|
||||
{"crypto/internal/fips140/subtle", "\x1e\a\x1a\xc5\x01"},
|
||||
{"crypto/internal/fips140/tls12", "\x03\x1f\x05\t\x06\x029\x15"},
|
||||
{"crypto/internal/fips140/tls13", "\x03\x1f\x05\b\a\t2\x15"},
|
||||
{"crypto/internal/fips140cache", "\xae\x02\r&"},
|
||||
{"crypto/internal/fips140deps", ""},
|
||||
{"crypto/internal/fips140deps/byteorder", "\x99\x01"},
|
||||
{"crypto/internal/fips140deps/cpu", "\xae\x01\a"},
|
||||
{"crypto/internal/fips140deps/godebug", "\xb6\x01"},
|
||||
{"crypto/internal/fips140hash", "5\x1b3\xc8\x01"},
|
||||
{"crypto/internal/fips140only", "'\r\x01\x01M3;"},
|
||||
{"crypto/internal/fips140deps/byteorder", "\x9c\x01"},
|
||||
{"crypto/internal/fips140deps/cpu", "\xb1\x01\a"},
|
||||
{"crypto/internal/fips140deps/godebug", "\xb9\x01"},
|
||||
{"crypto/internal/fips140deps/time", "\xc9\x02"},
|
||||
{"crypto/internal/fips140hash", "7\x1c3\xc9\x01"},
|
||||
{"crypto/internal/fips140only", ")\r\x01\x01N3<"},
|
||||
{"crypto/internal/fips140test", ""},
|
||||
{"crypto/internal/hpke", "\x0e\x01\x01\x03\x053#+gM"},
|
||||
{"crypto/internal/impl", "\xb5\x02"},
|
||||
{"crypto/internal/randutil", "\xf1\x01\x12"},
|
||||
{"crypto/internal/sysrand", "nn! \r\r\x01\x01\f\x06"},
|
||||
{"crypto/internal/sysrand/internal/seccomp", "n"},
|
||||
{"crypto/md5", "\x0e3-\x15\x16g"},
|
||||
{"crypto/mlkem", "/"},
|
||||
{"crypto/pbkdf2", "2\x0e\x01-\x15"},
|
||||
{"crypto/rand", "\x1a\x06\a\x1a\x04\x01(\x83\x01\rM"},
|
||||
{"crypto/rc4", "#\x1e-\xc6\x01"},
|
||||
{"crypto/rsa", "\x0e\f\x01\t\x0f\r\x01\x04\x06\a\x1c\x03\x123;\f\x01"},
|
||||
{"crypto/sha1", "\x0e\f'\x03*\x15\x16\x15R"},
|
||||
{"crypto/sha256", "\x0e\f\x1aO"},
|
||||
{"crypto/sha3", "\x0e'N\xc8\x01"},
|
||||
{"crypto/sha512", "\x0e\f\x1cM"},
|
||||
{"crypto/subtle", "8\x9b\x01W"},
|
||||
{"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x02\x01\x01\a\x01\r\n\x01\t\x05\x03\x01\x01\x01\x01\x02\x01\x02\x01\x17\x02\x03\x12\x16\x15\b;\x16\x16\r\b\x01\x01\x01\x02\x01\r\x06\x02\x01\x0f"},
|
||||
{"crypto/tls/internal/fips140tls", "\x17\xa1\x02"},
|
||||
{"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x012\x05\x01\x01\x02\x05\x0e\x06\x02\x02\x03E\x038\x01\x02\b\x01\x01\x02\a\x10\x05\x01\x06\x02\x05\n\x01\x02\x0e\x02\x01\x01\x02\x03\x01"},
|
||||
{"crypto/x509/pkix", "d\x06\a\x8d\x01G"},
|
||||
{"database/sql", "\x03\nK\x16\x03\x80\x01\v\a\"\x05\b\x02\x03\x01\r\x02\x02\x02"},
|
||||
{"database/sql/driver", "\ra\x03\xb4\x01\x0f\x11"},
|
||||
{"debug/buildinfo", "\x03X\x02\x01\x01\b\a\x03e\x19\x02\x01+\x0f\x1f"},
|
||||
{"debug/dwarf", "\x03d\a\x03\x80\x011\x11\x01\x01"},
|
||||
{"debug/elf", "\x03\x06Q\r\a\x03e\x1a\x01,\x17\x01\x16"},
|
||||
{"debug/gosym", "\x03d\n\xc2\x01\x01\x01\x02"},
|
||||
{"debug/macho", "\x03\x06Q\r\ne\x1b,\x17\x01"},
|
||||
{"debug/pe", "\x03\x06Q\r\a\x03e\x1b,\x17\x01\x16"},
|
||||
{"debug/plan9obj", "g\a\x03e\x1b,"},
|
||||
{"embed", "n*@\x19\x01S"},
|
||||
{"crypto/internal/hpke", "\x0e\x01\x01\x03\x056#+hM"},
|
||||
{"crypto/internal/impl", "\xb9\x02"},
|
||||
{"crypto/internal/randutil", "\xf5\x01\x12"},
|
||||
{"crypto/internal/sysrand", "qo! \r\r\x01\x01\f\x06"},
|
||||
{"crypto/internal/sysrand/internal/seccomp", "q"},
|
||||
{"crypto/md5", "\x0e6-\x15\x16h"},
|
||||
{"crypto/mlkem", "1"},
|
||||
{"crypto/pbkdf2", "4\x0f\x01-\x15"},
|
||||
{"crypto/rand", "\x1a\b\a\x1b\x04\x01(\x84\x01\rM"},
|
||||
{"crypto/rc4", "%\x1f-\xc7\x01"},
|
||||
{"crypto/rsa", "\x0e\f\x01\v\x0f\x0e\x01\x04\x06\a\x1c\x03\x123<\f\x01"},
|
||||
{"crypto/sha1", "\x0e\f*\x03*\x15\x16\x15S"},
|
||||
{"crypto/sha256", "\x0e\f\x1cP"},
|
||||
{"crypto/sha3", "\x0e)O\xc9\x01"},
|
||||
{"crypto/sha512", "\x0e\f\x1eN"},
|
||||
{"crypto/subtle", "\x1e\x1c\x9c\x01X"},
|
||||
{"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x02\x01\x01\t\x01\r\n\x01\n\x05\x03\x01\x01\x01\x01\x02\x01\x02\x01\x17\x02\x03\x12\x16\x15\b<\x16\x16\r\b\x01\x01\x01\x02\x01\r\x06\x02\x01\x0f"},
|
||||
{"crypto/tls/internal/fips140tls", "\x17\xa5\x02"},
|
||||
{"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x015\x05\x01\x01\x02\x05\x0e\x06\x02\x02\x03E\x039\x01\x02\b\x01\x01\x02\a\x10\x05\x01\x06\x02\x05\b\x02\x01\x02\x0e\x02\x01\x01\x02\x03\x01"},
|
||||
{"crypto/x509/pkix", "g\x06\a\x8e\x01G"},
|
||||
{"database/sql", "\x03\nN\x16\x03\x81\x01\v\a\"\x05\b\x02\x03\x01\r\x02\x02\x02"},
|
||||
{"database/sql/driver", "\rd\x03\xb5\x01\x0f\x11"},
|
||||
{"debug/buildinfo", "\x03[\x02\x01\x01\b\a\x03e\x1a\x02\x01+\x0f\x1f"},
|
||||
{"debug/dwarf", "\x03g\a\x03\x81\x011\x11\x01\x01"},
|
||||
{"debug/elf", "\x03\x06T\r\a\x03e\x1b\x01\f \x17\x01\x16"},
|
||||
{"debug/gosym", "\x03g\n\xc3\x01\x01\x01\x02"},
|
||||
{"debug/macho", "\x03\x06T\r\ne\x1c,\x17\x01"},
|
||||
{"debug/pe", "\x03\x06T\r\a\x03e\x1c,\x17\x01\x16"},
|
||||
{"debug/plan9obj", "j\a\x03e\x1c,"},
|
||||
{"embed", "q*A\x19\x01S"},
|
||||
{"embed/internal/embedtest", ""},
|
||||
{"encoding", ""},
|
||||
{"encoding/ascii85", "\xf1\x01C"},
|
||||
{"encoding/asn1", "\x03k\x03\x8c\x01\x01'\r\x02\x01\x10\x03\x01"},
|
||||
{"encoding/base32", "\xf1\x01A\x02"},
|
||||
{"encoding/base64", "\x99\x01XA\x02"},
|
||||
{"encoding/binary", "n\x83\x01\f(\r\x05"},
|
||||
{"encoding/csv", "\x02\x01k\x03\x80\x01D\x12\x02"},
|
||||
{"encoding/gob", "\x02`\x05\a\x03e\x1b\v\x01\x03\x1d\b\x12\x01\x0f\x02"},
|
||||
{"encoding/hex", "n\x03\x80\x01A\x03"},
|
||||
{"encoding/json", "\x03\x01^\x04\b\x03\x80\x01\f(\r\x02\x01\x02\x10\x01\x01\x02"},
|
||||
{"encoding/pem", "\x03c\b\x83\x01A\x03"},
|
||||
{"encoding/xml", "\x02\x01_\f\x03\x80\x014\x05\n\x01\x02\x10\x02"},
|
||||
{"errors", "\xca\x01\x81\x01"},
|
||||
{"expvar", "kK?\b\v\x15\r\b\x02\x03\x01\x11"},
|
||||
{"flag", "b\f\x03\x80\x01,\b\x05\b\x02\x01\x10"},
|
||||
{"fmt", "nE>\f \b\r\x02\x03\x12"},
|
||||
{"go/ast", "\x03\x01m\x0e\x01q\x03)\b\r\x02\x01"},
|
||||
{"go/build", "\x02\x01k\x03\x01\x02\x02\a\x02\x01\x17\x1f\x04\x02\t\x19\x13\x01+\x01\x04\x01\a\b\x02\x01\x12\x02\x02"},
|
||||
{"go/build/constraint", "n\xc6\x01\x01\x12\x02"},
|
||||
{"go/constant", "q\x0f}\x01\x024\x01\x02\x12"},
|
||||
{"go/doc", "\x04m\x01\x05\t>31\x10\x02\x01\x12\x02"},
|
||||
{"go/doc/comment", "\x03n\xc1\x01\x01\x01\x01\x12\x02"},
|
||||
{"go/format", "\x03n\x01\v\x01\x02qD"},
|
||||
{"go/importer", "s\a\x01\x01\x04\x01p9"},
|
||||
{"go/internal/gccgoimporter", "\x02\x01X\x13\x03\x04\v\x01n\x02,\x01\x05\x11\x01\f\b"},
|
||||
{"go/internal/gcimporter", "\x02o\x0f\x010\x05\x0e-,\x15\x03\x02"},
|
||||
{"go/internal/srcimporter", "q\x01\x01\n\x03\x01p,\x01\x05\x12\x02\x14"},
|
||||
{"go/parser", "\x03k\x03\x01\x02\v\x01q\x01+\x06\x12"},
|
||||
{"go/printer", "q\x01\x02\x03\tq\f \x15\x02\x01\x02\v\x05\x02"},
|
||||
{"go/scanner", "\x03n\x0fq2\x10\x01\x13\x02"},
|
||||
{"go/token", "\x04m\x83\x01>\x02\x03\x01\x0f\x02"},
|
||||
{"go/types", "\x03\x01\x06d\x03\x01\x03\b\x03\x02\x15\x1f\x061\x04\x03\t \x06\a\b\x01\x01\x01\x02\x01\x0f\x02\x02"},
|
||||
{"go/version", "\xbb\x01z"},
|
||||
{"hash", "\xf1\x01"},
|
||||
{"hash/adler32", "n\x15\x16"},
|
||||
{"hash/crc32", "n\x15\x16\x15\x89\x01\x01\x13"},
|
||||
{"hash/crc64", "n\x15\x16\x9e\x01"},
|
||||
{"hash/fnv", "n\x15\x16g"},
|
||||
{"hash/maphash", "\x83\x01\x11!\x03\x93\x01"},
|
||||
{"html", "\xb5\x02\x02\x12"},
|
||||
{"html/template", "\x03h\x06\x18-;\x01\n!\x05\x01\x02\x03\f\x01\x02\f\x01\x03\x02"},
|
||||
{"image", "\x02l\x1ee\x0f4\x03\x01"},
|
||||
{"encoding/ascii85", "\xf5\x01C"},
|
||||
{"encoding/asn1", "\x03n\x03e(\x01'\r\x02\x01\x10\x03\x01"},
|
||||
{"encoding/base32", "\xf5\x01A\x02"},
|
||||
{"encoding/base64", "\x9c\x01YA\x02"},
|
||||
{"encoding/binary", "q\x84\x01\f(\r\x05"},
|
||||
{"encoding/csv", "\x02\x01n\x03\x81\x01D\x12\x02"},
|
||||
{"encoding/gob", "\x02c\x05\a\x03e\x1c\v\x01\x03\x1d\b\x12\x01\x0f\x02"},
|
||||
{"encoding/hex", "q\x03\x81\x01A\x03"},
|
||||
{"encoding/json", "\x03\x01a\x04\b\x03\x81\x01\f(\r\x02\x01\x02\x10\x01\x01\x02"},
|
||||
{"encoding/pem", "\x03f\b\x84\x01A\x03"},
|
||||
{"encoding/xml", "\x02\x01b\f\x03\x81\x014\x05\n\x01\x02\x10\x02"},
|
||||
{"errors", "\xcc\x01\x83\x01"},
|
||||
{"expvar", "nK@\b\v\x15\r\b\x02\x03\x01\x11"},
|
||||
{"flag", "e\f\x03\x81\x01,\b\x05\b\x02\x01\x10"},
|
||||
{"fmt", "qE&\x19\f \b\r\x02\x03\x12"},
|
||||
{"go/ast", "\x03\x01p\x0e\x01r\x03)\b\r\x02\x01\x12\x02"},
|
||||
{"go/build", "\x02\x01n\x03\x01\x02\x02\a\x02\x01\x17\x1f\x04\x02\b\x1b\x13\x01+\x01\x04\x01\a\b\x02\x01\x12\x02\x02"},
|
||||
{"go/build/constraint", "q\xc7\x01\x01\x12\x02"},
|
||||
{"go/constant", "t\x0f~\x01\x024\x01\x02\x12"},
|
||||
{"go/doc", "\x04p\x01\x05\t=51\x10\x02\x01\x12\x02"},
|
||||
{"go/doc/comment", "\x03q\xc2\x01\x01\x01\x01\x12\x02"},
|
||||
{"go/format", "\x03q\x01\v\x01\x02rD"},
|
||||
{"go/importer", "v\a\x01\x01\x04\x01q9"},
|
||||
{"go/internal/gccgoimporter", "\x02\x01[\x13\x03\x04\v\x01o\x02,\x01\x05\x11\x01\f\b"},
|
||||
{"go/internal/gcimporter", "\x02r\x0f\x010\x05\r/,\x15\x03\x02"},
|
||||
{"go/internal/srcimporter", "t\x01\x01\n\x03\x01q,\x01\x05\x12\x02\x14"},
|
||||
{"go/parser", "\x03n\x03\x01\x02\v\x01r\x01+\x06\x12"},
|
||||
{"go/printer", "t\x01\x02\x03\tr\f \x15\x02\x01\x02\v\x05\x02"},
|
||||
{"go/scanner", "\x03q\x0fr2\x10\x01\x13\x02"},
|
||||
{"go/token", "\x04p\x84\x01>\x02\x03\x01\x0f\x02"},
|
||||
{"go/types", "\x03\x01\x06g\x03\x01\x03\b\x03\x024\x062\x04\x03\t \x06\a\b\x01\x01\x01\x02\x01\x0f\x02\x02"},
|
||||
{"go/version", "\xbe\x01{"},
|
||||
{"hash", "\xf5\x01"},
|
||||
{"hash/adler32", "q\x15\x16"},
|
||||
{"hash/crc32", "q\x15\x16\x15\x8a\x01\x01\x13"},
|
||||
{"hash/crc64", "q\x15\x16\x9f\x01"},
|
||||
{"hash/fnv", "q\x15\x16h"},
|
||||
{"hash/maphash", "\x86\x01\x11<|"},
|
||||
{"html", "\xb9\x02\x02\x12"},
|
||||
{"html/template", "\x03k\x06\x18-<\x01\n!\x05\x01\x02\x03\f\x01\x02\f\x01\x03\x02"},
|
||||
{"image", "\x02o\x1ef\x0f4\x03\x01"},
|
||||
{"image/color", ""},
|
||||
{"image/color/palette", "\x8c\x01"},
|
||||
{"image/draw", "\x8b\x01\x01\x04"},
|
||||
{"image/gif", "\x02\x01\x05f\x03\x1a\x01\x01\x01\vX"},
|
||||
{"image/internal/imageutil", "\x8b\x01"},
|
||||
{"image/jpeg", "\x02l\x1d\x01\x04a"},
|
||||
{"image/png", "\x02\a^\n\x12\x02\x06\x01eC"},
|
||||
{"index/suffixarray", "\x03d\a\x83\x01\f+\n\x01"},
|
||||
{"internal/abi", "\xb5\x01\x96\x01"},
|
||||
{"internal/asan", "\xcb\x02"},
|
||||
{"internal/bisect", "\xaa\x02\r\x01"},
|
||||
{"internal/buildcfg", "qGe\x06\x02\x05\n\x01"},
|
||||
{"internal/bytealg", "\xae\x01\x9d\x01"},
|
||||
{"image/color/palette", "\x8f\x01"},
|
||||
{"image/draw", "\x8e\x01\x01\x04"},
|
||||
{"image/gif", "\x02\x01\x05i\x03\x1a\x01\x01\x01\vY"},
|
||||
{"image/internal/imageutil", "\x8e\x01"},
|
||||
{"image/jpeg", "\x02o\x1d\x01\x04b"},
|
||||
{"image/png", "\x02\aa\n\x12\x02\x06\x01fC"},
|
||||
{"index/suffixarray", "\x03g\a\x84\x01\f+\n\x01"},
|
||||
{"internal/abi", "\xb8\x01\x97\x01"},
|
||||
{"internal/asan", "\xcf\x02"},
|
||||
{"internal/bisect", "\xae\x02\r\x01"},
|
||||
{"internal/buildcfg", "tGf\x06\x02\x05\n\x01"},
|
||||
{"internal/bytealg", "\xb1\x01\x9e\x01"},
|
||||
{"internal/byteorder", ""},
|
||||
{"internal/cfg", ""},
|
||||
{"internal/cgrouptest", "q[Q\x06\x0f\x02\x01\x04\x01"},
|
||||
{"internal/chacha8rand", "\x99\x01\x15\a\x96\x01"},
|
||||
{"internal/cgrouptest", "tZS\x06\x0f\x02\x01\x04\x01"},
|
||||
{"internal/chacha8rand", "\x9c\x01\x15\a\x97\x01"},
|
||||
{"internal/copyright", ""},
|
||||
{"internal/coverage", ""},
|
||||
{"internal/coverage/calloc", ""},
|
||||
{"internal/coverage/cfile", "k\x06\x16\x17\x01\x02\x01\x01\x01\x01\x01\x01\x01#\x02$,\x06\a\n\x01\x03\r\x06"},
|
||||
{"internal/coverage/cformat", "\x04m-\x04O\v6\x01\x02\r"},
|
||||
{"internal/coverage/cmerge", "q-_"},
|
||||
{"internal/coverage/decodecounter", "g\n-\v\x02F,\x17\x17"},
|
||||
{"internal/coverage/decodemeta", "\x02e\n\x16\x17\v\x02F,"},
|
||||
{"internal/coverage/encodecounter", "\x02e\n-\f\x01\x02D\v!\x15"},
|
||||
{"internal/coverage/encodemeta", "\x02\x01d\n\x12\x04\x17\r\x02D,."},
|
||||
{"internal/coverage/pods", "\x04m-\x7f\x06\x05\n\x02\x01"},
|
||||
{"internal/coverage/rtcov", "\xcb\x02"},
|
||||
{"internal/coverage/slicereader", "g\n\x80\x01Z"},
|
||||
{"internal/coverage/slicewriter", "q\x80\x01"},
|
||||
{"internal/coverage/stringtab", "q8\x04D"},
|
||||
{"internal/coverage/cfile", "n\x06\x16\x17\x01\x02\x01\x01\x01\x01\x01\x01\x01\"\x02&,\x06\a\n\x01\x03\r\x06"},
|
||||
{"internal/coverage/cformat", "\x04p-\x04P\v6\x01\x02\r"},
|
||||
{"internal/coverage/cmerge", "t-`"},
|
||||
{"internal/coverage/decodecounter", "j\n-\v\x02G,\x17\x17"},
|
||||
{"internal/coverage/decodemeta", "\x02h\n\x16\x17\v\x02G,"},
|
||||
{"internal/coverage/encodecounter", "\x02h\n-\f\x01\x02E\v!\x15"},
|
||||
{"internal/coverage/encodemeta", "\x02\x01g\n\x12\x04\x17\r\x02E,."},
|
||||
{"internal/coverage/pods", "\x04p-\x80\x01\x06\x05\n\x02\x01"},
|
||||
{"internal/coverage/rtcov", "\xcf\x02"},
|
||||
{"internal/coverage/slicereader", "j\n\x81\x01Z"},
|
||||
{"internal/coverage/slicewriter", "t\x81\x01"},
|
||||
{"internal/coverage/stringtab", "t8\x04E"},
|
||||
{"internal/coverage/test", ""},
|
||||
{"internal/coverage/uleb128", ""},
|
||||
{"internal/cpu", "\xcb\x02"},
|
||||
{"internal/dag", "\x04m\xc1\x01\x03"},
|
||||
{"internal/diff", "\x03n\xc2\x01\x02"},
|
||||
{"internal/exportdata", "\x02\x01k\x03\x02c\x1b,\x01\x05\x11\x01\x02"},
|
||||
{"internal/filepathlite", "n*@\x1a@"},
|
||||
{"internal/fmtsort", "\x04\xa1\x02\r"},
|
||||
{"internal/fuzz", "\x03\nB\x18\x04\x03\x03\x01\v\x036;\f\x03\x1d\x01\x05\x02\x05\n\x01\x02\x01\x01\f\x04\x02"},
|
||||
{"internal/cpu", "\xcf\x02"},
|
||||
{"internal/dag", "\x04p\xc2\x01\x03"},
|
||||
{"internal/diff", "\x03q\xc3\x01\x02"},
|
||||
{"internal/exportdata", "\x02\x01n\x03\x02c\x1c,\x01\x05\x11\x01\x02"},
|
||||
{"internal/filepathlite", "q*A\x1a@"},
|
||||
{"internal/fmtsort", "\x04\xa5\x02\r"},
|
||||
{"internal/fuzz", "\x03\nE\x18\x04\x03\x03\x01\v\x036<\f\x03\x1d\x01\x05\x02\x05\n\x01\x02\x01\x01\f\x04\x02"},
|
||||
{"internal/goarch", ""},
|
||||
{"internal/godebug", "\x96\x01!\x80\x01\x01\x13"},
|
||||
{"internal/godebug", "\x99\x01!\x81\x01\x01\x13"},
|
||||
{"internal/godebugs", ""},
|
||||
{"internal/goexperiment", ""},
|
||||
{"internal/goos", ""},
|
||||
{"internal/goroot", "\x9d\x02\x01\x05\x12\x02"},
|
||||
{"internal/goroot", "\xa1\x02\x01\x05\x12\x02"},
|
||||
{"internal/gover", "\x04"},
|
||||
{"internal/goversion", ""},
|
||||
{"internal/itoa", ""},
|
||||
{"internal/lazyregexp", "\x9d\x02\v\r\x02"},
|
||||
{"internal/lazytemplate", "\xf1\x01,\x18\x02\f"},
|
||||
{"internal/msan", "\xcb\x02"},
|
||||
{"internal/lazyregexp", "\xa1\x02\v\r\x02"},
|
||||
{"internal/lazytemplate", "\xf5\x01,\x18\x02\f"},
|
||||
{"internal/msan", "\xcf\x02"},
|
||||
{"internal/nettrace", ""},
|
||||
{"internal/obscuretestdata", "f\x8b\x01,"},
|
||||
{"internal/oserror", "n"},
|
||||
{"internal/pkgbits", "\x03L\x18\a\x03\x04\vq\r\x1f\r\n\x01"},
|
||||
{"internal/obscuretestdata", "i\x8c\x01,"},
|
||||
{"internal/oserror", "q"},
|
||||
{"internal/pkgbits", "\x03O\x18\a\x03\x04\vr\r\x1f\r\n\x01"},
|
||||
{"internal/platform", ""},
|
||||
{"internal/poll", "nO\x1f\x159\r\x01\x01\f\x06"},
|
||||
{"internal/profile", "\x03\x04g\x03\x80\x017\v\x01\x01\x10"},
|
||||
{"internal/poll", "qj\x05\x159\r\x01\x01\f\x06"},
|
||||
{"internal/profile", "\x03\x04j\x03\x81\x017\n\x01\x01\x01\x10"},
|
||||
{"internal/profilerecord", ""},
|
||||
{"internal/race", "\x94\x01\xb7\x01"},
|
||||
{"internal/reflectlite", "\x94\x01!9<!"},
|
||||
{"internal/runtime/atomic", "\xb5\x01\x96\x01"},
|
||||
{"internal/runtime/cgroup", "\x98\x01:\x02w"},
|
||||
{"internal/runtime/exithook", "\xcb\x01\x80\x01"},
|
||||
{"internal/runtime/gc", "\xb5\x01"},
|
||||
{"internal/runtime/maps", "\x94\x01\x01 \v\t\a\x03x"},
|
||||
{"internal/runtime/math", "\xb5\x01"},
|
||||
{"internal/race", "\x97\x01\xb8\x01"},
|
||||
{"internal/reflectlite", "\x97\x01!:<!"},
|
||||
{"internal/runtime/atomic", "\xb8\x01\x97\x01"},
|
||||
{"internal/runtime/cgroup", "\x9b\x01<\x04t"},
|
||||
{"internal/runtime/exithook", "\xcd\x01\x82\x01"},
|
||||
{"internal/runtime/gc", "\xb8\x01"},
|
||||
{"internal/runtime/gc/internal/gen", "\n`\n\x17j\x04\v\x1d\b\x10\x02"},
|
||||
{"internal/runtime/gc/scan", "\xb1\x01\a\x18\x06y"},
|
||||
{"internal/runtime/maps", "\x97\x01\x01 \n\t\t\x02y"},
|
||||
{"internal/runtime/math", "\xb8\x01"},
|
||||
{"internal/runtime/startlinetest", ""},
|
||||
{"internal/runtime/strconv", "\xd0\x01"},
|
||||
{"internal/runtime/sys", "\xb5\x01\x04"},
|
||||
{"internal/runtime/syscall", "\xb5\x01\x96\x01"},
|
||||
{"internal/runtime/sys", "\xb8\x01\x04"},
|
||||
{"internal/runtime/syscall/linux", "\xb8\x01\x97\x01"},
|
||||
{"internal/runtime/wasitest", ""},
|
||||
{"internal/saferio", "\xf1\x01Z"},
|
||||
{"internal/singleflight", "\xb7\x02"},
|
||||
{"internal/stringslite", "\x98\x01\xb3\x01"},
|
||||
{"internal/sync", "\x94\x01!\x14o\x13"},
|
||||
{"internal/synctest", "\x94\x01\xb7\x01"},
|
||||
{"internal/syscall/execenv", "\xb9\x02"},
|
||||
{"internal/syscall/unix", "\xaa\x02\x0e\x01\x12"},
|
||||
{"internal/sysinfo", "\x02\x01\xab\x01C,\x18\x02"},
|
||||
{"internal/saferio", "\xf5\x01Z"},
|
||||
{"internal/singleflight", "\xbb\x02"},
|
||||
{"internal/strconv", "\x84\x02K"},
|
||||
{"internal/stringslite", "\x9b\x01\xb4\x01"},
|
||||
{"internal/sync", "\x97\x01!\x13q\x13"},
|
||||
{"internal/synctest", "\x97\x01\xb8\x01"},
|
||||
{"internal/syscall/execenv", "\xbd\x02"},
|
||||
{"internal/syscall/unix", "\xae\x02\x0e\x01\x12"},
|
||||
{"internal/sysinfo", "\x02\x01\xae\x01D,\x18\x02"},
|
||||
{"internal/syslist", ""},
|
||||
{"internal/testenv", "\x03\na\x02\x01)\x1b\x10-+\x01\x05\a\n\x01\x02\x02\x01\v"},
|
||||
{"internal/testhash", "\x03\x80\x01n\x118\v"},
|
||||
{"internal/testlog", "\xb7\x02\x01\x13"},
|
||||
{"internal/testpty", "n\x03\xac\x01"},
|
||||
{"internal/trace", "\x02\x01\x01\x06]\a\x03t\x03\x03\x06\x03\t5\x01\x01\x01\x10\x06"},
|
||||
{"internal/trace/internal/testgen", "\x03d\nr\x03\x02\x03\x011\v\r\x10"},
|
||||
{"internal/trace/internal/tracev1", "\x03\x01c\a\x03z\x06\f5\x01"},
|
||||
{"internal/trace/raw", "\x02e\nw\x03\x06C\x01\x12"},
|
||||
{"internal/trace/testtrace", "\x02\x01k\x03r\x03\x05\x01\x057\n\x02\x01"},
|
||||
{"internal/testenv", "\x03\nd\x02\x01)\x1b\x0f/+\x01\x05\a\n\x01\x02\x02\x01\v"},
|
||||
{"internal/testhash", "\x03\x83\x01o\x118\v"},
|
||||
{"internal/testlog", "\xbb\x02\x01\x13"},
|
||||
{"internal/testpty", "q\x03\xad\x01"},
|
||||
{"internal/trace", "\x02\x01\x01\x06`\a\x03u\x03\x03\x06\x03\t5\x01\x01\x01\x10\x06"},
|
||||
{"internal/trace/internal/testgen", "\x03g\ns\x03\x02\x03\x011\v\r\x10"},
|
||||
{"internal/trace/internal/tracev1", "\x03\x01f\a\x03{\x06\f5\x01"},
|
||||
{"internal/trace/raw", "\x02h\nx\x03\x06C\x01\x12"},
|
||||
{"internal/trace/testtrace", "\x02\x01n\x03o\x04\x03\x05\x01\x05,\v\x02\b\x02\x01\x05"},
|
||||
{"internal/trace/tracev2", ""},
|
||||
{"internal/trace/traceviewer", "\x02^\v\x06\x19=\x1c\a\a\x04\b\v\x15\x01\x05\a\n\x01\x02\x0e"},
|
||||
{"internal/trace/traceviewer", "\x02a\v\x06\x19<\x1e\a\a\x04\b\v\x15\x01\x05\a\n\x01\x02\x0e"},
|
||||
{"internal/trace/traceviewer/format", ""},
|
||||
{"internal/trace/version", "qw\t"},
|
||||
{"internal/txtar", "\x03n\xac\x01\x18"},
|
||||
{"internal/types/errors", "\xb4\x02"},
|
||||
{"internal/unsafeheader", "\xcb\x02"},
|
||||
{"internal/xcoff", "Z\r\a\x03e\x1b,\x17\x01"},
|
||||
{"internal/zstd", "g\a\x03\x80\x01\x0f"},
|
||||
{"io", "n\xc9\x01"},
|
||||
{"io/fs", "n*+.1\x10\x13\x04"},
|
||||
{"io/ioutil", "\xf1\x01\x01+\x15\x03"},
|
||||
{"iter", "\xc9\x01a!"},
|
||||
{"log", "q\x80\x01\x05'\r\r\x01\r"},
|
||||
{"internal/trace/version", "tx\t"},
|
||||
{"internal/txtar", "\x03q\xad\x01\x18"},
|
||||
{"internal/types/errors", "\xb8\x02"},
|
||||
{"internal/unsafeheader", "\xcf\x02"},
|
||||
{"internal/xcoff", "]\r\a\x03e\x1c,\x17\x01"},
|
||||
{"internal/zstd", "j\a\x03\x81\x01\x0f"},
|
||||
{"io", "q\xca\x01"},
|
||||
{"io/fs", "q**01\x10\x13\x04"},
|
||||
{"io/ioutil", "\xf5\x01\x01+\x15\x03"},
|
||||
{"iter", "\xcb\x01c!"},
|
||||
{"log", "t\x81\x01\x05'\r\r\x01\r"},
|
||||
{"log/internal", ""},
|
||||
{"log/slog", "\x03\nU\t\x03\x03\x80\x01\x04\x01\x02\x02\x03(\x05\b\x02\x01\x02\x01\r\x02\x02\x02"},
|
||||
{"log/slog", "\x03\nX\t\x03\x03\x81\x01\x04\x01\x02\x02\x03(\x05\b\x02\x01\x02\x01\r\x02\x02\x02"},
|
||||
{"log/slog/internal", ""},
|
||||
{"log/slog/internal/benchmarks", "\ra\x03\x80\x01\x06\x03:\x11"},
|
||||
{"log/slog/internal/buffer", "\xb7\x02"},
|
||||
{"log/syslog", "n\x03\x84\x01\x12\x16\x18\x02\x0e"},
|
||||
{"maps", "\xf4\x01W"},
|
||||
{"math", "\xae\x01RK"},
|
||||
{"math/big", "\x03k\x03(\x15C\f\x03\x020\x02\x01\x02\x14"},
|
||||
{"math/big/internal/asmgen", "\x03\x01m\x8f\x012\x03"},
|
||||
{"math/bits", "\xcb\x02"},
|
||||
{"math/cmplx", "\xfd\x01\x03"},
|
||||
{"math/rand", "\xb6\x01G:\x01\x13"},
|
||||
{"math/rand/v2", "n+\x03a\x03K"},
|
||||
{"mime", "\x02\x01c\b\x03\x80\x01\v!\x15\x03\x02\x10\x02"},
|
||||
{"mime/multipart", "\x02\x01H#\x03E;\v\x01\a\x02\x15\x02\x06\x0f\x02\x01\x16"},
|
||||
{"mime/quotedprintable", "\x02\x01n\x80\x01"},
|
||||
{"net", "\x04\ta*\x1e\a\x04\x05\x11\x01\x04\x15\x01%\x06\r\b\x05\x01\x01\f\x06\a"},
|
||||
{"net/http", "\x02\x01\x04\x04\x02>\b\x13\x01\a\x03E;\x01\x03\a\x01\x03\x02\x02\x01\x02\x06\x02\x01\x01\n\x01\x01\x05\x01\x02\x05\b\x01\x01\x01\x02\x01\r\x02\x02\x02\b\x01\x01\x01"},
|
||||
{"net/http/cgi", "\x02Q\x1b\x03\x80\x01\x04\a\v\x01\x13\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x10\x0e"},
|
||||
{"net/http/cookiejar", "\x04j\x03\x96\x01\x01\b\f\x16\x03\x02\x0e\x04"},
|
||||
{"net/http/fcgi", "\x02\x01\nZ\a\x03\x80\x01\x16\x01\x01\x14\x18\x02\x0e"},
|
||||
{"net/http/httptest", "\x02\x01\nF\x02\x1b\x01\x80\x01\x04\x12\x01\n\t\x02\x17\x01\x02\x0e\x0e"},
|
||||
{"net/http/httptrace", "\rFnF\x14\n "},
|
||||
{"net/http/httputil", "\x02\x01\na\x03\x80\x01\x04\x0f\x03\x01\x05\x02\x01\v\x01\x19\x02\x0e\x0e"},
|
||||
{"net/http/internal", "\x02\x01k\x03\x80\x01"},
|
||||
{"net/http/internal/ascii", "\xb5\x02\x12"},
|
||||
{"net/http/internal/httpcommon", "\ra\x03\x9c\x01\x0e\x01\x17\x01\x01\x02\x1c\x02"},
|
||||
{"net/http/internal/testcert", "\xb5\x02"},
|
||||
{"net/http/pprof", "\x02\x01\nd\x18-\x11*\x04\x13\x14\x01\r\x04\x03\x01\x02\x01\x10"},
|
||||
{"log/slog/internal/benchmarks", "\rd\x03\x81\x01\x06\x03:\x11"},
|
||||
{"log/slog/internal/buffer", "\xbb\x02"},
|
||||
{"log/syslog", "q\x03\x85\x01\x12\x16\x18\x02\x0e"},
|
||||
{"maps", "\xf8\x01W"},
|
||||
{"math", "\xb1\x01SK"},
|
||||
{"math/big", "\x03n\x03(\x15D\f\x03\x020\x02\x01\x02\x14"},
|
||||
{"math/big/internal/asmgen", "\x03\x01p\x90\x012\x03"},
|
||||
{"math/bits", "\xcf\x02"},
|
||||
{"math/cmplx", "\x81\x02\x03"},
|
||||
{"math/rand", "\xb9\x01H:\x01\x13"},
|
||||
{"math/rand/v2", "q+\x03b\x03K"},
|
||||
{"mime", "\x02\x01f\b\x03\x81\x01\v!\x15\x03\x02\x10\x02"},
|
||||
{"mime/multipart", "\x02\x01K#\x03E<\v\x01\a\x02\x15\x02\x06\x0f\x02\x01\x16"},
|
||||
{"mime/quotedprintable", "\x02\x01q\x81\x01"},
|
||||
{"net", "\x04\td*\x1e\n\x05\x12\x01\x01\x04\x15\x01%\x06\r\b\x05\x01\x01\f\x06\a"},
|
||||
{"net/http", "\x02\x01\x03\x01\x04\x02A\b\x13\x01\a\x03E<\x01\x03\a\x01\x03\x02\x02\x01\x02\x06\x02\x01\x01\n\x01\x01\x05\x01\x02\x05\b\x01\x01\x01\x02\x01\r\x02\x02\x02\b\x01\x01\x01"},
|
||||
{"net/http/cgi", "\x02T\x1b\x03\x81\x01\x04\a\v\x01\x13\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x10\x0e"},
|
||||
{"net/http/cookiejar", "\x04m\x03\x97\x01\x01\b\f\x16\x03\x02\x0e\x04"},
|
||||
{"net/http/fcgi", "\x02\x01\n]\a\x03\x81\x01\x16\x01\x01\x14\x18\x02\x0e"},
|
||||
{"net/http/httptest", "\x02\x01\nI\x02\x1b\x01\x81\x01\x04\x12\x01\n\t\x02\x17\x01\x02\x0e\x0e"},
|
||||
{"net/http/httptrace", "\rImH\x14\n "},
|
||||
{"net/http/httputil", "\x02\x01\nd\x03\x81\x01\x04\x0f\x03\x01\x05\x02\x01\v\x01\x19\x02\x0e\x0e"},
|
||||
{"net/http/internal", "\x02\x01n\x03\x81\x01"},
|
||||
{"net/http/internal/ascii", "\xb9\x02\x12"},
|
||||
{"net/http/internal/httpcommon", "\rd\x03\x9d\x01\x0e\x01\x17\x01\x01\x02\x1c\x02"},
|
||||
{"net/http/internal/testcert", "\xb9\x02"},
|
||||
{"net/http/pprof", "\x02\x01\ng\x18-\x02\x0e,\x04\x13\x14\x01\r\x04\x03\x01\x02\x01\x10"},
|
||||
{"net/internal/cgotest", ""},
|
||||
{"net/internal/socktest", "q\xc6\x01\x02"},
|
||||
{"net/mail", "\x02l\x03\x80\x01\x04\x0f\x03\x14\x1a\x02\x0e\x04"},
|
||||
{"net/netip", "\x04j*\x01$@\x034\x16"},
|
||||
{"net/rpc", "\x02g\x05\x03\x0f\ng\x04\x12\x01\x1d\r\x03\x02"},
|
||||
{"net/rpc/jsonrpc", "k\x03\x03\x80\x01\x16\x11\x1f"},
|
||||
{"net/smtp", "\x19/\v\x13\b\x03\x80\x01\x16\x14\x1a"},
|
||||
{"net/textproto", "\x02\x01k\x03\x80\x01\f\n-\x01\x02\x14"},
|
||||
{"net/url", "n\x03\x8b\x01&\x10\x02\x01\x16"},
|
||||
{"os", "n*\x01\x19\x03\b\t\x12\x03\x01\x05\x10\x018\b\x05\x01\x01\f\x06"},
|
||||
{"os/exec", "\x03\naH%\x01\x15\x01+\x06\a\n\x01\x04\f"},
|
||||
{"os/exec/internal/fdtest", "\xb9\x02"},
|
||||
{"os/signal", "\r\x90\x02\x15\x05\x02"},
|
||||
{"os/user", "\x02\x01k\x03\x80\x01,\r\n\x01\x02"},
|
||||
{"path", "n*\xb1\x01"},
|
||||
{"path/filepath", "n*\x1a@+\r\b\x03\x04\x10"},
|
||||
{"plugin", "n"},
|
||||
{"reflect", "n&\x04\x1d\b\f\x06\x04\x1b\x06\t-\n\x03\x10\x02\x02"},
|
||||
{"net/internal/socktest", "t\xc7\x01\x02"},
|
||||
{"net/mail", "\x02o\x03\x81\x01\x04\x0f\x03\x14\x1a\x02\x0e\x04"},
|
||||
{"net/netip", "\x04m*\x01e\x034\x16"},
|
||||
{"net/rpc", "\x02j\x05\x03\x0f\nh\x04\x12\x01\x1d\r\x03\x02"},
|
||||
{"net/rpc/jsonrpc", "n\x03\x03\x81\x01\x16\x11\x1f"},
|
||||
{"net/smtp", "\x192\v\x13\b\x03\x81\x01\x16\x14\x1a"},
|
||||
{"net/textproto", "\x02\x01n\x03\x81\x01\f\n-\x01\x02\x14"},
|
||||
{"net/url", "q\x03\xa7\x01\v\x10\x02\x01\x16"},
|
||||
{"os", "q*\x01\x19\x03\x10\x13\x01\x03\x01\x05\x10\x018\b\x05\x01\x01\f\x06"},
|
||||
{"os/exec", "\x03\ndH&\x01\x15\x01+\x06\a\n\x01\x04\f"},
|
||||
{"os/exec/internal/fdtest", "\xbd\x02"},
|
||||
{"os/signal", "\r\x94\x02\x15\x05\x02"},
|
||||
{"os/user", "\x02\x01n\x03\x81\x01,\r\n\x01\x02"},
|
||||
{"path", "q*\xb2\x01"},
|
||||
{"path/filepath", "q*\x1aA+\r\b\x03\x04\x10"},
|
||||
{"plugin", "q"},
|
||||
{"reflect", "q&\x04\x1d\x13\b\x03\x05\x17\x06\t-\n\x03\x10\x02\x02"},
|
||||
{"reflect/internal/example1", ""},
|
||||
{"reflect/internal/example2", ""},
|
||||
{"regexp", "\x03\xee\x018\t\x02\x01\x02\x10\x02"},
|
||||
{"regexp/syntax", "\xb2\x02\x01\x01\x01\x02\x10\x02"},
|
||||
{"runtime", "\x94\x01\x04\x01\x03\f\x06\a\x02\x01\x01\x0f\x03\x01\x01\x01\x01\x01\x02\x01\x01\x04\x10c"},
|
||||
{"runtime/coverage", "\xa0\x01Q"},
|
||||
{"runtime/debug", "qUW\r\b\x02\x01\x10\x06"},
|
||||
{"runtime/metrics", "\xb7\x01F-!"},
|
||||
{"runtime/pprof", "\x02\x01\x01\x03\x06Z\a\x03#4)\f \r\b\x01\x01\x01\x02\x02\t\x03\x06"},
|
||||
{"runtime/race", "\xb0\x02"},
|
||||
{"regexp", "\x03\xf2\x018\t\x02\x01\x02\x10\x02"},
|
||||
{"regexp/syntax", "\xb6\x02\x01\x01\x01\x02\x10\x02"},
|
||||
{"runtime", "\x97\x01\x04\x01\x03\f\x06\a\x02\x01\x01\x0e\x03\x01\x01\x01\x02\x01\x01\x02\x01\x04\x01\x10c"},
|
||||
{"runtime/coverage", "\xa3\x01R"},
|
||||
{"runtime/debug", "tTY\r\b\x02\x01\x10\x06"},
|
||||
{"runtime/metrics", "\xba\x01G-!"},
|
||||
{"runtime/pprof", "\x02\x01\x01\x03\x06]\a\x03#$\x0f+\f \r\b\x01\x01\x01\x02\x02\t\x03\x06"},
|
||||
{"runtime/race", "\xb4\x02"},
|
||||
{"runtime/race/internal/amd64v1", ""},
|
||||
{"runtime/trace", "\ra\x03w\t9\b\x05\x01\r\x06"},
|
||||
{"slices", "\x04\xf0\x01\fK"},
|
||||
{"sort", "\xca\x0162"},
|
||||
{"strconv", "n*@%\x03I"},
|
||||
{"strings", "n&\x04@\x19\x03\f7\x10\x02\x02"},
|
||||
{"runtime/trace", "\rd\x03x\t9\b\x05\x01\r\x06"},
|
||||
{"slices", "\x04\xf4\x01\fK"},
|
||||
{"sort", "\xcc\x0182"},
|
||||
{"strconv", "q*@\x01q"},
|
||||
{"strings", "q&\x04A\x19\x03\f7\x10\x02\x02"},
|
||||
{"structs", ""},
|
||||
{"sync", "\xc9\x01\x10\x01P\x0e\x13"},
|
||||
{"sync/atomic", "\xcb\x02"},
|
||||
{"syscall", "n'\x03\x01\x1c\b\x03\x03\x06\vV\b\x05\x01\x13"},
|
||||
{"testing", "\x03\na\x02\x01X\x14\x14\f\x05\x1b\x06\x02\x05\x02\x05\x01\x02\x01\x02\x01\r\x02\x02\x02"},
|
||||
{"testing/fstest", "n\x03\x80\x01\x01\n&\x10\x03\b\b"},
|
||||
{"testing/internal/testdeps", "\x02\v\xa7\x01-\x10,\x03\x05\x03\x06\a\x02\x0e"},
|
||||
{"testing/iotest", "\x03k\x03\x80\x01\x04"},
|
||||
{"testing/quick", "p\x01\x8c\x01\x05#\x10\x10"},
|
||||
{"testing/slogtest", "\ra\x03\x86\x01.\x05\x10\v"},
|
||||
{"testing/synctest", "\xda\x01`\x11"},
|
||||
{"text/scanner", "\x03n\x80\x01,*\x02"},
|
||||
{"text/tabwriter", "q\x80\x01X"},
|
||||
{"text/template", "n\x03B>\x01\n \x01\x05\x01\x02\x05\v\x02\r\x03\x02"},
|
||||
{"text/template/parse", "\x03n\xb9\x01\n\x01\x12\x02"},
|
||||
{"time", "n*\x1e\"(*\r\x02\x12"},
|
||||
{"time/tzdata", "n\xcb\x01\x12"},
|
||||
{"sync", "\xcb\x01\x12\x01P\x0e\x13"},
|
||||
{"sync/atomic", "\xcf\x02"},
|
||||
{"syscall", "q'\x03\x01\x1c\n\x03\x06\f\x04S\b\x05\x01\x13"},
|
||||
{"testing", "\x03\nd\x02\x01W\x16\x14\f\x05\x1b\x06\x02\x05\x02\x05\x01\x02\x01\x02\x01\r\x02\x04"},
|
||||
{"testing/fstest", "q\x03\x81\x01\x01\n&\x10\x03\b\b"},
|
||||
{"testing/internal/testdeps", "\x02\v\xaa\x01.\x10,\x03\x05\x03\x06\a\x02\x0e"},
|
||||
{"testing/iotest", "\x03n\x03\x81\x01\x04"},
|
||||
{"testing/quick", "s\x01\x8d\x01\x05#\x10\x10"},
|
||||
{"testing/slogtest", "\rd\x03\x87\x01.\x05\x10\v"},
|
||||
{"testing/synctest", "\xde\x01`\x11"},
|
||||
{"text/scanner", "\x03q\x81\x01,*\x02"},
|
||||
{"text/tabwriter", "t\x81\x01X"},
|
||||
{"text/template", "q\x03B?\x01\n \x01\x05\x01\x02\x05\v\x02\r\x03\x02"},
|
||||
{"text/template/parse", "\x03q\xba\x01\n\x01\x12\x02"},
|
||||
{"time", "q*\x1e#(*\r\x02\x12"},
|
||||
{"time/tzdata", "q\xcc\x01\x12"},
|
||||
{"unicode", ""},
|
||||
{"unicode/utf16", ""},
|
||||
{"unicode/utf8", ""},
|
||||
{"unique", "\x94\x01!#\x01Q\r\x01\x13\x12"},
|
||||
{"unique", "\x97\x01!$\x01Q\r\x01\x13\x12"},
|
||||
{"unsafe", ""},
|
||||
{"vendor/golang.org/x/crypto/chacha20", "\x10W\a\x92\x01*&"},
|
||||
{"vendor/golang.org/x/crypto/chacha20poly1305", "\x10W\a\xde\x01\x04\x01\a"},
|
||||
{"vendor/golang.org/x/crypto/cryptobyte", "d\n\x03\x8d\x01' \n"},
|
||||
{"vendor/golang.org/x/crypto/chacha20", "\x10Z\a\x93\x01*&"},
|
||||
{"vendor/golang.org/x/crypto/chacha20poly1305", "\x10Z\a\xdf\x01\x04\x01\a"},
|
||||
{"vendor/golang.org/x/crypto/cryptobyte", "g\n\x03\x8e\x01' \n"},
|
||||
{"vendor/golang.org/x/crypto/cryptobyte/asn1", ""},
|
||||
{"vendor/golang.org/x/crypto/internal/alias", "\xcb\x02"},
|
||||
{"vendor/golang.org/x/crypto/internal/poly1305", "R\x15\x99\x01"},
|
||||
{"vendor/golang.org/x/net/dns/dnsmessage", "n"},
|
||||
{"vendor/golang.org/x/net/http/httpguts", "\x87\x02\x14\x1a\x14\r"},
|
||||
{"vendor/golang.org/x/net/http/httpproxy", "n\x03\x96\x01\x10\x05\x01\x18\x14\r"},
|
||||
{"vendor/golang.org/x/net/http2/hpack", "\x03k\x03\x80\x01F"},
|
||||
{"vendor/golang.org/x/net/idna", "q\x8c\x018\x14\x10\x02\x01"},
|
||||
{"vendor/golang.org/x/net/nettest", "\x03d\a\x03\x80\x01\x11\x05\x16\x01\f\n\x01\x02\x02\x01\v"},
|
||||
{"vendor/golang.org/x/sys/cpu", "\x9d\x02\r\n\x01\x16"},
|
||||
{"vendor/golang.org/x/text/secure/bidirule", "n\xdb\x01\x11\x01"},
|
||||
{"vendor/golang.org/x/text/transform", "\x03k\x83\x01X"},
|
||||
{"vendor/golang.org/x/text/unicode/bidi", "\x03\bf\x84\x01>\x16"},
|
||||
{"vendor/golang.org/x/text/unicode/norm", "g\n\x80\x01F\x12\x11"},
|
||||
{"weak", "\x94\x01\x96\x01!"},
|
||||
{"vendor/golang.org/x/crypto/internal/alias", "\xcf\x02"},
|
||||
{"vendor/golang.org/x/crypto/internal/poly1305", "U\x15\x9a\x01"},
|
||||
{"vendor/golang.org/x/net/dns/dnsmessage", "q"},
|
||||
{"vendor/golang.org/x/net/http/httpguts", "\x8b\x02\x14\x1a\x14\r"},
|
||||
{"vendor/golang.org/x/net/http/httpproxy", "q\x03\x97\x01\x10\x05\x01\x18\x14\r"},
|
||||
{"vendor/golang.org/x/net/http2/hpack", "\x03n\x03\x81\x01F"},
|
||||
{"vendor/golang.org/x/net/idna", "t\x8d\x018\x14\x10\x02\x01"},
|
||||
{"vendor/golang.org/x/net/nettest", "\x03g\a\x03\x81\x01\x11\x05\x16\x01\f\n\x01\x02\x02\x01\v"},
|
||||
{"vendor/golang.org/x/sys/cpu", "\xa1\x02\r\n\x01\x16"},
|
||||
{"vendor/golang.org/x/text/secure/bidirule", "q\xdc\x01\x11\x01"},
|
||||
{"vendor/golang.org/x/text/transform", "\x03n\x84\x01X"},
|
||||
{"vendor/golang.org/x/text/unicode/bidi", "\x03\bi\x85\x01>\x16"},
|
||||
{"vendor/golang.org/x/text/unicode/norm", "j\n\x81\x01F\x12\x11"},
|
||||
{"weak", "\x97\x01\x97\x01!"},
|
||||
}
|
||||
|
||||
// bootstrap is the list of bootstrap packages extracted from cmd/dist.
|
||||
var bootstrap = map[string]bool{
|
||||
"cmp": true,
|
||||
"cmd/asm": true,
|
||||
"cmd/asm/internal/arch": true,
|
||||
"cmd/asm/internal/asm": true,
|
||||
"cmd/asm/internal/flags": true,
|
||||
"cmd/asm/internal/lex": true,
|
||||
"cmd/cgo": true,
|
||||
"cmd/compile": true,
|
||||
"cmd/compile/internal/abi": true,
|
||||
"cmd/compile/internal/abt": true,
|
||||
"cmd/compile/internal/amd64": true,
|
||||
"cmd/compile/internal/arm": true,
|
||||
"cmd/compile/internal/arm64": true,
|
||||
"cmd/compile/internal/base": true,
|
||||
"cmd/compile/internal/bitvec": true,
|
||||
"cmd/compile/internal/compare": true,
|
||||
"cmd/compile/internal/coverage": true,
|
||||
"cmd/compile/internal/deadlocals": true,
|
||||
"cmd/compile/internal/devirtualize": true,
|
||||
"cmd/compile/internal/dwarfgen": true,
|
||||
"cmd/compile/internal/escape": true,
|
||||
"cmd/compile/internal/gc": true,
|
||||
"cmd/compile/internal/importer": true,
|
||||
"cmd/compile/internal/inline": true,
|
||||
"cmd/compile/internal/inline/inlheur": true,
|
||||
"cmd/compile/internal/inline/interleaved": true,
|
||||
"cmd/compile/internal/ir": true,
|
||||
"cmd/compile/internal/liveness": true,
|
||||
"cmd/compile/internal/logopt": true,
|
||||
"cmd/compile/internal/loong64": true,
|
||||
"cmd/compile/internal/loopvar": true,
|
||||
"cmd/compile/internal/mips": true,
|
||||
"cmd/compile/internal/mips64": true,
|
||||
"cmd/compile/internal/noder": true,
|
||||
"cmd/compile/internal/objw": true,
|
||||
"cmd/compile/internal/pgoir": true,
|
||||
"cmd/compile/internal/pkginit": true,
|
||||
"cmd/compile/internal/ppc64": true,
|
||||
"cmd/compile/internal/rangefunc": true,
|
||||
"cmd/compile/internal/reflectdata": true,
|
||||
"cmd/compile/internal/riscv64": true,
|
||||
"cmd/compile/internal/rttype": true,
|
||||
"cmd/compile/internal/s390x": true,
|
||||
"cmd/compile/internal/ssa": true,
|
||||
"cmd/compile/internal/ssagen": true,
|
||||
"cmd/compile/internal/staticdata": true,
|
||||
"cmd/compile/internal/staticinit": true,
|
||||
"cmd/compile/internal/syntax": true,
|
||||
"cmd/compile/internal/test": true,
|
||||
"cmd/compile/internal/typebits": true,
|
||||
"cmd/compile/internal/typecheck": true,
|
||||
"cmd/compile/internal/types": true,
|
||||
"cmd/compile/internal/types2": true,
|
||||
"cmd/compile/internal/walk": true,
|
||||
"cmd/compile/internal/wasm": true,
|
||||
"cmd/compile/internal/x86": true,
|
||||
"cmd/internal/archive": true,
|
||||
"cmd/internal/bio": true,
|
||||
"cmd/internal/codesign": true,
|
||||
"cmd/internal/dwarf": true,
|
||||
"cmd/internal/edit": true,
|
||||
"cmd/internal/gcprog": true,
|
||||
"cmd/internal/goobj": true,
|
||||
"cmd/internal/hash": true,
|
||||
"cmd/internal/macho": true,
|
||||
"cmd/internal/obj": true,
|
||||
"cmd/internal/obj/arm": true,
|
||||
"cmd/internal/obj/arm64": true,
|
||||
"cmd/internal/obj/loong64": true,
|
||||
"cmd/internal/obj/mips": true,
|
||||
"cmd/internal/obj/ppc64": true,
|
||||
"cmd/internal/obj/riscv": true,
|
||||
"cmd/internal/obj/s390x": true,
|
||||
"cmd/internal/obj/wasm": true,
|
||||
"cmd/internal/obj/x86": true,
|
||||
"cmd/internal/objabi": true,
|
||||
"cmd/internal/par": true,
|
||||
"cmd/internal/pgo": true,
|
||||
"cmd/internal/pkgpath": true,
|
||||
"cmd/internal/quoted": true,
|
||||
"cmd/internal/src": true,
|
||||
"cmd/internal/sys": true,
|
||||
"cmd/internal/telemetry": true,
|
||||
"cmd/internal/telemetry/counter": true,
|
||||
"cmd/link": true,
|
||||
"cmd/link/internal/amd64": true,
|
||||
"cmd/link/internal/arm": true,
|
||||
"cmd/link/internal/arm64": true,
|
||||
"cmd/link/internal/benchmark": true,
|
||||
"cmd/link/internal/dwtest": true,
|
||||
"cmd/link/internal/ld": true,
|
||||
"cmd/link/internal/loadelf": true,
|
||||
"cmd/link/internal/loader": true,
|
||||
"cmd/link/internal/loadmacho": true,
|
||||
"cmd/link/internal/loadpe": true,
|
||||
"cmd/link/internal/loadxcoff": true,
|
||||
"cmd/link/internal/loong64": true,
|
||||
"cmd/link/internal/mips": true,
|
||||
"cmd/link/internal/mips64": true,
|
||||
"cmd/link/internal/ppc64": true,
|
||||
"cmd/link/internal/riscv64": true,
|
||||
"cmd/link/internal/s390x": true,
|
||||
"cmd/link/internal/sym": true,
|
||||
"cmd/link/internal/wasm": true,
|
||||
"cmd/link/internal/x86": true,
|
||||
"compress/flate": true,
|
||||
"compress/zlib": true,
|
||||
"container/heap": true,
|
||||
"debug/dwarf": true,
|
||||
"debug/elf": true,
|
||||
"debug/macho": true,
|
||||
"debug/pe": true,
|
||||
"go/build/constraint": true,
|
||||
"go/constant": true,
|
||||
"go/version": true,
|
||||
"internal/abi": true,
|
||||
"internal/coverage": true,
|
||||
"cmd/internal/cov/covcmd": true,
|
||||
"internal/bisect": true,
|
||||
"internal/buildcfg": true,
|
||||
"internal/exportdata": true,
|
||||
"internal/goarch": true,
|
||||
"internal/godebugs": true,
|
||||
"internal/goexperiment": true,
|
||||
"internal/goroot": true,
|
||||
"internal/gover": true,
|
||||
"internal/goversion": true,
|
||||
"internal/lazyregexp": true,
|
||||
"internal/pkgbits": true,
|
||||
"internal/platform": true,
|
||||
"internal/profile": true,
|
||||
"internal/race": true,
|
||||
"internal/runtime/gc": true,
|
||||
"internal/saferio": true,
|
||||
"internal/syscall/unix": true,
|
||||
"internal/types/errors": true,
|
||||
"internal/unsafeheader": true,
|
||||
"internal/xcoff": true,
|
||||
"internal/zstd": true,
|
||||
"math/bits": true,
|
||||
"sort": true,
|
||||
}
|
||||
|
||||
// BootstrapVersion is the minor version of Go used during toolchain
|
||||
// bootstrapping. Packages for which [IsBootstrapPackage] must not use
|
||||
// features of Go newer than this version.
|
||||
const BootstrapVersion = Version(24) // go1.24.6
|
||||
|
||||
+8
@@ -87,3 +87,11 @@ func find(pkg string) (int, bool) {
|
||||
return strings.Compare(p.name, n)
|
||||
})
|
||||
}
|
||||
|
||||
// IsBootstrapPackage reports whether pkg is one of the low-level
|
||||
// packages in the Go distribution that must compile with the older
|
||||
// language version specified by [BootstrapVersion] during toolchain
|
||||
// bootstrapping; see golang.org/s/go15bootstrap.
|
||||
func IsBootstrapPackage(pkg string) bool {
|
||||
return bootstrap[pkg]
|
||||
}
|
||||
|
||||
+37
-4
@@ -225,6 +225,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"(*Buffer).Grow", Method, 1, ""},
|
||||
{"(*Buffer).Len", Method, 0, ""},
|
||||
{"(*Buffer).Next", Method, 0, ""},
|
||||
{"(*Buffer).Peek", Method, 26, ""},
|
||||
{"(*Buffer).Read", Method, 0, ""},
|
||||
{"(*Buffer).ReadByte", Method, 0, ""},
|
||||
{"(*Buffer).ReadBytes", Method, 0, ""},
|
||||
@@ -1628,6 +1629,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"ResultNoRows", Var, 0, ""},
|
||||
{"Rows", Type, 0, ""},
|
||||
{"RowsAffected", Type, 0, ""},
|
||||
{"RowsColumnScanner", Type, 26, ""},
|
||||
{"RowsColumnTypeDatabaseTypeName", Type, 8, ""},
|
||||
{"RowsColumnTypeLength", Type, 8, ""},
|
||||
{"RowsColumnTypeNullable", Type, 8, ""},
|
||||
@@ -4953,6 +4955,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
},
|
||||
"errors": {
|
||||
{"As", Func, 13, "func(err error, target any) bool"},
|
||||
{"AsType", Func, 26, "func[E error](err error) (E, bool)"},
|
||||
{"ErrUnsupported", Var, 21, ""},
|
||||
{"Is", Func, 13, "func(err error, target error) bool"},
|
||||
{"Join", Func, 20, "func(errs ...error) error"},
|
||||
@@ -5090,7 +5093,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"Append", Func, 19, "func(b []byte, a ...any) []byte"},
|
||||
{"Appendf", Func, 19, "func(b []byte, format string, a ...any) []byte"},
|
||||
{"Appendln", Func, 19, "func(b []byte, a ...any) []byte"},
|
||||
{"Errorf", Func, 0, "func(format string, a ...any) error"},
|
||||
{"Errorf", Func, 0, "func(format string, a ...any) (err error)"},
|
||||
{"FormatString", Func, 20, "func(state State, verb rune) string"},
|
||||
{"Formatter", Type, 0, ""},
|
||||
{"Fprint", Func, 0, "func(w io.Writer, a ...any) (n int, err error)"},
|
||||
@@ -5155,6 +5158,9 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"(*DeclStmt).Pos", Method, 0, ""},
|
||||
{"(*DeferStmt).End", Method, 0, ""},
|
||||
{"(*DeferStmt).Pos", Method, 0, ""},
|
||||
{"(*Directive).End", Method, 26, ""},
|
||||
{"(*Directive).ParseArgs", Method, 26, ""},
|
||||
{"(*Directive).Pos", Method, 26, ""},
|
||||
{"(*Ellipsis).End", Method, 0, ""},
|
||||
{"(*Ellipsis).Pos", Method, 0, ""},
|
||||
{"(*EmptyStmt).End", Method, 0, ""},
|
||||
@@ -5320,6 +5326,15 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"DeferStmt", Type, 0, ""},
|
||||
{"DeferStmt.Call", Field, 0, ""},
|
||||
{"DeferStmt.Defer", Field, 0, ""},
|
||||
{"Directive", Type, 26, ""},
|
||||
{"Directive.Args", Field, 26, ""},
|
||||
{"Directive.ArgsPos", Field, 26, ""},
|
||||
{"Directive.Name", Field, 26, ""},
|
||||
{"Directive.Slash", Field, 26, ""},
|
||||
{"Directive.Tool", Field, 26, ""},
|
||||
{"DirectiveArg", Type, 26, ""},
|
||||
{"DirectiveArg.Arg", Field, 26, ""},
|
||||
{"DirectiveArg.Pos", Field, 26, ""},
|
||||
{"Ellipsis", Type, 0, ""},
|
||||
{"Ellipsis.Ellipsis", Field, 0, ""},
|
||||
{"Ellipsis.Elt", Field, 0, ""},
|
||||
@@ -5469,6 +5484,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"ParenExpr.Lparen", Field, 0, ""},
|
||||
{"ParenExpr.Rparen", Field, 0, ""},
|
||||
{"ParenExpr.X", Field, 0, ""},
|
||||
{"ParseDirective", Func, 26, "func(pos token.Pos, c string) (Directive, bool)"},
|
||||
{"Pkg", Const, 0, ""},
|
||||
{"Preorder", Func, 23, "func(root Node) iter.Seq[Node]"},
|
||||
{"PreorderStack", Func, 25, "func(root Node, stack []Node, f func(n Node, stack []Node) bool)"},
|
||||
@@ -7271,6 +7287,10 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"(*Logger).WarnContext", Method, 21, ""},
|
||||
{"(*Logger).With", Method, 21, ""},
|
||||
{"(*Logger).WithGroup", Method, 21, ""},
|
||||
{"(*MultiHandler).Enabled", Method, 26, ""},
|
||||
{"(*MultiHandler).Handle", Method, 26, ""},
|
||||
{"(*MultiHandler).WithAttrs", Method, 26, ""},
|
||||
{"(*MultiHandler).WithGroup", Method, 26, ""},
|
||||
{"(*Record).Add", Method, 21, ""},
|
||||
{"(*Record).AddAttrs", Method, 21, ""},
|
||||
{"(*TextHandler).Enabled", Method, 21, ""},
|
||||
@@ -7358,9 +7378,11 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"LogValuer", Type, 21, ""},
|
||||
{"Logger", Type, 21, ""},
|
||||
{"MessageKey", Const, 21, ""},
|
||||
{"MultiHandler", Type, 26, ""},
|
||||
{"New", Func, 21, "func(h Handler) *Logger"},
|
||||
{"NewJSONHandler", Func, 21, "func(w io.Writer, opts *HandlerOptions) *JSONHandler"},
|
||||
{"NewLogLogger", Func, 21, "func(h Handler, level Level) *log.Logger"},
|
||||
{"NewMultiHandler", Func, 26, "func(handlers ...Handler) *MultiHandler"},
|
||||
{"NewRecord", Func, 21, "func(t time.Time, level Level, msg string, pc uintptr) Record"},
|
||||
{"NewTextHandler", Func, 21, "func(w io.Writer, opts *HandlerOptions) *TextHandler"},
|
||||
{"Record", Type, 21, ""},
|
||||
@@ -7515,7 +7537,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"MinInt64", Const, 0, ""},
|
||||
{"MinInt8", Const, 0, ""},
|
||||
{"Mod", Func, 0, "func(x float64, y float64) float64"},
|
||||
{"Modf", Func, 0, "func(f float64) (int float64, frac float64)"},
|
||||
{"Modf", Func, 0, "func(f float64) (integer float64, fractional float64)"},
|
||||
{"NaN", Func, 0, "func() float64"},
|
||||
{"Nextafter", Func, 0, "func(x float64, y float64) (r float64)"},
|
||||
{"Nextafter32", Func, 4, "func(x float32, y float32) (r float32)"},
|
||||
@@ -7972,6 +7994,10 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"(*DNSError).Unwrap", Method, 23, ""},
|
||||
{"(*Dialer).Dial", Method, 1, ""},
|
||||
{"(*Dialer).DialContext", Method, 7, ""},
|
||||
{"(*Dialer).DialIP", Method, 26, ""},
|
||||
{"(*Dialer).DialTCP", Method, 26, ""},
|
||||
{"(*Dialer).DialUDP", Method, 26, ""},
|
||||
{"(*Dialer).DialUnix", Method, 26, ""},
|
||||
{"(*Dialer).MultipathTCP", Method, 21, ""},
|
||||
{"(*Dialer).SetMultipathTCP", Method, 21, ""},
|
||||
{"(*IP).UnmarshalText", Method, 2, ""},
|
||||
@@ -8457,6 +8483,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"HTTP2Config.PermitProhibitedCipherSuites", Field, 24, ""},
|
||||
{"HTTP2Config.PingTimeout", Field, 24, ""},
|
||||
{"HTTP2Config.SendPingTimeout", Field, 24, ""},
|
||||
{"HTTP2Config.StrictMaxConcurrentRequests", Field, 26, ""},
|
||||
{"HTTP2Config.WriteByteTimeout", Field, 24, ""},
|
||||
{"Handle", Func, 0, "func(pattern string, handler Handler)"},
|
||||
{"HandleFunc", Func, 0, "func(pattern string, handler func(ResponseWriter, *Request))"},
|
||||
@@ -8904,6 +8931,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"(Prefix).AppendText", Method, 24, ""},
|
||||
{"(Prefix).AppendTo", Method, 18, ""},
|
||||
{"(Prefix).Bits", Method, 18, ""},
|
||||
{"(Prefix).Compare", Method, 26, ""},
|
||||
{"(Prefix).Contains", Method, 18, ""},
|
||||
{"(Prefix).IsSingleIP", Method, 18, ""},
|
||||
{"(Prefix).IsValid", Method, 18, ""},
|
||||
@@ -9177,6 +9205,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"(*Process).Release", Method, 0, ""},
|
||||
{"(*Process).Signal", Method, 0, ""},
|
||||
{"(*Process).Wait", Method, 0, ""},
|
||||
{"(*Process).WithHandle", Method, 26, ""},
|
||||
{"(*ProcessState).ExitCode", Method, 12, ""},
|
||||
{"(*ProcessState).Exited", Method, 0, ""},
|
||||
{"(*ProcessState).Pid", Method, 0, ""},
|
||||
@@ -9234,6 +9263,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"ErrExist", Var, 0, ""},
|
||||
{"ErrInvalid", Var, 0, ""},
|
||||
{"ErrNoDeadline", Var, 10, ""},
|
||||
{"ErrNoHandle", Var, 26, ""},
|
||||
{"ErrNotExist", Var, 0, ""},
|
||||
{"ErrPermission", Var, 0, ""},
|
||||
{"ErrProcessDone", Var, 16, ""},
|
||||
@@ -9461,7 +9491,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"ListSeparator", Const, 0, ""},
|
||||
{"Localize", Func, 23, "func(path string) (string, error)"},
|
||||
{"Match", Func, 0, "func(pattern string, name string) (matched bool, err error)"},
|
||||
{"Rel", Func, 0, "func(basepath string, targpath string) (string, error)"},
|
||||
{"Rel", Func, 0, "func(basePath string, targPath string) (string, error)"},
|
||||
{"Separator", Const, 0, ""},
|
||||
{"SkipAll", Var, 20, ""},
|
||||
{"SkipDir", Var, 0, ""},
|
||||
@@ -9932,7 +9962,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"PanicNilError", Type, 21, ""},
|
||||
{"Pinner", Type, 21, ""},
|
||||
{"ReadMemStats", Func, 0, "func(m *MemStats)"},
|
||||
{"ReadTrace", Func, 5, "func() []byte"},
|
||||
{"ReadTrace", Func, 5, "func() (buf []byte)"},
|
||||
{"SetBlockProfileRate", Func, 1, "func(rate int)"},
|
||||
{"SetCPUProfileRate", Func, 0, "func(hz int)"},
|
||||
{"SetCgoTraceback", Func, 7, "func(version int, traceback unsafe.Pointer, context unsafe.Pointer, symbolizer unsafe.Pointer)"},
|
||||
@@ -16679,6 +16709,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"ValueOf", Func, 0, ""},
|
||||
},
|
||||
"testing": {
|
||||
{"(*B).ArtifactDir", Method, 26, ""},
|
||||
{"(*B).Attr", Method, 25, ""},
|
||||
{"(*B).Chdir", Method, 24, ""},
|
||||
{"(*B).Cleanup", Method, 14, ""},
|
||||
@@ -16713,6 +16744,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"(*B).StopTimer", Method, 0, ""},
|
||||
{"(*B).TempDir", Method, 15, ""},
|
||||
{"(*F).Add", Method, 18, ""},
|
||||
{"(*F).ArtifactDir", Method, 26, ""},
|
||||
{"(*F).Attr", Method, 25, ""},
|
||||
{"(*F).Chdir", Method, 24, ""},
|
||||
{"(*F).Cleanup", Method, 18, ""},
|
||||
@@ -16738,6 +16770,7 @@ var PackageSymbols = map[string][]Symbol{
|
||||
{"(*F).TempDir", Method, 18, ""},
|
||||
{"(*M).Run", Method, 4, ""},
|
||||
{"(*PB).Next", Method, 3, ""},
|
||||
{"(*T).ArtifactDir", Method, 26, ""},
|
||||
{"(*T).Attr", Method, 25, ""},
|
||||
{"(*T).Chdir", Method, 24, ""},
|
||||
{"(*T).Cleanup", Method, 14, ""},
|
||||
|
||||
+2
-4
@@ -160,8 +160,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
||||
// The term set of an interface is the intersection of the term sets of its
|
||||
// embedded types.
|
||||
tset.terms = allTermlist
|
||||
for i := 0; i < u.NumEmbeddeds(); i++ {
|
||||
embedded := u.EmbeddedType(i)
|
||||
for embedded := range u.EmbeddedTypes() {
|
||||
if _, ok := embedded.Underlying().(*types.TypeParam); ok {
|
||||
return nil, fmt.Errorf("invalid embedded type %T", embedded)
|
||||
}
|
||||
@@ -174,8 +173,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
||||
case *types.Union:
|
||||
// The term set of a union is the union of term sets of its terms.
|
||||
tset.terms = nil
|
||||
for i := 0; i < u.Len(); i++ {
|
||||
t := u.Term(i)
|
||||
for t := range u.Terms() {
|
||||
var terms termlist
|
||||
switch t.Type().Underlying().(type) {
|
||||
case *types.Interface:
|
||||
|
||||
+2
-2
@@ -35,8 +35,8 @@ func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T type
|
||||
|
||||
// Recursion over signatures of each method.
|
||||
tmset := msets.MethodSet(T)
|
||||
for i := 0; i < tmset.Len(); i++ {
|
||||
sig := tmset.At(i).Type().(*types.Signature)
|
||||
for method := range tmset.Methods() {
|
||||
sig := method.Type().(*types.Signature)
|
||||
// It is tempting to call visit(sig, false)
|
||||
// but, as noted in golang.org/cl/65450043,
|
||||
// the Signature.Recv field is ignored by
|
||||
|
||||
+49
-10
@@ -19,25 +19,46 @@ func NoEffects(info *types.Info, expr ast.Expr) bool {
|
||||
switch v := n.(type) {
|
||||
case nil, *ast.Ident, *ast.BasicLit, *ast.BinaryExpr, *ast.ParenExpr,
|
||||
*ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr, *ast.TypeAssertExpr,
|
||||
*ast.StarExpr, *ast.CompositeLit, *ast.ArrayType, *ast.StructType,
|
||||
*ast.MapType, *ast.InterfaceType, *ast.KeyValueExpr:
|
||||
// No effect
|
||||
*ast.StarExpr, *ast.CompositeLit,
|
||||
// non-expressions that may appear within expressions
|
||||
*ast.KeyValueExpr,
|
||||
*ast.FieldList,
|
||||
*ast.Field,
|
||||
*ast.Ellipsis,
|
||||
*ast.IndexListExpr:
|
||||
// No effect.
|
||||
|
||||
case *ast.ArrayType,
|
||||
*ast.StructType,
|
||||
*ast.ChanType,
|
||||
*ast.FuncType,
|
||||
*ast.MapType,
|
||||
*ast.InterfaceType:
|
||||
// Type syntax: no effects, recursively.
|
||||
// Prune descent.
|
||||
return false
|
||||
|
||||
case *ast.UnaryExpr:
|
||||
// Channel send <-ch has effects
|
||||
// Channel send <-ch has effects.
|
||||
if v.Op == token.ARROW {
|
||||
noEffects = false
|
||||
}
|
||||
case *ast.CallExpr:
|
||||
// Type conversion has no effects
|
||||
if !info.Types[v.Fun].IsType() {
|
||||
// TODO(adonovan): Add a case for built-in functions without side
|
||||
// effects (by using callsPureBuiltin from tools/internal/refactor/inline)
|
||||
|
||||
noEffects = false
|
||||
case *ast.CallExpr:
|
||||
// Type conversion has no effects.
|
||||
if !info.Types[v.Fun].IsType() {
|
||||
if CallsPureBuiltin(info, v) {
|
||||
// A call such as len(e) has no effects of its
|
||||
// own, though the subexpression e might.
|
||||
} else {
|
||||
noEffects = false
|
||||
}
|
||||
}
|
||||
|
||||
case *ast.FuncLit:
|
||||
// A FuncLit has no effects, but do not descend into it.
|
||||
return false
|
||||
|
||||
default:
|
||||
// All other expressions have effects
|
||||
noEffects = false
|
||||
@@ -47,3 +68,21 @@ func NoEffects(info *types.Info, expr ast.Expr) bool {
|
||||
})
|
||||
return noEffects
|
||||
}
|
||||
|
||||
// CallsPureBuiltin reports whether call is a call of a built-in
|
||||
// function that is a pure computation over its operands (analogous to
|
||||
// a + operator). Because it does not depend on program state, it may
|
||||
// be evaluated at any point--though not necessarily at multiple
|
||||
// points (consider new, make).
|
||||
func CallsPureBuiltin(info *types.Info, call *ast.CallExpr) bool {
|
||||
if id, ok := ast.Unparen(call.Fun).(*ast.Ident); ok {
|
||||
if b, ok := info.ObjectOf(id).(*types.Builtin); ok {
|
||||
switch b.Name() {
|
||||
case "len", "cap", "complex", "imag", "real", "make", "new", "max", "min":
|
||||
return true
|
||||
}
|
||||
// Not: append clear close copy delete panic print println recover
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+2
-2
@@ -48,7 +48,7 @@ func IsFunctionNamed(obj types.Object, pkgPath string, names ...string) bool {
|
||||
return ok &&
|
||||
IsPackageLevel(obj) &&
|
||||
f.Pkg().Path() == pkgPath &&
|
||||
f.Type().(*types.Signature).Recv() == nil &&
|
||||
f.Signature().Recv() == nil &&
|
||||
slices.Contains(names, f.Name())
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ func IsFunctionNamed(obj types.Object, pkgPath string, names ...string) bool {
|
||||
// which is important for the performance of syntax matching.
|
||||
func IsMethodNamed(obj types.Object, pkgPath string, typeName string, names ...string) bool {
|
||||
if fn, ok := obj.(*types.Func); ok {
|
||||
if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
|
||||
if recv := fn.Signature().Recv(); recv != nil {
|
||||
_, T := ReceiverNamed(recv)
|
||||
return T != nil &&
|
||||
IsTypeNamed(T, pkgPath, typeName) &&
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ import (
|
||||
// TODO(adonovan): this function ignores the effect of shadowing. It
|
||||
// should accept a [token.Pos] and a [types.Info] and compute only the
|
||||
// set of imports that are not shadowed at that point, analogous to
|
||||
// [analysisinternal.AddImport]. It could also compute (as a side
|
||||
// [analysis.AddImport]. It could also compute (as a side
|
||||
// effect) the set of additional imports required to ensure that there
|
||||
// is an accessible import for each necessary package, making it
|
||||
// converge even more closely with AddImport.
|
||||
|
||||
+11
-28
@@ -2,39 +2,22 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typesinternal
|
||||
//go:build go1.25
|
||||
|
||||
// TODO(adonovan): when CL 645115 lands, define the go1.25 version of
|
||||
// this API that actually does something.
|
||||
package typesinternal
|
||||
|
||||
import "go/types"
|
||||
|
||||
type VarKind uint8
|
||||
type VarKind = types.VarKind
|
||||
|
||||
const (
|
||||
_ VarKind = iota // (not meaningful)
|
||||
PackageVar // a package-level variable
|
||||
LocalVar // a local variable
|
||||
RecvVar // a method receiver variable
|
||||
ParamVar // a function parameter variable
|
||||
ResultVar // a function result variable
|
||||
FieldVar // a struct field
|
||||
PackageVar = types.PackageVar
|
||||
LocalVar = types.LocalVar
|
||||
RecvVar = types.RecvVar
|
||||
ParamVar = types.ParamVar
|
||||
ResultVar = types.ResultVar
|
||||
FieldVar = types.FieldVar
|
||||
)
|
||||
|
||||
func (kind VarKind) String() string {
|
||||
return [...]string{
|
||||
0: "VarKind(0)",
|
||||
PackageVar: "PackageVar",
|
||||
LocalVar: "LocalVar",
|
||||
RecvVar: "RecvVar",
|
||||
ParamVar: "ParamVar",
|
||||
ResultVar: "ResultVar",
|
||||
FieldVar: "FieldVar",
|
||||
}[kind]
|
||||
}
|
||||
|
||||
// GetVarKind returns an invalid VarKind.
|
||||
func GetVarKind(v *types.Var) VarKind { return 0 }
|
||||
|
||||
// SetVarKind has no effect.
|
||||
func SetVarKind(v *types.Var, kind VarKind) {}
|
||||
func GetVarKind(v *types.Var) VarKind { return v.Kind() }
|
||||
func SetVarKind(v *types.Var, kind VarKind) { v.SetKind(kind) }
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// 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.
|
||||
|
||||
//go:build !go1.25
|
||||
|
||||
package typesinternal
|
||||
|
||||
import "go/types"
|
||||
|
||||
type VarKind uint8
|
||||
|
||||
const (
|
||||
_ VarKind = iota // (not meaningful)
|
||||
PackageVar // a package-level variable
|
||||
LocalVar // a local variable
|
||||
RecvVar // a method receiver variable
|
||||
ParamVar // a function parameter variable
|
||||
ResultVar // a function result variable
|
||||
FieldVar // a struct field
|
||||
)
|
||||
|
||||
func (kind VarKind) String() string {
|
||||
return [...]string{
|
||||
0: "VarKind(0)",
|
||||
PackageVar: "PackageVar",
|
||||
LocalVar: "LocalVar",
|
||||
RecvVar: "RecvVar",
|
||||
ParamVar: "ParamVar",
|
||||
ResultVar: "ResultVar",
|
||||
FieldVar: "FieldVar",
|
||||
}[kind]
|
||||
}
|
||||
|
||||
// GetVarKind returns an invalid VarKind.
|
||||
func GetVarKind(v *types.Var) VarKind { return 0 }
|
||||
|
||||
// SetVarKind has no effect.
|
||||
func SetVarKind(v *types.Var, kind VarKind) {}
|
||||
+7
-7
@@ -258,12 +258,12 @@ func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
|
||||
|
||||
case *types.Signature:
|
||||
var params []*ast.Field
|
||||
for i := 0; i < t.Params().Len(); i++ {
|
||||
for v := range t.Params().Variables() {
|
||||
params = append(params, &ast.Field{
|
||||
Type: TypeExpr(t.Params().At(i).Type(), qual),
|
||||
Type: TypeExpr(v.Type(), qual),
|
||||
Names: []*ast.Ident{
|
||||
{
|
||||
Name: t.Params().At(i).Name(),
|
||||
Name: v.Name(),
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -273,9 +273,9 @@ func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
|
||||
last.Type = &ast.Ellipsis{Elt: last.Type.(*ast.ArrayType).Elt}
|
||||
}
|
||||
var returns []*ast.Field
|
||||
for i := 0; i < t.Results().Len(); i++ {
|
||||
for v := range t.Results().Variables() {
|
||||
returns = append(returns, &ast.Field{
|
||||
Type: TypeExpr(t.Results().At(i).Type(), qual),
|
||||
Type: TypeExpr(v.Type(), qual),
|
||||
})
|
||||
}
|
||||
return &ast.FuncType{
|
||||
@@ -315,8 +315,8 @@ func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
|
||||
if hasTypeArgs, ok := t.(interface{ TypeArgs() *types.TypeList }); ok {
|
||||
if typeArgs := hasTypeArgs.TypeArgs(); typeArgs != nil && typeArgs.Len() > 0 {
|
||||
var indices []ast.Expr
|
||||
for i := range typeArgs.Len() {
|
||||
indices = append(indices, TypeExpr(typeArgs.At(i), qual))
|
||||
for t0 := range typeArgs.Types() {
|
||||
indices = append(indices, TypeExpr(t0, qual))
|
||||
}
|
||||
expr = &ast.IndexListExpr{
|
||||
X: expr,
|
||||
|
||||
+5
-1
@@ -7,13 +7,17 @@ package versions
|
||||
// This file contains predicates for working with file versions to
|
||||
// decide when a tool should consider a language feature enabled.
|
||||
|
||||
// GoVersions that features in x/tools can be gated to.
|
||||
// named constants, to avoid misspelling
|
||||
const (
|
||||
Go1_18 = "go1.18"
|
||||
Go1_19 = "go1.19"
|
||||
Go1_20 = "go1.20"
|
||||
Go1_21 = "go1.21"
|
||||
Go1_22 = "go1.22"
|
||||
Go1_23 = "go1.23"
|
||||
Go1_24 = "go1.24"
|
||||
Go1_25 = "go1.25"
|
||||
Go1_26 = "go1.26"
|
||||
)
|
||||
|
||||
// Future is an invalid unknown Go version sometime in the future.
|
||||
|
||||
Vendored
+9
-9
@@ -41,7 +41,7 @@ github.com/jedisct1/dlog
|
||||
# github.com/jedisct1/go-clocksmith v0.0.0-20250224222044-e151f21a353a
|
||||
## explicit
|
||||
github.com/jedisct1/go-clocksmith
|
||||
# github.com/jedisct1/go-dnsstamps v0.0.0-20240423203910-07a0735c7774
|
||||
# github.com/jedisct1/go-dnsstamps v0.0.0-20251112173516-191fc465df31
|
||||
## explicit; go 1.18
|
||||
github.com/jedisct1/go-dnsstamps
|
||||
# github.com/jedisct1/go-hpke-compact v0.0.0-20241212093903-5caa4621366f
|
||||
@@ -83,10 +83,10 @@ github.com/powerman/check
|
||||
# github.com/powerman/deepequal v0.1.0
|
||||
## explicit; go 1.16
|
||||
github.com/powerman/deepequal
|
||||
# github.com/quic-go/qpack v0.5.1
|
||||
## explicit; go 1.22
|
||||
# github.com/quic-go/qpack v0.6.0
|
||||
## explicit; go 1.24
|
||||
github.com/quic-go/qpack
|
||||
# github.com/quic-go/quic-go v0.56.0
|
||||
# github.com/quic-go/quic-go v0.57.1
|
||||
## explicit; go 1.24
|
||||
github.com/quic-go/quic-go
|
||||
github.com/quic-go/quic-go/http3
|
||||
@@ -110,7 +110,7 @@ github.com/quic-go/quic-go/quicvarint
|
||||
## explicit; go 1.18
|
||||
github.com/smartystreets/goconvey/convey/gotest
|
||||
github.com/smartystreets/goconvey/convey/reporting
|
||||
# golang.org/x/crypto v0.43.0
|
||||
# golang.org/x/crypto v0.45.0
|
||||
## explicit; go 1.24.0
|
||||
golang.org/x/crypto/blake2b
|
||||
golang.org/x/crypto/chacha20
|
||||
@@ -124,10 +124,10 @@ golang.org/x/crypto/nacl/box
|
||||
golang.org/x/crypto/nacl/secretbox
|
||||
golang.org/x/crypto/poly1305
|
||||
golang.org/x/crypto/salsa20/salsa
|
||||
# golang.org/x/mod v0.29.0
|
||||
# golang.org/x/mod v0.30.0
|
||||
## explicit; go 1.24.0
|
||||
golang.org/x/mod/semver
|
||||
# golang.org/x/net v0.46.0
|
||||
# golang.org/x/net v0.47.0
|
||||
## explicit; go 1.24.0
|
||||
golang.org/x/net/bpf
|
||||
golang.org/x/net/http/httpguts
|
||||
@@ -153,13 +153,13 @@ golang.org/x/sys/windows/registry
|
||||
golang.org/x/sys/windows/svc
|
||||
golang.org/x/sys/windows/svc/eventlog
|
||||
golang.org/x/sys/windows/svc/mgr
|
||||
# golang.org/x/text v0.30.0
|
||||
# golang.org/x/text v0.31.0
|
||||
## explicit; go 1.24.0
|
||||
golang.org/x/text/secure/bidirule
|
||||
golang.org/x/text/transform
|
||||
golang.org/x/text/unicode/bidi
|
||||
golang.org/x/text/unicode/norm
|
||||
# golang.org/x/tools v0.38.0
|
||||
# golang.org/x/tools v0.39.0
|
||||
## explicit; go 1.24.0
|
||||
golang.org/x/tools/go/ast/edge
|
||||
golang.org/x/tools/go/ast/inspector
|
||||
|
||||
Reference in New Issue
Block a user