From 44a6805ca92b00f30d5ed3f9e8d0b464d3f402bf Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Mon, 24 Aug 2020 14:43:32 +0800 Subject: [release-branch.go1.15] math/big: fix TestShiftOverlap for test -count arguments > 1 Don't overwrite incoming test data. The change uses copy instead of assigning statement to avoid this. For #45335 Change-Id: Ib907101822d811de5c45145cb9d7961907e212c3 Reviewed-on: https://go-review.googlesource.com/c/go/+/250137 Run-TryBot: Emmanuel Odeke TryBot-Result: Gobot Gobot Reviewed-by: Robert Griesemer (cherry picked from commit 41bc0a1713b9436e96c2d64211ad94e42cafd591) Reviewed-on: https://go-review.googlesource.com/c/go/+/319831 Run-TryBot: Carlos Amedee TryBot-Result: Go Bot Trust: Carlos Amedee Reviewed-by: Jonathan Albrecht Reviewed-by: Emmanuel Odeke --- src/math/big/arith_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/math/big/arith_test.go b/src/math/big/arith_test.go index 05136f1895..e2b982c89c 100644 --- a/src/math/big/arith_test.go +++ b/src/math/big/arith_test.go @@ -241,20 +241,20 @@ var argshrVU = []argVU{ } 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) } } -- cgit v1.2.3-54-g00ecf From 963687891319d118c20a2a71f0234ceb3a8dade4 Mon Sep 17 00:00:00 2001 From: Jonathan Albrecht Date: Wed, 2 Dec 2020 10:44:10 -0500 Subject: [release-branch.go1.15] math/big: remove the s390x assembly for shlVU and shrVU The s390x assembly for shlVU does a forward copy when the shift amount s is 0. This causes corruption of the result z when z is aliased to the input x. This fix removes the s390x assembly for both shlVU and shrVU so the pure go implementations will be used. Test cases have been added to the existing TestShiftOverlap test to cover shift values of 0, 1 and (_W - 1). Fixes #45335 Change-Id: I75ca0e98f3acfaa6366a26355dcd9dd82499a48b Reviewed-on: https://go-review.googlesource.com/c/go/+/274442 Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Reviewed-by: Matthew Dempsky Trust: Robert Griesemer (cherry picked from commit b1369d5862bc78eaa902ae637c874e6a6133f1f9) Reviewed-on: https://go-review.googlesource.com/c/go/+/320169 Trust: Carlos Amedee Run-TryBot: Carlos Amedee Reviewed-by: Dmitri Shuralyov --- src/math/big/arith_s390x.s | 192 +-------------------------------------------- src/math/big/arith_test.go | 55 ++++++++++++- 2 files changed, 54 insertions(+), 193 deletions(-) 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<>ŝ - SRD R7, R10, R6 - OR R6, R3 - MOVD R3, (R2)(R5*1) // z[i] = w<>ŝ - SUB $8, R5 // i-- - -E8: - CMPBGT R5, R0, L8 // i < n-1 - - // i >= n-1 -X8a: - SLD R4, R10 // w1<= 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 | w1<= 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<= 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<= 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 e2b982c89c..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,6 +261,19 @@ 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) { @@ -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) } } -- cgit v1.2.3-54-g00ecf From 3380b180c66ffcee2bec37877f4a5be5ab78fd5c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 11 May 2021 22:40:02 -0400 Subject: [release-branch.go1.15] cmd/link: don't cast end address to int32 When linking a very large binary, the section address may not fit in int32. Don't truncate it. Fixes #46127. Updates #46126. Change-Id: Ibcc8d74bf5662611949e547ce44ca8b973de383f Reviewed-on: https://go-review.googlesource.com/c/go/+/319289 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh TryBot-Result: Go Bot (cherry picked from commit af0f8c149e8a4b237910fc7b41739bedc546473c) Reviewed-on: https://go-review.googlesource.com/c/go/+/319370 --- src/cmd/link/internal/ld/elf.go | 2 +- src/cmd/link/internal/ld/macho.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 -- cgit v1.2.3-54-g00ecf From df9ce19db6df32d94eae8760927bdfbc595433c3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 2 May 2021 11:27:03 -0700 Subject: [release-branch.go1.15] math/big: check for excessive exponents in Rat.SetString Found by OSS-Fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33284 Thanks to Emmanuel Odeke for reporting this issue. Updates #45910 Fixes #46305 Fixes CVE-2021-33198 Change-Id: I61e7b04dbd80343420b57eede439e361c0f7b79c Reviewed-on: https://go-review.googlesource.com/c/go/+/316149 Trust: Robert Griesemer Trust: Katie Hockman Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Katie Hockman Reviewed-by: Emmanuel Odeke (cherry picked from commit 6c591f79b0b5327549bd4e94970f7a279efb4ab0) Reviewed-on: https://go-review.googlesource.com/c/go/+/321831 Run-TryBot: Katie Hockman Reviewed-by: Roland Shoemaker --- src/math/big/ratconv.go | 15 ++++++++------- src/math/big/ratconv_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) 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) + } + } +} -- cgit v1.2.3-54-g00ecf From 31d60cda1f58b7558fc5725d2b9e4531655d980e Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 27 May 2021 10:40:06 -0700 Subject: [release-branch.go1.15] net: verify results from Lookup* are valid domain names For the methods LookupCNAME, LookupSRV, LookupMX, LookupNS, and LookupAddr check that the returned domain names are in fact valid DNS names using the existing isDomainName function. Thanks to Philipp Jeitner and Haya Shulman from Fraunhofer SIT for reporting this issue. Updates #46241 Fixes #46356 Fixes CVE-2021-33195 Change-Id: I47a4f58c031cb752f732e88bbdae7f819f0af4f3 Reviewed-on: https://go-review.googlesource.com/c/go/+/323131 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda Reviewed-by: Katie Hockman (cherry picked from commit cdcd02842da7c004efd023881e3719105209c908) Reviewed-on: https://go-review.googlesource.com/c/go/+/323269 --- src/net/dnsclient_unix_test.go | 157 +++++++++++++++++++++++++++++++++++++++++ src/net/lookup.go | 111 +++++++++++++++++++++++++---- 2 files changed, 255 insertions(+), 13 deletions(-) diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 06553636ee..819f20b887 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -1799,3 +1799,160 @@ 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(".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(".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(".golang.org."), + }, + }, + ) + case dnsmessage.TypeMX: + r.Answers = append(r.Answers, + dnsmessage.Resource{ + Header: dnsmessage.ResourceHeader{ + Name: dnsmessage.MustNewName(".golang.org."), + Type: dnsmessage.TypeMX, + Class: dnsmessage.ClassINET, + Length: 4, + }, + Body: &dnsmessage.MXResource{ + MX: dnsmessage.MustNewName(".golang.org."), + }, + }, + ) + case dnsmessage.TypeNS: + r.Answers = append(r.Answers, + dnsmessage.Resource{ + Header: dnsmessage.ResourceHeader{ + Name: dnsmessage.MustNewName(".golang.org."), + Type: dnsmessage.TypeNS, + Class: dnsmessage.ClassINET, + Length: 4, + }, + Body: &dnsmessage.NSResource{ + NS: dnsmessage.MustNewName(".golang.org."), + }, + }, + ) + case dnsmessage.TypePTR: + r.Answers = append(r.Answers, + dnsmessage.Resource{ + Header: dnsmessage.ResourceHeader{ + Name: dnsmessage.MustNewName(".golang.org."), + Type: dnsmessage.TypePTR, + Class: dnsmessage.ClassINET, + Length: 4, + }, + Body: &dnsmessage.PTRResource{ + PTR: dnsmessage.MustNewName(".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 + }() + + _, 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.Error(), 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.Error(), 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.Error(), 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.Error(), 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.Error(), 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.Error(), 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.Error(), 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.Error(), 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.Error(), 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.Error(), expected) + } + + _, err = r.LookupAddr(context.Background(), "1.2.3.4") + if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected { + t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err.Error(), expected) + } + _, err = LookupAddr("1.2.3.4") + if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected { + t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err.Error(), expected) + } +} 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 } -- cgit v1.2.3-54-g00ecf From c92adf420a3d9a5510f9aea382d826f0c9216a10 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 11 May 2021 11:31:31 -0700 Subject: [release-branch.go1.15] archive/zip: only preallocate File slice if reasonably sized Since the number of files in the EOCD record isn't validated, it isn't safe to preallocate Reader.Files using that field. A malformed archive can indicate it contains up to 1 << 128 - 1 files. We can still safely preallocate the slice by checking if the specified number of files in the archive is reasonable, given the size of the archive. Thanks to the OSS-Fuzz project for discovering this issue and to Emmanuel Odeke for reporting it. Updates #46242 Fixes #46396 Fixes CVE-2021-33196 Change-Id: I3c76d8eec178468b380d87fdb4a3f2cb06f0ee76 Reviewed-on: https://go-review.googlesource.com/c/go/+/318909 Trust: Roland Shoemaker Trust: Katie Hockman Trust: Joe Tsai Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman Reviewed-by: Joe Tsai (cherry picked from commit 74242baa4136c7a9132a8ccd9881354442788c8c) Reviewed-on: https://go-review.googlesource.com/c/go/+/322949 Reviewed-by: Filippo Valsorda --- src/archive/zip/reader.go | 10 ++++++- src/archive/zip/reader_test.go | 59 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) 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)) + } +} -- cgit v1.2.3-54-g00ecf From cbd1ca84453fecf3825a6bb9f985823e8bc32b76 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 21 May 2021 14:02:30 -0400 Subject: [release-branch.go1.15] net/http/httputil: always remove hop-by-hop headers Previously, we'd fail to remove the Connection header from a request like this: Connection: Connection: x-header Updates #46313 Fixes #46314 Fixes CVE-2021-33197 Change-Id: Ie3009e926ceecfa86dfa6bcc6fe14ff01086be7d Reviewed-on: https://go-review.googlesource.com/c/go/+/321929 Run-TryBot: Filippo Valsorda Reviewed-by: Katie Hockman Trust: Katie Hockman Trust: Filippo Valsorda TryBot-Result: Go Bot Reviewed-on: https://go-review.googlesource.com/c/go/+/323091 Run-TryBot: Katie Hockman --- src/net/http/httputil/reverseproxy.go | 22 +++++------ src/net/http/httputil/reverseproxy_test.go | 63 +++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 15 deletions(-) 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" -- cgit v1.2.3-54-g00ecf From e3c9537541e35460f4fca12fe36fec822a8d53e3 Mon Sep 17 00:00:00 2001 From: Michael Fraenkel Date: Thu, 13 May 2021 09:41:45 -0600 Subject: [release-branch.go1.15] net/http: prevent infinite wait during TestMissingStatusNoPanic If the client request never makes it to the server, the outstanding accept is never broken. Change the test to always close the listening socket when the client request completes. Updates #45358 Change-Id: I744a91dfa11704e7e528163d7669c394e90456dc Reviewed-on: https://go-review.googlesource.com/c/go/+/319275 Trust: Heschi Kreinick Reviewed-by: Bryan C. Mills (cherry picked from commit c0a7ecfae775a9d50d338e8123fac32a5d04308c) Reviewed-on: https://go-review.googlesource.com/c/go/+/320189 Reviewed-by: Damien Neil Run-TryBot: Bryan C. Mills Run-TryBot: Damien Neil TryBot-Result: Go Bot --- src/net/http/transport_test.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 } -- cgit v1.2.3-54-g00ecf From 448be06c36caa792b12d997fea8cae50ba7d9de0 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Thu, 29 Apr 2021 16:07:25 -0500 Subject: [release-branch.go1.15] cmd/link/internal: fix use of DynlinkingGo with ppc64le trampolines When creating programs with large text sections on ppc64le, trampolines are needed for calls that are too far; however they are not created if the code is generated such that the TOC register r2 is initialized and maintained in the code because then the external linker can create the trampolines. Previously the function DynlinkingGo was used to determine this but in the case where plugins are used, this could return true even though r2 is not valid. To fix this problem I've added a new function r2Valid which returns true when the build options indicate that the r2 is initialized and maintained. Because of the ways that DynlinkingGo is used I wanted to maintain its previous behavior. Fixes #46002 Change-Id: I6d902eba6ad41757aa6474948b79acdbd479cb38 Reviewed-on: https://go-review.googlesource.com/c/go/+/315289 Trust: Lynn Boger Run-TryBot: Lynn Boger Reviewed-by: Cherry Zhang TryBot-Result: Go Bot (cherry picked from commit 9ed736ac2a99aa2e7ef7d8bed3b01ca8b20a6f80) Reviewed-on: https://go-review.googlesource.com/c/go/+/317974 Run-TryBot: Dmitri Shuralyov Reviewed-by: Carlos Amedee Reviewed-by: Cherry Mui --- src/cmd/link/internal/ppc64/asm.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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 { -- cgit v1.2.3-54-g00ecf From d9cffabed288ebece50ece29d44eff283e5cc485 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 27 Apr 2021 02:31:23 -0400 Subject: [release-branch.go1.15] cmd/go: use a real Go version in the go.mod files in TestScript/mod_readonly For some reason, the go.mod file added to this test in CL 147281 lists 'go 1.20' instead of the version that was actually current when the go.mod file was added. That causes the test's behavior to change under lazy loading, because 1.20 is above the threshold to trigger lazy-loading invariants (1.17). This backports CL 314049 to Go 1.15 in order to fix a spurious test failure in a subsequent change. For #46143 Updates #46142 Updates #36460 Change-Id: I92400996cb051ab30e99bfffafd91ff32a1e7087 Reviewed-on: https://go-review.googlesource.com/c/go/+/314049 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Michael Matloob TryBot-Result: Go Bot Reviewed-on: https://go-review.googlesource.com/c/go/+/319709 Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/mod_readonly.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 -- cgit v1.2.3-54-g00ecf From fbf844b46d147c442a6016aa9c6bef51c309257b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 13 May 2021 09:48:40 -0400 Subject: [release-branch.go1.15] cmd/go: error out of 'go mod tidy' if the go version is newer than supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This backports the test from CL 319669, but — because of extensive changes to the module loader during the Go 1.16 and 1.17 cycles — the implementation is entirely different. (This implementation is based on the addGoStmt function already present in init.go.) Fixes #46143 Updates #46142 Change-Id: Ib7a0a159e53cbe476be6aa9a050add10cc750dec Reviewed-on: https://go-review.googlesource.com/c/go/+/319710 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod TryBot-Result: Go Bot --- src/cmd/go/internal/modcmd/tidy.go | 1 + src/cmd/go/internal/modload/load.go | 27 +++++++++++++++++++++ src/cmd/go/testdata/script/mod_tidy_too_new.txt | 31 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 src/cmd/go/testdata/script/mod_tidy_too_new.txt 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_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 -- cgit v1.2.3-54-g00ecf From 6b411e90d4d017f28c1cc7d442b5ec8c1f9de549 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 2 Jun 2021 09:20:22 -0700 Subject: [release-branch.go1.15] net: don't rely on system hosts in TestCVE202133195 Also don't unnecessarily deref the error return. Updates #46504 Fixes #46531 Change-Id: I22d14ac76776f8988fa0774bdcb5fcd801ce0185 Reviewed-on: https://go-review.googlesource.com/c/go/+/324190 Trust: David Chase Trust: Damien Neil Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Damien Neil (cherry picked from commit dd7ba3ba2c860c40be6d70b63d4a678449cae80f) Reviewed-on: https://go-review.googlesource.com/c/go/+/324333 Reviewed-by: Ian Lance Taylor --- src/net/dnsclient_unix_test.go | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 819f20b887..f646629912 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -1898,61 +1898,62 @@ func TestCVE202133195(t *testing.T) { // Change the default resolver to match our manipulated resolver originalDefault := DefaultResolver DefaultResolver = &r - defer func() { - DefaultResolver = originalDefault - }() + 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.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.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.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.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.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.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.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.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.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.Error(), expected) + t.Errorf("LookupNS returned unexpected error, got %q, want %q", err, expected) } - _, err = r.LookupAddr(context.Background(), "1.2.3.4") - if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected { - t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err.Error(), 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("1.2.3.4") - if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected { - t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err.Error(), 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) } } -- cgit v1.2.3-54-g00ecf From ab7f8297f9734b24a43a942930258cda411f16a3 Mon Sep 17 00:00:00 2001 From: David Chase Date: Thu, 3 Jun 2021 15:22:10 +0000 Subject: [release-branch.go1.15] go1.15.13 Change-Id: Ib0907538e78ef9b272be8858bc8b52c8b7d6c71a Reviewed-on: https://go-review.googlesource.com/c/go/+/324551 Run-TryBot: David Chase Trust: David Chase TryBot-Result: Go Bot Reviewed-by: Carlos Amedee --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1a6490f14b..b818ff589c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -go1.15.12 \ No newline at end of file +go1.15.13 \ No newline at end of file -- cgit v1.2.3-54-g00ecf