aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatie Hockman <katie@golang.org>2021-06-07 12:31:32 -0400
committerKatie Hockman <katie@golang.org>2021-06-07 12:31:32 -0400
commit9647f89f2ac2a64acb502c594fc747f206842a86 (patch)
treee48b92008454a8aa6ffd1f4709578ac5b921a6a4
parent03a15201e7e0f11c8f4021a181071040a04dc375 (diff)
parentab7f8297f9734b24a43a942930258cda411f16a3 (diff)
downloadgo-9647f89f2ac2a64acb502c594fc747f206842a86.tar.gz
go-9647f89f2ac2a64acb502c594fc747f206842a86.zip
[dev.boringcrypto.go1.15] all: merge go1.15.13 into dev.boringcrypto.go1.15
Change-Id: I90b28aa5938fe0bddf11201c6bdb851de5c654c3
-rw-r--r--src/archive/zip/reader.go10
-rw-r--r--src/archive/zip/reader_test.go59
-rw-r--r--src/cmd/go/internal/modcmd/tidy.go1
-rw-r--r--src/cmd/go/internal/modload/load.go27
-rw-r--r--src/cmd/go/testdata/script/mod_readonly.txt6
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_too_new.txt31
-rw-r--r--src/cmd/link/internal/ld/elf.go2
-rw-r--r--src/cmd/link/internal/ld/macho.go2
-rw-r--r--src/cmd/link/internal/ppc64/asm.go14
-rw-r--r--src/math/big/arith_s390x.s192
-rw-r--r--src/math/big/arith_test.go65
-rw-r--r--src/math/big/ratconv.go15
-rw-r--r--src/math/big/ratconv_test.go25
-rw-r--r--src/net/dnsclient_unix_test.go158
-rw-r--r--src/net/http/httputil/reverseproxy.go22
-rw-r--r--src/net/http/httputil/reverseproxy_test.go63
-rw-r--r--src/net/http/transport_test.go8
-rw-r--r--src/net/lookup.go111
18 files changed, 564 insertions, 247 deletions
diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go
index 13ff9ddcf4..2d5151af3d 100644
--- a/src/archive/zip/reader.go
+++ b/src/archive/zip/reader.go
@@ -84,7 +84,15 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
return err
}
z.r = r
- z.File = make([]*File, 0, end.directoryRecords)
+ // Since the number of directory records is not validated, it is not
+ // safe to preallocate z.File without first checking that the specified
+ // number of files is reasonable, since a malformed archive may
+ // indicate it contains up to 1 << 128 - 1 files. Since each file has a
+ // header which will be _at least_ 30 bytes we can safely preallocate
+ // if (data size / 30) >= end.directoryRecords.
+ if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
+ z.File = make([]*File, 0, end.directoryRecords)
+ }
z.Comment = end.comment
rs := io.NewSectionReader(r, 0, size)
if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go
index adca87a8b3..6f67d2e4a9 100644
--- a/src/archive/zip/reader_test.go
+++ b/src/archive/zip/reader_test.go
@@ -1070,3 +1070,62 @@ func TestIssue12449(t *testing.T) {
t.Errorf("Error reading the archive: %v", err)
}
}
+
+func TestCVE202133196(t *testing.T) {
+ // Archive that indicates it has 1 << 128 -1 files,
+ // this would previously cause a panic due to attempting
+ // to allocate a slice with 1 << 128 -1 elements.
+ data := []byte{
+ 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00,
+ 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20,
+ 0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
+ 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
+ 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
+ 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0x00,
+ }
+ _, err := NewReader(bytes.NewReader(data), int64(len(data)))
+ if err != ErrFormat {
+ t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
+ }
+
+ // Also check that an archive containing a handful of empty
+ // files doesn't cause an issue
+ b := bytes.NewBuffer(nil)
+ w := NewWriter(b)
+ for i := 0; i < 5; i++ {
+ _, err := w.Create("")
+ if err != nil {
+ t.Fatalf("Writer.Create failed: %s", err)
+ }
+ }
+ if err := w.Close(); err != nil {
+ t.Fatalf("Writer.Close failed: %s", err)
+ }
+ r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
+ if err != nil {
+ t.Fatalf("NewReader failed: %s", err)
+ }
+ if len(r.File) != 5 {
+ t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
+ }
+}
diff --git a/src/cmd/go/internal/modcmd/tidy.go b/src/cmd/go/internal/modcmd/tidy.go
index 5ff847485c..71e1eda44a 100644
--- a/src/cmd/go/internal/modcmd/tidy.go
+++ b/src/cmd/go/internal/modcmd/tidy.go
@@ -43,6 +43,7 @@ func runTidy(cmd *base.Command, args []string) {
}
modload.SilenceMissingStdImports = true
+ modload.CheckTidyVersion()
modload.LoadALL()
modload.TidyBuildList()
modTidyGoSum() // updates memory copy; WriteGoMod on next line flushes it out
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index e5ea1a6c23..0dea6ee636 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -24,7 +24,9 @@ import (
"sort"
"strings"
+ "golang.org/x/mod/modfile"
"golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
)
// buildList is the list of modules to use for building packages.
@@ -478,6 +480,31 @@ func SetBuildList(list []module.Version) {
buildList = append([]module.Version{}, list...)
}
+// CheckTidyVersion reports an error to stderr if the Go version indicated by
+// the go.mod file is not supported by this version of the 'go' command.
+//
+// If allowError is false, such an error terminates the program.
+func CheckTidyVersion() {
+ InitMod()
+ mf := ModFile()
+ if mf.Go == nil || mf.Go.Version == "" {
+ return
+ }
+ goVersionV := "v" + mf.Go.Version
+
+ tags := build.Default.ReleaseTags
+ maxGo := tags[len(tags)-1]
+ if !strings.HasPrefix(maxGo, "go") || !modfile.GoVersionRE.MatchString(maxGo[2:]) {
+ base.Fatalf("go: unrecognized go version %q", maxGo)
+ }
+ max := maxGo[2:]
+
+ if semver.Compare(goVersionV, "v"+max) > 0 {
+ have := goVersionV[1:]
+ base.Fatalf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", have, max)
+ }
+}
+
// TidyBuildList trims the build list to the minimal requirements needed to
// retain the same versions of all packages from the preceding Load* or
// ImportPaths* call.
diff --git a/src/cmd/go/testdata/script/mod_readonly.txt b/src/cmd/go/testdata/script/mod_readonly.txt
index ac581264f1..a5d49bc771 100644
--- a/src/cmd/go/testdata/script/mod_readonly.txt
+++ b/src/cmd/go/testdata/script/mod_readonly.txt
@@ -64,7 +64,7 @@ go list all
-- go.mod --
module m
-go 1.20
+go 1.15
-- x.go --
package x
@@ -79,7 +79,7 @@ require (
-- go.mod.redundant --
module m
-go 1.20
+go 1.15
require (
rsc.io/quote v1.5.2
@@ -89,7 +89,7 @@ require (
-- go.mod.indirect --
module m
-go 1.20
+go 1.15
require (
rsc.io/quote v1.5.2 // indirect
diff --git a/src/cmd/go/testdata/script/mod_tidy_too_new.txt b/src/cmd/go/testdata/script/mod_tidy_too_new.txt
new file mode 100644
index 0000000000..8a73c28cbb
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_too_new.txt
@@ -0,0 +1,31 @@
+# https://golang.org/issue/46142: 'go mod tidy' should error out if the version
+# in the go.mod file is newer than the most recent supported version.
+
+cp go.mod go.mod.orig
+
+
+# If the go.mod file specifies an unsupported Go version, 'go mod tidy' should
+# refuse to edit it: we don't know what a tidy go.mod file for that version
+# would look like.
+
+! go mod tidy
+stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$'
+cmp go.mod go.mod.orig
+
+
+-- go.mod --
+module example.net/from/the/future
+
+go 2000.0
+
+replace example.net/m v0.0.0 => ./m
+-- x.go --
+package x
+
+import "example.net/m"
+-- m/go.mod --
+module example.net/m
+
+go 1.17
+-- m/m.go --
+package m
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 78298beafe..36ec4035c3 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -1400,7 +1400,7 @@ func elfrelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
}
ldr := ctxt.loader
- eaddr := int32(sect.Vaddr + sect.Length)
+ eaddr := sect.Vaddr + sect.Length
for _, s := range syms {
if !s.Attr.Reachable() {
continue
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index 5548b8c666..df016f3d43 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -1044,7 +1044,7 @@ func machorelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
}
}
- eaddr := int32(sect.Vaddr + sect.Length)
+ eaddr := sect.Vaddr + sect.Length
for _, s := range syms {
if !s.Attr.Reachable() {
continue
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index a3ecd43f89..8b0f15141c 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -658,6 +658,16 @@ func archrelocaddr(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Sy
return int64(o2)<<32 | int64(o1)
}
+// Determine if the code was compiled so that the TOC register R2 is initialized and maintained
+func r2Valid(ctxt *ld.Link) bool {
+ switch ctxt.BuildMode {
+ case ld.BuildModeCArchive, ld.BuildModeCShared, ld.BuildModePIE, ld.BuildModeShared, ld.BuildModePlugin:
+ return true
+ }
+ // -linkshared option
+ return ctxt.IsSharedGoLink()
+}
+
// resolve direct jump relocation r in s, and add trampoline if necessary
func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
@@ -665,7 +675,7 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
// For internal linking, trampolines are always created for long calls.
// For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in
// r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created.
- if ctxt.IsExternal() && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) {
+ if ctxt.IsExternal() && r2Valid(ctxt) {
// No trampolines needed since r2 contains the TOC
return
}
@@ -719,7 +729,7 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
}
}
if ldr.SymType(tramp) == 0 {
- if ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE {
+ if r2Valid(ctxt) {
// Should have returned for above cases
ctxt.Errorf(s, "unexpected trampoline for shared or dynamic linking")
} else {
diff --git a/src/math/big/arith_s390x.s b/src/math/big/arith_s390x.s
index 4891768111..153c42679c 100644
--- a/src/math/big/arith_s390x.s
+++ b/src/math/big/arith_s390x.s
@@ -702,199 +702,11 @@ returnC:
// func shlVU(z, x []Word, s uint) (c Word)
TEXT ·shlVU(SB), NOSPLIT, $0
- MOVD z_len+8(FP), R5
- MOVD $0, R0
- SUB $1, R5 // n--
- BLT X8b // n < 0 (n <= 0)
-
- // n > 0
- MOVD s+48(FP), R4
- CMPBEQ R0, R4, Z80 // handle 0 case beq
- MOVD $64, R6
- CMPBEQ R6, R4, Z864 // handle 64 case beq
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
- SUB R4, R6, R7
- MOVD (R8)(R5*1), R10 // w1 = x[i-1]
- SRD R7, R10, R3
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E8
-
- // i < n-1
-L8:
- MOVD R10, R3 // w = w1
- MOVD -8(R8)(R5*1), R10 // w1 = x[i+1]
-
- SLD R4, R3 // w<<s | w1>>ŝ
- SRD R7, R10, R6
- OR R6, R3
- MOVD R3, (R2)(R5*1) // z[i] = w<<s | w1>>ŝ
- SUB $8, R5 // i--
-
-E8:
- CMPBGT R5, R0, L8 // i < n-1
-
- // i >= n-1
-X8a:
- SLD R4, R10 // w1<<s
- MOVD R10, (R2) // z[0] = w1<<s
- RET
-
-X8b:
- MOVD R0, c+56(FP)
- RET
-
-Z80:
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
-
- MOVD (R8), R10
- MOVD $0, R3
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E8Z
-
- // i < n-1
-L8Z:
- MOVD R10, R3
- MOVD 8(R8)(R1*1), R10
-
- MOVD R3, (R2)(R1*1)
- ADD $8, R1
-
-E8Z:
- CMPBLT R1, R5, L8Z
-
- // i >= n-1
- MOVD R10, (R2)(R5*1)
- RET
-
-Z864:
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
- MOVD (R8)(R5*1), R3 // w1 = x[n-1]
- MOVD R3, c+56(FP) // z[i] = x[n-1]
-
- BR E864
-
- // i < n-1
-L864:
- MOVD -8(R8)(R5*1), R3
-
- MOVD R3, (R2)(R5*1) // z[i] = x[n-1]
- SUB $8, R5 // i--
-
-E864:
- CMPBGT R5, R0, L864 // i < n-1
-
- MOVD R0, (R2) // z[n-1] = 0
- RET
+ BR ·shlVU_g(SB)
-// CX = R4, r8 = r8, r10 = r2 , r11 = r5, DX = r3, AX = r10 , BX = R1 , 64-count = r7 (R0 set to 0) temp = R6
// func shrVU(z, x []Word, s uint) (c Word)
TEXT ·shrVU(SB), NOSPLIT, $0
- MOVD z_len+8(FP), R5
- MOVD $0, R0
- SUB $1, R5 // n--
- BLT X9b // n < 0 (n <= 0)
-
- // n > 0
- MOVD s+48(FP), R4
- CMPBEQ R0, R4, ZB0 // handle 0 case beq
- MOVD $64, R6
- CMPBEQ R6, R4, ZB64 // handle 64 case beq
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
- SUB R4, R6, R7
- MOVD (R8), R10 // w1 = x[0]
- SLD R7, R10, R3
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E9
-
- // i < n-1
-L9:
- MOVD R10, R3 // w = w1
- MOVD 8(R8)(R1*1), R10 // w1 = x[i+1]
-
- SRD R4, R3 // w>>s | w1<<s
- SLD R7, R10, R6
- OR R6, R3
- MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<<s
- ADD $8, R1 // i++
-
-E9:
- CMPBLT R1, R5, L9 // i < n-1
-
- // i >= n-1
-X9a:
- SRD R4, R10 // w1>>s
- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s
- RET
-
-X9b:
- MOVD R0, c+56(FP)
- RET
-
-ZB0:
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
-
- MOVD (R8), R10 // w1 = x[0]
- MOVD $0, R3 // R10 << 64
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E9Z
-
- // i < n-1
-L9Z:
- MOVD R10, R3 // w = w1
- MOVD 8(R8)(R1*1), R10 // w1 = x[i+1]
-
- MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<<s
- ADD $8, R1 // i++
-
-E9Z:
- CMPBLT R1, R5, L9Z // i < n-1
-
- // i >= n-1
- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s
- RET
-
-ZB64:
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
- MOVD (R8), R3 // w1 = x[0]
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E964
-
- // i < n-1
-L964:
- MOVD 8(R8)(R1*1), R3 // w1 = x[i+1]
-
- MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<<s
- ADD $8, R1 // i++
-
-E964:
- CMPBLT R1, R5, L964 // i < n-1
-
- // i >= n-1
- MOVD $0, R10 // w1>>s
- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s
- RET
+ BR ·shrVU_g(SB)
// CX = R4, r8 = r8, r9=r9, r10 = r2 , r11 = r5, DX = r3, AX = r6 , BX = R1 , (R0 set to 0) + use R11 + use R7 for i
// func mulAddVWW(z, x []Word, y, r Word) (c Word)
diff --git a/src/math/big/arith_test.go b/src/math/big/arith_test.go
index 05136f1895..fbbaa0e122 100644
--- a/src/math/big/arith_test.go
+++ b/src/math/big/arith_test.go
@@ -224,13 +224,36 @@ type argVU struct {
m string // message.
}
+var argshlVUIn = []Word{1, 2, 4, 8, 16, 32, 64, 0, 0, 0}
+var argshlVUr0 = []Word{1, 2, 4, 8, 16, 32, 64}
+var argshlVUr1 = []Word{2, 4, 8, 16, 32, 64, 128}
+var argshlVUrWm1 = []Word{1 << (_W - 1), 0, 1, 2, 4, 8, 16}
+
var argshlVU = []argVU{
// test cases for shlVU
{[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0}, 7, 0, 0, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "complete overlap of shlVU"},
{[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0}, 7, 0, 3, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "partial overlap by half of shlVU"},
{[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0, 0, 0, 0}, 7, 0, 6, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "partial overlap by 1 Word of shlVU"},
{[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0, 0, 0, 0, 0}, 7, 0, 7, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "no overlap of shlVU"},
-}
+ // additional test cases with shift values of 0, 1 and (_W-1)
+ {argshlVUIn, 7, 0, 0, 0, argshlVUr0, 0, "complete overlap of shlVU and shift of 0"},
+ {argshlVUIn, 7, 0, 0, 1, argshlVUr1, 0, "complete overlap of shlVU and shift of 1"},
+ {argshlVUIn, 7, 0, 0, _W - 1, argshlVUrWm1, 32, "complete overlap of shlVU and shift of _W - 1"},
+ {argshlVUIn, 7, 0, 1, 0, argshlVUr0, 0, "partial overlap by 6 Words of shlVU and shift of 0"},
+ {argshlVUIn, 7, 0, 1, 1, argshlVUr1, 0, "partial overlap by 6 Words of shlVU and shift of 1"},
+ {argshlVUIn, 7, 0, 1, _W - 1, argshlVUrWm1, 32, "partial overlap by 6 Words of shlVU and shift of _W - 1"},
+ {argshlVUIn, 7, 0, 2, 0, argshlVUr0, 0, "partial overlap by 5 Words of shlVU and shift of 0"},
+ {argshlVUIn, 7, 0, 2, 1, argshlVUr1, 0, "partial overlap by 5 Words of shlVU and shift of 1"},
+ {argshlVUIn, 7, 0, 2, _W - 1, argshlVUrWm1, 32, "partial overlap by 5 Words of shlVU abd shift of _W - 1"},
+ {argshlVUIn, 7, 0, 3, 0, argshlVUr0, 0, "partial overlap by 4 Words of shlVU and shift of 0"},
+ {argshlVUIn, 7, 0, 3, 1, argshlVUr1, 0, "partial overlap by 4 Words of shlVU and shift of 1"},
+ {argshlVUIn, 7, 0, 3, _W - 1, argshlVUrWm1, 32, "partial overlap by 4 Words of shlVU and shift of _W - 1"},
+}
+
+var argshrVUIn = []Word{0, 0, 0, 1, 2, 4, 8, 16, 32, 64}
+var argshrVUr0 = []Word{1, 2, 4, 8, 16, 32, 64}
+var argshrVUr1 = []Word{0, 1, 2, 4, 8, 16, 32}
+var argshrVUrWm1 = []Word{4, 8, 16, 32, 64, 128, 0}
var argshrVU = []argVU{
// test cases for shrVU
@@ -238,23 +261,36 @@ var argshrVU = []argVU{
{[]Word{0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 4, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "partial overlap by half of shrVU"},
{[]Word{0, 0, 0, 0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 7, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "partial overlap by 1 Word of shrVU"},
{[]Word{0, 0, 0, 0, 0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 8, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "no overlap of shrVU"},
+ // additional test cases with shift values of 0, 1 and (_W-1)
+ {argshrVUIn, 7, 3, 3, 0, argshrVUr0, 0, "complete overlap of shrVU and shift of 0"},
+ {argshrVUIn, 7, 3, 3, 1, argshrVUr1, 1 << (_W - 1), "complete overlap of shrVU and shift of 1"},
+ {argshrVUIn, 7, 3, 3, _W - 1, argshrVUrWm1, 2, "complete overlap of shrVU and shift of _W - 1"},
+ {argshrVUIn, 7, 3, 2, 0, argshrVUr0, 0, "partial overlap by 6 Words of shrVU and shift of 0"},
+ {argshrVUIn, 7, 3, 2, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 6 Words of shrVU and shift of 1"},
+ {argshrVUIn, 7, 3, 2, _W - 1, argshrVUrWm1, 2, "partial overlap by 6 Words of shrVU and shift of _W - 1"},
+ {argshrVUIn, 7, 3, 1, 0, argshrVUr0, 0, "partial overlap by 5 Words of shrVU and shift of 0"},
+ {argshrVUIn, 7, 3, 1, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 5 Words of shrVU and shift of 1"},
+ {argshrVUIn, 7, 3, 1, _W - 1, argshrVUrWm1, 2, "partial overlap by 5 Words of shrVU and shift of _W - 1"},
+ {argshrVUIn, 7, 3, 0, 0, argshrVUr0, 0, "partial overlap by 4 Words of shrVU and shift of 0"},
+ {argshrVUIn, 7, 3, 0, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 4 Words of shrVU and shift of 1"},
+ {argshrVUIn, 7, 3, 0, _W - 1, argshrVUrWm1, 2, "partial overlap by 4 Words of shrVU and shift of _W - 1"},
}
func testShiftFunc(t *testing.T, f func(z, x []Word, s uint) Word, a argVU) {
- // save a.d for error message, or it will be overwritten.
+ // work on copy of a.d to preserve the original data.
b := make([]Word, len(a.d))
copy(b, a.d)
- z := a.d[a.zp : a.zp+a.l]
- x := a.d[a.xp : a.xp+a.l]
+ z := b[a.zp : a.zp+a.l]
+ x := b[a.xp : a.xp+a.l]
c := f(z, x, a.s)
for i, zi := range z {
if zi != a.r[i] {
- t.Errorf("d := %v, %s(d[%d:%d], d[%d:%d], %d)\n\tgot z[%d] = %#x; want %#x", b, a.m, a.zp, a.zp+a.l, a.xp, a.xp+a.l, a.s, i, zi, a.r[i])
+ t.Errorf("d := %v, %s(d[%d:%d], d[%d:%d], %d)\n\tgot z[%d] = %#x; want %#x", a.d, a.m, a.zp, a.zp+a.l, a.xp, a.xp+a.l, a.s, i, zi, a.r[i])
break
}
}
if c != a.c {
- t.Errorf("d := %v, %s(d[%d:%d], d[%d:%d], %d)\n\tgot c = %#x; want %#x", b, a.m, a.zp, a.zp+a.l, a.xp, a.xp+a.l, a.s, c, a.c)
+ t.Errorf("d := %v, %s(d[%d:%d], d[%d:%d], %d)\n\tgot c = %#x; want %#x", a.d, a.m, a.zp, a.zp+a.l, a.xp, a.xp+a.l, a.s, c, a.c)
}
}
@@ -274,11 +310,24 @@ func TestIssue31084(t *testing.T) {
// compute 10^n via 5^n << n.
const n = 165
p := nat(nil).expNN(nat{5}, nat{n}, nil)
- p = p.shl(p, uint(n))
+ p = p.shl(p, n)
got := string(p.utoa(10))
want := "1" + strings.Repeat("0", n)
if got != want {
- t.Errorf("shl(%v, %v)\n\tgot %s; want %s\n", p, uint(n), got, want)
+ t.Errorf("shl(%v, %v)\n\tgot %s\n\twant %s", p, n, got, want)
+ }
+}
+
+const issue42838Value = "159309191113245227702888039776771180559110455519261878607388585338616290151305816094308987472018268594098344692611135542392730712890625"
+
+func TestIssue42838(t *testing.T) {
+ const s = 192
+ z, _, _, _ := nat(nil).scan(strings.NewReader(issue42838Value), 0, false)
+ z = z.shl(z, s)
+ got := string(z.utoa(10))
+ want := "1" + strings.Repeat("0", s)
+ if got != want {
+ t.Errorf("shl(%v, %v)\n\tgot %s\n\twant %s", z, s, got, want)
}
}
diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go
index 941139e72d..ac3c8bd11f 100644
--- a/src/math/big/ratconv.go
+++ b/src/math/big/ratconv.go
@@ -51,7 +51,8 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
// An optional base-10 ``e'' or base-2 ``p'' (or their upper-case variants)
// exponent may be provided as well, except for hexadecimal floats which
// only accept an (optional) ``p'' exponent (because an ``e'' or ``E'' cannot
-// be distinguished from a mantissa digit).
+// be distinguished from a mantissa digit). If the exponent's absolute value
+// is too large, the operation may fail.
// The entire string, not just a prefix, must be valid for success. If the
// operation failed, the value of z is undefined but the returned value is nil.
func (z *Rat) SetString(s string) (*Rat, bool) {
@@ -169,6 +170,9 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
if n < 0 {
n = -n
}
+ if n > 1e6 {
+ return nil, false // avoid excessively large exponents
+ }
pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs
if exp5 > 0 {
z.a.abs = z.a.abs.mul(z.a.abs, pow5)
@@ -181,15 +185,12 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
}
// apply exp2 contributions
+ if exp2 < -1e7 || exp2 > 1e7 {
+ return nil, false // avoid excessively large exponents
+ }
if exp2 > 0 {
- if int64(uint(exp2)) != exp2 {
- panic("exponent too large")
- }
z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
} else if exp2 < 0 {
- if int64(uint(-exp2)) != -exp2 {
- panic("exponent too large")
- }
z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2))
}
diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go
index ba0d1ba9e1..15d206cb38 100644
--- a/src/math/big/ratconv_test.go
+++ b/src/math/big/ratconv_test.go
@@ -589,3 +589,28 @@ func TestIssue31184(t *testing.T) {
}
}
}
+
+func TestIssue45910(t *testing.T) {
+ var x Rat
+ for _, test := range []struct {
+ input string
+ want bool
+ }{
+ {"1e-1000001", false},
+ {"1e-1000000", true},
+ {"1e+1000000", true},
+ {"1e+1000001", false},
+
+ {"0p1000000000000", true},
+ {"1p-10000001", false},
+ {"1p-10000000", true},
+ {"1p+10000000", true},
+ {"1p+10000001", false},
+ {"1.770p02041010010011001001", false}, // test case from issue
+ } {
+ _, got := x.SetString(test.input)
+ if got != test.want {
+ t.Errorf("SetString(%s) got ok = %v; want %v", test.input, got, test.want)
+ }
+ }
+}
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 06553636ee..f646629912 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -1799,3 +1799,161 @@ func TestPTRandNonPTR(t *testing.T) {
t.Errorf("names = %q; want %q", names, want)
}
}
+
+func TestCVE202133195(t *testing.T) {
+ fake := fakeDNSServer{
+ rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+ r := dnsmessage.Message{
+ Header: dnsmessage.Header{
+ ID: q.Header.ID,
+ Response: true,
+ RCode: dnsmessage.RCodeSuccess,
+ RecursionAvailable: true,
+ },
+ Questions: q.Questions,
+ }
+ switch q.Questions[0].Type {
+ case dnsmessage.TypeCNAME:
+ r.Answers = []dnsmessage.Resource{}
+ case dnsmessage.TypeA: // CNAME lookup uses a A/AAAA as a proxy
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("<html>.golang.org."),
+ Type: dnsmessage.TypeA,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.AResource{
+ A: TestAddr,
+ },
+ },
+ )
+ case dnsmessage.TypeSRV:
+ n := q.Questions[0].Name
+ if n.String() == "_hdr._tcp.golang.org." {
+ n = dnsmessage.MustNewName("<html>.golang.org.")
+ }
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: n,
+ Type: dnsmessage.TypeSRV,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.SRVResource{
+ Target: dnsmessage.MustNewName("<html>.golang.org."),
+ },
+ },
+ )
+ case dnsmessage.TypeMX:
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("<html>.golang.org."),
+ Type: dnsmessage.TypeMX,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.MXResource{
+ MX: dnsmessage.MustNewName("<html>.golang.org."),
+ },
+ },
+ )
+ case dnsmessage.TypeNS:
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("<html>.golang.org."),
+ Type: dnsmessage.TypeNS,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.NSResource{
+ NS: dnsmessage.MustNewName("<html>.golang.org."),
+ },
+ },
+ )
+ case dnsmessage.TypePTR:
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("<html>.golang.org."),
+ Type: dnsmessage.TypePTR,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.PTRResource{
+ PTR: dnsmessage.MustNewName("<html>.golang.org."),
+ },
+ },
+ )
+ }
+ return r, nil
+ },
+ }
+
+ r := Resolver{PreferGo: true, Dial: fake.DialContext}
+ // Change the default resolver to match our manipulated resolver
+ originalDefault := DefaultResolver
+ DefaultResolver = &r
+ defer func() { DefaultResolver = originalDefault }()
+ // Redirect host file lookups.
+ defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
+ testHookHostsPath = "testdata/hosts"
+
+ _, err := r.LookupCNAME(context.Background(), "golang.org")
+ if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("Resolver.LookupCNAME returned unexpected error, got %q, want %q", err, expected)
+ }
+ _, err = LookupCNAME("golang.org")
+ if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("LookupCNAME returned unexpected error, got %q, want %q", err, expected)
+ }
+
+ _, _, err = r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
+ if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
+ }
+ _, _, err = LookupSRV("target", "tcp", "golang.org")
+ if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
+ }
+
+ _, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org")
+ if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
+ }
+ _, _, err = LookupSRV("hdr", "tcp", "golang.org")
+ if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
+ }
+
+ _, err = r.LookupMX(context.Background(), "golang.org")
+ if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("Resolver.LookupMX returned unexpected error, got %q, want %q", err, expected)
+ }
+ _, err = LookupMX("golang.org")
+ if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("LookupMX returned unexpected error, got %q, want %q", err, expected)
+ }
+
+ _, err = r.LookupNS(context.Background(), "golang.org")
+ if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("Resolver.LookupNS returned unexpected error, got %q, want %q", err, expected)
+ }
+ _, err = LookupNS("golang.org")
+ if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("LookupNS returned unexpected error, got %q, want %q", err, expected)
+ }
+
+ _, err = r.LookupAddr(context.Background(), "192.0.2.42")
+ if expected := "lookup 192.0.2.42: PTR target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err, expected)
+ }
+ _, err = LookupAddr("192.0.2.42")
+ if expected := "lookup 192.0.2.42: PTR target is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err, expected)
+ }
+}
diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
index 3f48fab544..f49cefbb4f 100644
--- a/src/net/http/httputil/reverseproxy.go
+++ b/src/net/http/httputil/reverseproxy.go
@@ -248,22 +248,18 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// important is "Connection" because we want a persistent
// connection, regardless of what the client sent to us.
for _, h := range hopHeaders {
- hv := outreq.Header.Get(h)
- if hv == "" {
- continue
- }
- if h == "Te" && hv == "trailers" {
- // Issue 21096: tell backend applications that
- // care about trailer support that we support
- // trailers. (We do, but we don't go out of
- // our way to advertise that unless the
- // incoming client request thought it was
- // worth mentioning)
- continue
- }
outreq.Header.Del(h)
}
+ // Issue 21096: tell backend applications that care about trailer support
+ // that we support trailers. (We do, but we don't go out of our way to
+ // advertise that unless the incoming client request thought it was worth
+ // mentioning.) Note that we look at req.Header, not outreq.Header, since
+ // the latter has passed through removeConnectionHeaders.
+ if httpguts.HeaderValuesContainsToken(req.Header["Te"], "trailers") {
+ outreq.Header.Set("Te", "trailers")
+ }
+
// After stripping all the hop-by-hop connection headers above, add back any
// necessary for protocol upgrades, such as for websockets.
if reqUpType != "" {
diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
index 764939fb0f..1f2dfb9867 100644
--- a/src/net/http/httputil/reverseproxy_test.go
+++ b/src/net/http/httputil/reverseproxy_test.go
@@ -91,8 +91,9 @@ func TestReverseProxy(t *testing.T) {
getReq, _ := http.NewRequest("GET", frontend.URL, nil)
getReq.Host = "some-name"
- getReq.Header.Set("Connection", "close")
- getReq.Header.Set("Te", "trailers")
+ getReq.Header.Set("Connection", "close, TE")
+ getReq.Header.Add("Te", "foo")
+ getReq.Header.Add("Te", "bar, trailers")
getReq.Header.Set("Proxy-Connection", "should be deleted")
getReq.Header.Set("Upgrade", "foo")
getReq.Close = true
@@ -236,6 +237,64 @@ func TestReverseProxyStripHeadersPresentInConnection(t *testing.T) {
}
}
+func TestReverseProxyStripEmptyConnection(t *testing.T) {
+ // See Issue 46313.
+ const backendResponse = "I am the backend"
+
+ // someConnHeader is some arbitrary header to be declared as a hop-by-hop header
+ // in the Request's Connection header.
+ const someConnHeader = "X-Some-Conn-Header"
+
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if c := r.Header.Values("Connection"); len(c) != 0 {
+ t.Errorf("handler got header %q = %v; want empty", "Connection", c)
+ }
+ if c := r.Header.Get(someConnHeader); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
+ }
+ w.Header().Add("Connection", "")
+ w.Header().Add("Connection", someConnHeader)
+ w.Header().Set(someConnHeader, "should be deleted")
+ io.WriteString(w, backendResponse)
+ }))
+ defer backend.Close()
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ proxyHandler.ServeHTTP(w, r)
+ if c := r.Header.Get(someConnHeader); c != "should be deleted" {
+ t.Errorf("handler modified header %q = %q; want %q", someConnHeader, c, "should be deleted")
+ }
+ }))
+ defer frontend.Close()
+
+ getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+ getReq.Header.Add("Connection", "")
+ getReq.Header.Add("Connection", someConnHeader)
+ getReq.Header.Set(someConnHeader, "should be deleted")
+ res, err := frontend.Client().Do(getReq)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ defer res.Body.Close()
+ bodyBytes, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatalf("reading body: %v", err)
+ }
+ if got, want := string(bodyBytes), backendResponse; got != want {
+ t.Errorf("got body %q; want %q", got, want)
+ }
+ if c := res.Header.Get("Connection"); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", "Connection", c)
+ }
+ if c := res.Header.Get(someConnHeader); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
+ }
+}
+
func TestXForwardedFor(t *testing.T) {
const prevForwardedFor = "client ip"
const backendResponse = "I am the backend"
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 3c7b9eb4de..faa77e9ccd 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -5270,7 +5270,6 @@ func TestMissingStatusNoPanic(t *testing.T) {
ln := newLocalListener(t)
addr := ln.Addr().String()
- shutdown := make(chan bool, 1)
done := make(chan bool)
fullAddrURL := fmt.Sprintf("http://%s", addr)
raw := "HTTP/1.1 400\r\n" +
@@ -5282,10 +5281,7 @@ func TestMissingStatusNoPanic(t *testing.T) {
"Aloha Olaa"
go func() {
- defer func() {
- ln.Close()
- close(done)
- }()
+ defer close(done)
conn, _ := ln.Accept()
if conn != nil {
@@ -5316,7 +5312,7 @@ func TestMissingStatusNoPanic(t *testing.T) {
t.Errorf("got=%v want=%q", err, want)
}
- close(shutdown)
+ ln.Close()
<-done
}
diff --git a/src/net/lookup.go b/src/net/lookup.go
index 5f7119872a..0660268249 100644
--- a/src/net/lookup.go
+++ b/src/net/lookup.go
@@ -389,8 +389,11 @@ func (r *Resolver) LookupPort(ctx context.Context, network, service string) (por
// LookupCNAME does not return an error if host does not
// contain DNS "CNAME" records, as long as host resolves to
// address records.
+//
+// The returned canonical name is validated to be a properly
+// formatted presentation-format domain name.
func LookupCNAME(host string) (cname string, err error) {
- return DefaultResolver.lookupCNAME(context.Background(), host)
+ return DefaultResolver.LookupCNAME(context.Background(), host)
}
// LookupCNAME returns the canonical name for the given host.
@@ -403,8 +406,18 @@ func LookupCNAME(host string) (cname string, err error) {
// LookupCNAME does not return an error if host does not
// contain DNS "CNAME" records, as long as host resolves to
// address records.
-func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, err error) {
- return r.lookupCNAME(ctx, host)
+//
+// The returned canonical name is validated to be a properly
+// formatted presentation-format domain name.
+func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) {
+ cname, err := r.lookupCNAME(ctx, host)
+ if err != nil {
+ return "", err
+ }
+ if !isDomainName(cname) {
+ return "", &DNSError{Err: "CNAME target is invalid", Name: host}
+ }
+ return cname, nil
}
// LookupSRV tries to resolve an SRV query of the given service,
@@ -416,8 +429,11 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string,
// That is, it looks up _service._proto.name. To accommodate services
// publishing SRV records under non-standard names, if both service
// and proto are empty strings, LookupSRV looks up name directly.
+//
+// The returned service names are validated to be properly
+// formatted presentation-format domain names.
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
- return DefaultResolver.lookupSRV(context.Background(), service, proto, name)
+ return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
}
// LookupSRV tries to resolve an SRV query of the given service,
@@ -429,28 +445,82 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
// That is, it looks up _service._proto.name. To accommodate services
// publishing SRV records under non-standard names, if both service
// and proto are empty strings, LookupSRV looks up name directly.
-func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
- return r.lookupSRV(ctx, service, proto, name)
+//
+// The returned service names are validated to be properly
+// formatted presentation-format domain names.
+func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
+ cname, addrs, err := r.lookupSRV(ctx, service, proto, name)
+ if err != nil {
+ return "", nil, err
+ }
+ if cname != "" && !isDomainName(cname) {
+ return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
+ }
+ for _, addr := range addrs {
+ if addr == nil {
+ continue
+ }
+ if !isDomainName(addr.Target) {
+ return "", nil, &DNSError{Err: "SRV target is invalid", Name: name}
+ }
+ }
+ return cname, addrs, nil
}
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
+//
+// The returned mail server names are validated to be properly
+// formatted presentation-format domain names.
func LookupMX(name string) ([]*MX, error) {
- return DefaultResolver.lookupMX(context.Background(), name)
+ return DefaultResolver.LookupMX(context.Background(), name)
}
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
+//
+// The returned mail server names are validated to be properly
+// formatted presentation-format domain names.
func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
- return r.lookupMX(ctx, name)
+ records, err := r.lookupMX(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ for _, mx := range records {
+ if mx == nil {
+ continue
+ }
+ if !isDomainName(mx.Host) {
+ return nil, &DNSError{Err: "MX target is invalid", Name: name}
+ }
+ }
+ return records, nil
}
// LookupNS returns the DNS NS records for the given domain name.
+//
+// The returned name server names are validated to be properly
+// formatted presentation-format domain names.
func LookupNS(name string) ([]*NS, error) {
- return DefaultResolver.lookupNS(context.Background(), name)
+ return DefaultResolver.LookupNS(context.Background(), name)
}
// LookupNS returns the DNS NS records for the given domain name.
+//
+// The returned name server names are validated to be properly
+// formatted presentation-format domain names.
func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
- return r.lookupNS(ctx, name)
+ records, err := r.lookupNS(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ for _, ns := range records {
+ if ns == nil {
+ continue
+ }
+ if !isDomainName(ns.Host) {
+ return nil, &DNSError{Err: "NS target is invalid", Name: name}
+ }
+ }
+ return records, nil
}
// LookupTXT returns the DNS TXT records for the given domain name.
@@ -466,14 +536,29 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error)
// LookupAddr performs a reverse lookup for the given address, returning a list
// of names mapping to that address.
//
+// The returned names are validated to be properly formatted presentation-format
+// domain names.
+//
// When using the host C library resolver, at most one result will be
// returned. To bypass the host resolver, use a custom Resolver.
func LookupAddr(addr string) (names []string, err error) {
- return DefaultResolver.lookupAddr(context.Background(), addr)
+ return DefaultResolver.LookupAddr(context.Background(), addr)
}
// LookupAddr performs a reverse lookup for the given address, returning a list
// of names mapping to that address.
-func (r *Resolver) LookupAddr(ctx context.Context, addr string) (names []string, err error) {
- return r.lookupAddr(ctx, addr)
+//
+// The returned names are validated to be properly formatted presentation-format
+// domain names.
+func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
+ names, err := r.lookupAddr(ctx, addr)
+ if err != nil {
+ return nil, err
+ }
+ for _, name := range names {
+ if !isDomainName(name) {
+ return nil, &DNSError{Err: "PTR target is invalid", Name: addr}
+ }
+ }
+ return names, nil
}