diff --git a/1000-all-implement-plugin-build-mode-for-riscv64.patch b/1000-all-implement-plugin-build-mode-for-riscv64.patch new file mode 100644 index 0000000000000000000000000000000000000000..be28f8fc03d791e6d81d5d0b876b99eb6f15fc50 --- /dev/null +++ b/1000-all-implement-plugin-build-mode-for-riscv64.patch @@ -0,0 +1,232 @@ +From 3adb57d3e689f0c3da7a26df52e9218afb18d94f Mon Sep 17 00:00:00 2001 +From: Meng Zhuo +Date: Thu, 12 Sep 2024 20:15:56 +0800 +Subject: [PATCH] all: implement plugin build mode for riscv64 + +Change-Id: I8d7bbeebbf4a46f2fd8d630b1edbaf79b8ffccc5 +Reviewed-on: https://go-review.googlesource.com/c/go/+/420114 +Reviewed-by: Dmitri Shuralyov +Reviewed-by: Michael Knyszek +Reviewed-by: Joel Sing +TryBot-Bypass: Joel Sing +--- + src/cmd/dist/test.go | 2 +- + src/cmd/internal/obj/riscv/obj.go | 121 +++++++++++++++++++++++++++ + src/cmd/link/internal/riscv64/asm.go | 21 ++++- + src/internal/platform/supported.go | 2 +- + src/runtime/asm_riscv64.s | 9 ++ + 5 files changed, 152 insertions(+), 3 deletions(-) + +diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go +index 0ffcabe416..b1e3929113 100644 +--- a/src/cmd/dist/test.go ++++ b/src/cmd/dist/test.go +@@ -1659,7 +1659,7 @@ func buildModeSupported(compiler, buildmode, goos, goarch string) bool { + + case "plugin": + switch platform { +- case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/loong64", "linux/s390x", "linux/ppc64le", ++ case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/loong64", "linux/riscv64", "linux/s390x", "linux/ppc64le", + "android/amd64", "android/386", + "darwin/amd64", "darwin/arm64", + "freebsd/amd64": +diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go +index 2055f4836e..44a2246e1f 100644 +--- a/src/cmd/internal/obj/riscv/obj.go ++++ b/src/cmd/internal/obj/riscv/obj.go +@@ -177,6 +177,127 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { + p.From.Offset = 0 + } + } ++ ++ if ctxt.Flag_dynlink { ++ rewriteToUseGot(ctxt, p, newprog) ++ } ++} ++ ++// Rewrite p, if necessary, to access global data via the global offset table. ++func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ++ if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO { ++ // ADUFFxxx $offset ++ // becomes ++ // MOV runtime.duffxxx@GOT, REG_TMP ++ // ADD $offset, REG_TMP ++ // CALL REG_TMP ++ var sym *obj.LSym ++ if p.As == obj.ADUFFCOPY { ++ sym = ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal) ++ } else { ++ sym = ctxt.LookupABI("runtime.duffzero", obj.ABIInternal) ++ } ++ offset := p.To.Offset ++ p.As = AMOV ++ p.From.Type = obj.TYPE_MEM ++ p.From.Name = obj.NAME_GOTREF ++ p.From.Sym = sym ++ p.To.Type = obj.TYPE_REG ++ p.To.Reg = REG_TMP ++ p.To.Name = obj.NAME_NONE ++ p.To.Offset = 0 ++ p.To.Sym = nil ++ ++ p1 := obj.Appendp(p, newprog) ++ p1.As = AADD ++ p1.From.Type = obj.TYPE_CONST ++ p1.From.Offset = offset ++ p1.To.Type = obj.TYPE_REG ++ p1.To.Reg = REG_TMP ++ ++ p2 := obj.Appendp(p1, newprog) ++ p2.As = obj.ACALL ++ p2.To.Type = obj.TYPE_REG ++ p2.To.Reg = REG_TMP ++ } ++ ++ // We only care about global data: NAME_EXTERN means a global ++ // symbol in the Go sense and p.Sym.Local is true for a few internally ++ // defined symbols. ++ if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { ++ // MOV $sym, Rx becomes MOV sym@GOT, Rx ++ // MOV $sym+, Rx becomes MOV sym@GOT, Rx; ADD , Rx ++ if p.As != AMOV { ++ ctxt.Diag("don't know how to handle TYPE_ADDR in %v with -dynlink", p) ++ } ++ if p.To.Type != obj.TYPE_REG { ++ ctxt.Diag("don't know how to handle LD instruction to non-register in %v with -dynlink", p) ++ } ++ p.From.Type = obj.TYPE_MEM ++ p.From.Name = obj.NAME_GOTREF ++ if p.From.Offset != 0 { ++ q := obj.Appendp(p, newprog) ++ q.As = AADD ++ q.From.Type = obj.TYPE_CONST ++ q.From.Offset = p.From.Offset ++ q.To = p.To ++ p.From.Offset = 0 ++ } ++ ++ } ++ ++ if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN { ++ ctxt.Diag("don't know how to handle %v with -dynlink", p) ++ } ++ ++ var source *obj.Addr ++ // MOVx sym, Ry becomes MOV sym@GOT, X31; MOVx (X31), Ry ++ // MOVx Ry, sym becomes MOV sym@GOT, X31; MOV Ry, (X31) ++ // An addition may be inserted between the two MOVs if there is an offset. ++ if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { ++ if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { ++ ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) ++ } ++ source = &p.From ++ } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { ++ source = &p.To ++ } else { ++ return ++ } ++ if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP { ++ return ++ } ++ if source.Sym.Type == objabi.STLSBSS { ++ return ++ } ++ if source.Type != obj.TYPE_MEM { ++ ctxt.Diag("don't know how to handle %v with -dynlink", p) ++ } ++ p1 := obj.Appendp(p, newprog) ++ p1.As = AMOV ++ p1.From.Type = obj.TYPE_MEM ++ p1.From.Sym = source.Sym ++ p1.From.Name = obj.NAME_GOTREF ++ p1.To.Type = obj.TYPE_REG ++ p1.To.Reg = REG_TMP ++ ++ p2 := obj.Appendp(p1, newprog) ++ p2.As = p.As ++ p2.From = p.From ++ p2.To = p.To ++ if p.From.Name == obj.NAME_EXTERN { ++ p2.From.Reg = REG_TMP ++ p2.From.Name = obj.NAME_NONE ++ p2.From.Sym = nil ++ } else if p.To.Name == obj.NAME_EXTERN { ++ p2.To.Reg = REG_TMP ++ p2.To.Name = obj.NAME_NONE ++ p2.To.Sym = nil ++ } else { ++ return ++ } ++ obj.Nopout(p) ++ + } + + // addrToReg extracts the register from an Addr, handling special Addr.Names. +diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go +index 6a4dd01240..a9583d21aa 100644 +--- a/src/cmd/link/internal/riscv64/asm.go ++++ b/src/cmd/link/internal/riscv64/asm.go +@@ -20,7 +20,26 @@ import ( + // fakeLabelName matches the RISCV_FAKE_LABEL_NAME from binutils. + const fakeLabelName = ".L0 " + +-func gentext(ctxt *ld.Link, ldr *loader.Loader) {} ++func gentext(ctxt *ld.Link, ldr *loader.Loader) { ++ initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt) ++ if initfunc == nil { ++ return ++ } ++ ++ // Emit the following function: ++ // ++ // go.link.addmoduledatainit: ++ // auipc a0, %pcrel_hi(local.moduledata) ++ // addi a0, %pcrel_lo(local.moduledata) ++ // j runtime.addmoduledata ++ ++ sz := initfunc.AddSymRef(ctxt.Arch, ctxt.Moduledata, 0, objabi.R_RISCV_PCREL_ITYPE, 8) ++ initfunc.SetUint32(ctxt.Arch, sz-8, 0x00000517) // auipc a0, %pcrel_hi(local.moduledata) ++ initfunc.SetUint32(ctxt.Arch, sz-4, 0x00050513) // addi a0, %pcrel_lo(local.moduledata) ++ ++ sz = initfunc.AddSymRef(ctxt.Arch, addmoduledata, 0, objabi.R_RISCV_JAL, 4) ++ initfunc.SetUint32(ctxt.Arch, sz-4, 0x0000006f) // j runtime.addmoduledata ++} + + func findHI20Reloc(ldr *loader.Loader, s loader.Sym, val int64) *loader.Reloc { + outer := ldr.OuterSym(s) +diff --git a/src/internal/platform/supported.go b/src/internal/platform/supported.go +index a774247e6b..bad1a6c9c4 100644 +--- a/src/internal/platform/supported.go ++++ b/src/internal/platform/supported.go +@@ -207,7 +207,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { + + case "plugin": + switch platform { +- case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/loong64", "linux/s390x", "linux/ppc64le", ++ case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/loong64", "linux/riscv64", "linux/s390x", "linux/ppc64le", + "android/amd64", "android/386", + "darwin/amd64", "darwin/arm64", + "freebsd/amd64": +diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s +index 491635b1cf..231564aca2 100644 +--- a/src/runtime/asm_riscv64.s ++++ b/src/runtime/asm_riscv64.s +@@ -542,6 +542,15 @@ TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 + // traceback from goexit1 must hit code range of goexit + MOV ZERO, ZERO // NOP + ++ ++// This is called from .init_array and follows the platform, not the Go ABI. ++TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0 ++ // Use X31 as it is a scratch register in both the Go ABI and psABI. ++ MOV runtime·lastmoduledatap(SB), X31 ++ MOV X10, moduledata_next(X31) ++ MOV X10, runtime·lastmoduledatap(SB) ++ RET ++ + // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) + // See cgocall.go for more details. + TEXT ·cgocallback(SB),NOSPLIT,$24-24 +-- +2.48.1.windows.1 + diff --git a/1001-cmd-link-cmd-internal-add-R_GOT_PCREL_ITYPE_RELOC-fo.patch b/1001-cmd-link-cmd-internal-add-R_GOT_PCREL_ITYPE_RELOC-fo.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc42cafd79f19b2464edb163da503f50f97167ab --- /dev/null +++ b/1001-cmd-link-cmd-internal-add-R_GOT_PCREL_ITYPE_RELOC-fo.patch @@ -0,0 +1,236 @@ +From 94dcbbcb6dc39b6a3c7c686580cab81be567dc7f Mon Sep 17 00:00:00 2001 +From: Meng Zhuo +Date: Thu, 12 Sep 2024 20:03:59 +0800 +Subject: [PATCH] cmd/link,cmd/internal: add R_GOT_PCREL_ITYPE_RELOC for + riscv64 + +This CL adds new relocation type for riscv64: R_GOT_PCREL_ITYPE_RELOC +which generate an AUIPC + I-type pair with relocation type of GOT_HI20 +and PCREL_LO12_I. +According to RISCV elf psabi doc, medium position independent code +model, the GNU as example is: + +``` + # Calculate address of non-local symbol +.Ltmp3: aupipc a0, %got_pcrel_hi(symbol) + ld a0, %pcrel_lo(.Ltmp3)(a0) +``` + +Change-Id: I719dd05e009ca2d9291f0689b346c059f9c56918 +Reviewed-on: https://go-review.googlesource.com/c/go/+/612635 +Reviewed-by: Dmitri Shuralyov +Reviewed-by: Joel Sing +Reviewed-by: Cherry Mui +LUCI-TryBot-Result: Go LUCI +--- + src/cmd/internal/obj/riscv/cpu.go | 5 ++ + src/cmd/internal/obj/riscv/obj.go | 9 +++- + src/cmd/internal/objabi/reloctype.go | 4 ++ + src/cmd/internal/objabi/reloctype_string.go | 55 +++++++++++---------- + src/cmd/link/internal/riscv64/asm.go | 19 +++++-- + 5 files changed, 59 insertions(+), 33 deletions(-) + +diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go +index 43ed3bc1f0..a7e2c49a42 100644 +--- a/src/cmd/internal/obj/riscv/cpu.go ++++ b/src/cmd/internal/obj/riscv/cpu.go +@@ -283,6 +283,11 @@ const ( + // it is the first instruction in an AUIPC + S-type pair that needs a + // R_RISCV_PCREL_STYPE relocation. + NEED_PCREL_STYPE_RELOC ++ ++ // NEED_GOT_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that ++ // it is the first instruction in an AUIPC + I-type pair that needs a ++ // R_RISCV_GOT_PCREL_ITYPE relocation. ++ NEED_GOT_PCREL_ITYPE_RELOC + ) + + // RISC-V mnemonics, as defined in the "opcodes" and "opcodes-pseudo" files +diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go +index 44a2246e1f..96772a85f0 100644 +--- a/src/cmd/internal/obj/riscv/obj.go ++++ b/src/cmd/internal/obj/riscv/obj.go +@@ -365,11 +365,15 @@ func markRelocs(p *obj.Prog) { + switch p.From.Name { + case obj.NAME_EXTERN, obj.NAME_STATIC: + p.Mark |= NEED_PCREL_ITYPE_RELOC ++ case obj.NAME_GOTREF: ++ p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC + } + case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG: + switch p.From.Name { + case obj.NAME_EXTERN, obj.NAME_STATIC: + p.Mark |= NEED_PCREL_ITYPE_RELOC ++ case obj.NAME_GOTREF: ++ p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC + } + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: + switch p.To.Name { +@@ -2323,7 +2327,7 @@ func instructionsForMOV(p *obj.Prog) []*instruction { + // MOV c(Rs), Rd -> L $c, Rs, Rd + inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From)) + +- case obj.NAME_EXTERN, obj.NAME_STATIC: ++ case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF: + if p.From.Sym.Type == objabi.STLSBSS { + return instructionsForTLSLoad(p) + } +@@ -2707,6 +2711,9 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { + } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC { + rt = objabi.R_RISCV_PCREL_STYPE + addr = &p.To ++ } else if p.Mark&NEED_GOT_PCREL_ITYPE_RELOC == NEED_GOT_PCREL_ITYPE_RELOC { ++ rt = objabi.R_RISCV_GOT_PCREL_ITYPE ++ addr = &p.From + } else { + break + } +diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go +index 8b9927d6eb..587c792742 100644 +--- a/src/cmd/internal/objabi/reloctype.go ++++ b/src/cmd/internal/objabi/reloctype.go +@@ -291,6 +291,10 @@ const ( + // address. + R_RISCV_GOT_HI20 + ++ // R_RISCV_GOT_PCREL_ITYPE resolves a 32-bit PC-relative GOT entry ++ // address for an AUIPC + I-type instruction pair. ++ R_RISCV_GOT_PCREL_ITYPE ++ + // R_RISCV_PCREL_HI20 resolves the high 20 bits of a 32-bit PC-relative + // address. + R_RISCV_PCREL_HI20 +diff --git a/src/cmd/internal/objabi/reloctype_string.go b/src/cmd/internal/objabi/reloctype_string.go +index 6d8cbb5dd2..6a9abe6796 100644 +--- a/src/cmd/internal/objabi/reloctype_string.go ++++ b/src/cmd/internal/objabi/reloctype_string.go +@@ -1,4 +1,4 @@ +-// Code generated by "stringer -type=RelocType"; DO NOT EDIT. ++// Code generated by "stringer -type=RelocType .\reloctype.go"; DO NOT EDIT. + + package objabi + +@@ -75,35 +75,36 @@ func _() { + _ = x[R_RISCV_TLS_IE-65] + _ = x[R_RISCV_TLS_LE-66] + _ = x[R_RISCV_GOT_HI20-67] +- _ = x[R_RISCV_PCREL_HI20-68] +- _ = x[R_RISCV_PCREL_LO12_I-69] +- _ = x[R_RISCV_PCREL_LO12_S-70] +- _ = x[R_RISCV_BRANCH-71] +- _ = x[R_RISCV_RVC_BRANCH-72] +- _ = x[R_RISCV_RVC_JUMP-73] +- _ = x[R_PCRELDBL-74] +- _ = x[R_LOONG64_ADDR_HI-75] +- _ = x[R_LOONG64_ADDR_LO-76] +- _ = x[R_LOONG64_TLS_LE_HI-77] +- _ = x[R_LOONG64_TLS_LE_LO-78] +- _ = x[R_CALLLOONG64-79] +- _ = x[R_LOONG64_TLS_IE_HI-80] +- _ = x[R_LOONG64_TLS_IE_LO-81] +- _ = x[R_LOONG64_GOT_HI-82] +- _ = x[R_LOONG64_GOT_LO-83] +- _ = x[R_JMPLOONG64-84] +- _ = x[R_ADDRMIPSU-85] +- _ = x[R_ADDRMIPSTLS-86] +- _ = x[R_ADDRCUOFF-87] +- _ = x[R_WASMIMPORT-88] +- _ = x[R_XCOFFREF-89] +- _ = x[R_PEIMAGEOFF-90] +- _ = x[R_INITORDER-91] ++ _ = x[R_RISCV_GOT_PCREL_ITYPE-68] ++ _ = x[R_RISCV_PCREL_HI20-69] ++ _ = x[R_RISCV_PCREL_LO12_I-70] ++ _ = x[R_RISCV_PCREL_LO12_S-71] ++ _ = x[R_RISCV_BRANCH-72] ++ _ = x[R_RISCV_RVC_BRANCH-73] ++ _ = x[R_RISCV_RVC_JUMP-74] ++ _ = x[R_PCRELDBL-75] ++ _ = x[R_LOONG64_ADDR_HI-76] ++ _ = x[R_LOONG64_ADDR_LO-77] ++ _ = x[R_LOONG64_TLS_LE_HI-78] ++ _ = x[R_LOONG64_TLS_LE_LO-79] ++ _ = x[R_CALLLOONG64-80] ++ _ = x[R_LOONG64_TLS_IE_HI-81] ++ _ = x[R_LOONG64_TLS_IE_LO-82] ++ _ = x[R_LOONG64_GOT_HI-83] ++ _ = x[R_LOONG64_GOT_LO-84] ++ _ = x[R_JMPLOONG64-85] ++ _ = x[R_ADDRMIPSU-86] ++ _ = x[R_ADDRMIPSTLS-87] ++ _ = x[R_ADDRCUOFF-88] ++ _ = x[R_WASMIMPORT-89] ++ _ = x[R_XCOFFREF-90] ++ _ = x[R_PEIMAGEOFF-91] ++ _ = x[R_INITORDER-92] + } + +-const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_JALR_RISCV_JAL_TRAMPR_RISCV_CALLR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_LOONG64_ADDR_HIR_LOONG64_ADDR_LOR_LOONG64_TLS_LE_HIR_LOONG64_TLS_LE_LOR_CALLLOONG64R_LOONG64_TLS_IE_HIR_LOONG64_TLS_IE_LOR_LOONG64_GOT_HIR_LOONG64_GOT_LOR_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDER" ++const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_JALR_RISCV_JAL_TRAMPR_RISCV_CALLR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_GOT_PCREL_ITYPER_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_LOONG64_ADDR_HIR_LOONG64_ADDR_LOR_LOONG64_TLS_LE_HIR_LOONG64_TLS_LE_LOR_CALLLOONG64R_LOONG64_TLS_IE_HIR_LOONG64_TLS_IE_LOR_LOONG64_GOT_HIR_LOONG64_GOT_LOR_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDER" + +-var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 328, 344, 355, 368, 387, 407, 427, 447, 460, 474, 488, 502, 517, 531, 545, 556, 578, 600, 614, 629, 652, 669, 687, 708, 723, 742, 753, 770, 782, 801, 820, 834, 848, 864, 882, 902, 922, 936, 954, 970, 980, 997, 1014, 1033, 1052, 1065, 1084, 1103, 1119, 1135, 1147, 1158, 1171, 1182, 1194, 1204, 1216, 1227} ++var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 328, 344, 355, 368, 387, 407, 427, 447, 460, 474, 488, 502, 517, 531, 545, 556, 578, 600, 614, 629, 652, 669, 687, 708, 723, 742, 753, 770, 782, 801, 820, 834, 848, 864, 887, 905, 925, 945, 959, 977, 993, 1003, 1020, 1037, 1056, 1075, 1088, 1107, 1126, 1142, 1158, 1170, 1181, 1194, 1205, 1217, 1227, 1239, 1250} + + func (i RelocType) String() string { + i -= 1 +diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go +index a9583d21aa..81644ea3b6 100644 +--- a/src/cmd/link/internal/riscv64/asm.go ++++ b/src/cmd/link/internal/riscv64/asm.go +@@ -189,8 +189,11 @@ func genSymsLate(ctxt *ld.Link, ldr *loader.Loader) { + relocs := ldr.Relocs(s) + for ri := 0; ri < relocs.Count(); ri++ { + r := relocs.At(ri) +- if r.Type() != objabi.R_RISCV_CALL && r.Type() != objabi.R_RISCV_PCREL_ITYPE && +- r.Type() != objabi.R_RISCV_PCREL_STYPE && r.Type() != objabi.R_RISCV_TLS_IE { ++ if r.Type() != objabi.R_RISCV_CALL && ++ r.Type() != objabi.R_RISCV_PCREL_ITYPE && ++ r.Type() != objabi.R_RISCV_PCREL_STYPE && ++ r.Type() != objabi.R_RISCV_TLS_IE && ++ r.Type() != objabi.R_RISCV_GOT_PCREL_ITYPE { + continue + } + if r.Off() == 0 && ldr.SymType(s) == sym.STEXT { +@@ -252,7 +255,11 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, + out.Write64(uint64(elf.R_RISCV_JAL) | uint64(elfsym)<<32) + out.Write64(uint64(r.Xadd)) + +- case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE: ++ case objabi.R_RISCV_CALL, ++ objabi.R_RISCV_PCREL_ITYPE, ++ objabi.R_RISCV_PCREL_STYPE, ++ objabi.R_RISCV_TLS_IE, ++ objabi.R_RISCV_GOT_PCREL_ITYPE: + // Find the text symbol for the AUIPC instruction targeted + // by this relocation. + relocs := ldr.Relocs(s) +@@ -281,6 +288,8 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, + hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_S + case objabi.R_RISCV_TLS_IE: + hiRel, loRel = elf.R_RISCV_TLS_GOT_HI20, elf.R_RISCV_PCREL_LO12_I ++ case objabi.R_RISCV_GOT_PCREL_ITYPE: ++ hiRel, loRel = elf.R_RISCV_GOT_HI20, elf.R_RISCV_PCREL_LO12_I + } + out.Write64(uint64(sectoff)) + out.Write64(uint64(hiRel) | uint64(elfsym)<<32) +@@ -445,7 +454,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade + case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP: + return val, 1, true + +- case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE: ++ case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE, objabi.R_RISCV_GOT_PCREL_ITYPE: + return val, 2, true + } + +@@ -645,7 +654,7 @@ func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sy + case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP: + return ld.ExtrelocSimple(ldr, r), true + +- case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE: ++ case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE, objabi.R_RISCV_GOT_PCREL_ITYPE: + return ld.ExtrelocViaOuterSym(ldr, r, s), true + } + return loader.ExtReloc{}, false +-- +2.48.1.windows.1 + diff --git a/1002-cmd-compile-don-t-merge-symbols-on-riscv64-when-dyna.patch b/1002-cmd-compile-don-t-merge-symbols-on-riscv64-when-dyna.patch new file mode 100644 index 0000000000000000000000000000000000000000..010f3eabcd06939c89d3683a3f6a825b2aadbebd --- /dev/null +++ b/1002-cmd-compile-don-t-merge-symbols-on-riscv64-when-dyna.patch @@ -0,0 +1,589 @@ +From f11737fca5ac7ec43bbd25c07bae6faa6319cddc Mon Sep 17 00:00:00 2001 +From: Meng Zhuo +Date: Thu, 12 Sep 2024 19:46:20 +0800 +Subject: [PATCH] cmd/compile: don't merge symbols on riscv64 when dynamic + linking + +Each plugin is compiled as a separate shared object, +with its own symbol table. When dynamic linking plugin symbols +are resolved within the plugin's scope, not globally merged to +avoid conflicts. + +Change-Id: I9e6986085855c17fbd6c39b937cb6129d216f5e9 +Reviewed-on: https://go-review.googlesource.com/c/go/+/435015 +LUCI-TryBot-Result: Go LUCI +Reviewed-by: Joel Sing +Reviewed-by: Michael Pratt +Reviewed-by: Cherry Mui +--- + .../compile/internal/ssa/_gen/RISCV64.rules | 82 +++------- + .../compile/internal/ssa/rewriteRISCV64.go | 154 +++++++++++------- + 2 files changed, 115 insertions(+), 121 deletions(-) + +diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules +index c2df433315..00d0d91b46 100644 +--- a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules ++++ b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules +@@ -271,65 +271,29 @@ + + // We need to fold MOVaddr into the LD/MOVDstore ops so that the live variable analysis + // knows what variables are being read/written by the ops. +-(MOVBUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} base mem) +-(MOVBload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem) +-(MOVHUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} base mem) +-(MOVHload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVHload [off1+off2] {mergeSym(sym1,sym2)} base mem) +-(MOVWUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} base mem) +-(MOVWload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem) +-(MOVDload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem) +- +-(MOVBstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +-(MOVHstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +-(MOVWstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +-(MOVDstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => +- (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +-(MOVBstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) => +- (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) +-(MOVHstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) => +- (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) +-(MOVWstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) => +- (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) +-(MOVDstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) => +- (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) +- +-(MOVBUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => +- (MOVBUload [off1+int32(off2)] {sym} base mem) +-(MOVBload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => +- (MOVBload [off1+int32(off2)] {sym} base mem) +-(MOVHUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => +- (MOVHUload [off1+int32(off2)] {sym} base mem) +-(MOVHload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => +- (MOVHload [off1+int32(off2)] {sym} base mem) +-(MOVWUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => +- (MOVWUload [off1+int32(off2)] {sym} base mem) +-(MOVWload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => +- (MOVWload [off1+int32(off2)] {sym} base mem) +-(MOVDload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => +- (MOVDload [off1+int32(off2)] {sym} base mem) +- +-(MOVBstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) => +- (MOVBstore [off1+int32(off2)] {sym} base val mem) +-(MOVHstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) => +- (MOVHstore [off1+int32(off2)] {sym} base val mem) +-(MOVWstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) => +- (MOVWstore [off1+int32(off2)] {sym} base val mem) +-(MOVDstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) => +- (MOVDstore [off1+int32(off2)] {sym} base val mem) +-(MOVBstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVBstorezero [off1+int32(off2)] {sym} ptr mem) +-(MOVHstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVHstorezero [off1+int32(off2)] {sym} ptr mem) +-(MOVWstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVWstorezero [off1+int32(off2)] {sym} ptr mem) +-(MOVDstorezero [off1] {sym} (ADDI [off2] ptr) mem) && is32Bit(int64(off1)+off2) => (MOVDstorezero [off1+int32(off2)] {sym} ptr mem) ++(MOV(B|BU|H|HU|W|WU|D)load [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && ++ is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && ++ (base.Op != OpSB || !config.ctxt.Flag_dynlink) => ++ (MOV(B|BU|H|HU|W|WU|D)load [off1+off2] {mergeSym(sym1,sym2)} base mem) ++ ++(MOV(B|H|W|D)store [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && ++ is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && ++ (base.Op != OpSB || !config.ctxt.Flag_dynlink) => ++ (MOV(B|H|W|D)store [off1+off2] {mergeSym(sym1,sym2)} base val mem) ++ ++(MOV(B|H|W|D)storezero [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && ++ canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && ++ (base.Op != OpSB || !config.ctxt.Flag_dynlink) => ++ (MOV(B|H|W|D)storezero [off1+off2] {mergeSym(sym1,sym2)} base mem) ++ ++(MOV(B|BU|H|HU|W|WU|D)load [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => ++ (MOV(B|BU|H|HU|W|WU|D)load [off1+int32(off2)] {sym} base mem) ++ ++(MOV(B|H|W|D)store [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) => ++ (MOV(B|H|W|D)store [off1+int32(off2)] {sym} base val mem) ++ ++(MOV(B|H|W|D)storezero [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) => ++ (MOV(B|H|W|D)storezero [off1+int32(off2)] {sym} base mem) + + // Similarly, fold ADDI into MOVaddr to avoid confusing live variable analysis + // with OffPtr -> ADDI. +diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go +index f033b25bdd..9243702508 100644 +--- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go ++++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go +@@ -3870,8 +3870,10 @@ func rewriteValueRISCV64_OpRISCV64FSUBS(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVBUload(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVBUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -3883,7 +3885,7 @@ func rewriteValueRISCV64_OpRISCV64MOVBUload(v *Value) bool { + sym2 := auxToSym(v_0.Aux) + base := v_0.Args[0] + mem := v_1 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVBUload) +@@ -4177,8 +4179,10 @@ func rewriteValueRISCV64_OpRISCV64MOVBUreg(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVBload(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVBload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -4190,7 +4194,7 @@ func rewriteValueRISCV64_OpRISCV64MOVBload(v *Value) bool { + sym2 := auxToSym(v_0.Aux) + base := v_0.Args[0] + mem := v_1 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVBload) +@@ -4303,8 +4307,10 @@ func rewriteValueRISCV64_OpRISCV64MOVBstore(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVBstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -4317,7 +4323,7 @@ func rewriteValueRISCV64_OpRISCV64MOVBstore(v *Value) bool { + base := v_0.Args[0] + val := v_1 + mem := v_2 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVBstore) +@@ -4471,9 +4477,11 @@ func rewriteValueRISCV64_OpRISCV64MOVBstore(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVBstorezero(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] +- // match: (MOVBstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) +- // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) +- // result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) ++ b := v.Block ++ config := b.Func.Config ++ // match: (MOVBstorezero [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) ++ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) ++ // result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) + sym1 := auxToSym(v.Aux) +@@ -4482,20 +4490,20 @@ func rewriteValueRISCV64_OpRISCV64MOVBstorezero(v *Value) bool { + } + off2 := auxIntToInt32(v_0.AuxInt) + sym2 := auxToSym(v_0.Aux) +- ptr := v_0.Args[0] ++ base := v_0.Args[0] + mem := v_1 +- if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { ++ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVBstorezero) + v.AuxInt = int32ToAuxInt(off1 + off2) + v.Aux = symToAux(mergeSym(sym1, sym2)) +- v.AddArg2(ptr, mem) ++ v.AddArg2(base, mem) + return true + } +- // match: (MOVBstorezero [off1] {sym} (ADDI [off2] ptr) mem) ++ // match: (MOVBstorezero [off1] {sym} (ADDI [off2] base) mem) + // cond: is32Bit(int64(off1)+off2) +- // result: (MOVBstorezero [off1+int32(off2)] {sym} ptr mem) ++ // result: (MOVBstorezero [off1+int32(off2)] {sym} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) +@@ -4503,7 +4511,7 @@ func rewriteValueRISCV64_OpRISCV64MOVBstorezero(v *Value) bool { + break + } + off2 := auxIntToInt64(v_0.AuxInt) +- ptr := v_0.Args[0] ++ base := v_0.Args[0] + mem := v_1 + if !(is32Bit(int64(off1) + off2)) { + break +@@ -4511,7 +4519,7 @@ func rewriteValueRISCV64_OpRISCV64MOVBstorezero(v *Value) bool { + v.reset(OpRISCV64MOVBstorezero) + v.AuxInt = int32ToAuxInt(off1 + int32(off2)) + v.Aux = symToAux(sym) +- v.AddArg2(ptr, mem) ++ v.AddArg2(base, mem) + return true + } + return false +@@ -4519,8 +4527,10 @@ func rewriteValueRISCV64_OpRISCV64MOVBstorezero(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVDload(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVDload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -4532,7 +4542,7 @@ func rewriteValueRISCV64_OpRISCV64MOVDload(v *Value) bool { + sym2 := auxToSym(v_0.Aux) + base := v_0.Args[0] + mem := v_1 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVDload) +@@ -4599,8 +4609,10 @@ func rewriteValueRISCV64_OpRISCV64MOVDstore(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVDstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -4613,7 +4625,7 @@ func rewriteValueRISCV64_OpRISCV64MOVDstore(v *Value) bool { + base := v_0.Args[0] + val := v_1 + mem := v_2 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVDstore) +@@ -4665,9 +4677,11 @@ func rewriteValueRISCV64_OpRISCV64MOVDstore(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVDstorezero(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] +- // match: (MOVDstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) +- // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) +- // result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) ++ b := v.Block ++ config := b.Func.Config ++ // match: (MOVDstorezero [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) ++ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) ++ // result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) + sym1 := auxToSym(v.Aux) +@@ -4676,20 +4690,20 @@ func rewriteValueRISCV64_OpRISCV64MOVDstorezero(v *Value) bool { + } + off2 := auxIntToInt32(v_0.AuxInt) + sym2 := auxToSym(v_0.Aux) +- ptr := v_0.Args[0] ++ base := v_0.Args[0] + mem := v_1 +- if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { ++ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVDstorezero) + v.AuxInt = int32ToAuxInt(off1 + off2) + v.Aux = symToAux(mergeSym(sym1, sym2)) +- v.AddArg2(ptr, mem) ++ v.AddArg2(base, mem) + return true + } +- // match: (MOVDstorezero [off1] {sym} (ADDI [off2] ptr) mem) ++ // match: (MOVDstorezero [off1] {sym} (ADDI [off2] base) mem) + // cond: is32Bit(int64(off1)+off2) +- // result: (MOVDstorezero [off1+int32(off2)] {sym} ptr mem) ++ // result: (MOVDstorezero [off1+int32(off2)] {sym} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) +@@ -4697,7 +4711,7 @@ func rewriteValueRISCV64_OpRISCV64MOVDstorezero(v *Value) bool { + break + } + off2 := auxIntToInt64(v_0.AuxInt) +- ptr := v_0.Args[0] ++ base := v_0.Args[0] + mem := v_1 + if !(is32Bit(int64(off1) + off2)) { + break +@@ -4705,7 +4719,7 @@ func rewriteValueRISCV64_OpRISCV64MOVDstorezero(v *Value) bool { + v.reset(OpRISCV64MOVDstorezero) + v.AuxInt = int32ToAuxInt(off1 + int32(off2)) + v.Aux = symToAux(sym) +- v.AddArg2(ptr, mem) ++ v.AddArg2(base, mem) + return true + } + return false +@@ -4713,8 +4727,10 @@ func rewriteValueRISCV64_OpRISCV64MOVDstorezero(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVHUload(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVHUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -4726,7 +4742,7 @@ func rewriteValueRISCV64_OpRISCV64MOVHUload(v *Value) bool { + sym2 := auxToSym(v_0.Aux) + base := v_0.Args[0] + mem := v_1 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVHUload) +@@ -4877,8 +4893,10 @@ func rewriteValueRISCV64_OpRISCV64MOVHUreg(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVHload(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVHload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -4890,7 +4908,7 @@ func rewriteValueRISCV64_OpRISCV64MOVHload(v *Value) bool { + sym2 := auxToSym(v_0.Aux) + base := v_0.Args[0] + mem := v_1 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVHload) +@@ -5047,8 +5065,10 @@ func rewriteValueRISCV64_OpRISCV64MOVHstore(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVHstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -5061,7 +5081,7 @@ func rewriteValueRISCV64_OpRISCV64MOVHstore(v *Value) bool { + base := v_0.Args[0] + val := v_1 + mem := v_2 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVHstore) +@@ -5181,9 +5201,11 @@ func rewriteValueRISCV64_OpRISCV64MOVHstore(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVHstorezero(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] +- // match: (MOVHstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) +- // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) +- // result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) ++ b := v.Block ++ config := b.Func.Config ++ // match: (MOVHstorezero [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) ++ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) ++ // result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) + sym1 := auxToSym(v.Aux) +@@ -5192,20 +5214,20 @@ func rewriteValueRISCV64_OpRISCV64MOVHstorezero(v *Value) bool { + } + off2 := auxIntToInt32(v_0.AuxInt) + sym2 := auxToSym(v_0.Aux) +- ptr := v_0.Args[0] ++ base := v_0.Args[0] + mem := v_1 +- if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { ++ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVHstorezero) + v.AuxInt = int32ToAuxInt(off1 + off2) + v.Aux = symToAux(mergeSym(sym1, sym2)) +- v.AddArg2(ptr, mem) ++ v.AddArg2(base, mem) + return true + } +- // match: (MOVHstorezero [off1] {sym} (ADDI [off2] ptr) mem) ++ // match: (MOVHstorezero [off1] {sym} (ADDI [off2] base) mem) + // cond: is32Bit(int64(off1)+off2) +- // result: (MOVHstorezero [off1+int32(off2)] {sym} ptr mem) ++ // result: (MOVHstorezero [off1+int32(off2)] {sym} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) +@@ -5213,7 +5235,7 @@ func rewriteValueRISCV64_OpRISCV64MOVHstorezero(v *Value) bool { + break + } + off2 := auxIntToInt64(v_0.AuxInt) +- ptr := v_0.Args[0] ++ base := v_0.Args[0] + mem := v_1 + if !(is32Bit(int64(off1) + off2)) { + break +@@ -5221,7 +5243,7 @@ func rewriteValueRISCV64_OpRISCV64MOVHstorezero(v *Value) bool { + v.reset(OpRISCV64MOVHstorezero) + v.AuxInt = int32ToAuxInt(off1 + int32(off2)) + v.Aux = symToAux(sym) +- v.AddArg2(ptr, mem) ++ v.AddArg2(base, mem) + return true + } + return false +@@ -5229,8 +5251,10 @@ func rewriteValueRISCV64_OpRISCV64MOVHstorezero(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVWUload(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVWUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -5242,7 +5266,7 @@ func rewriteValueRISCV64_OpRISCV64MOVWUload(v *Value) bool { + sym2 := auxToSym(v_0.Aux) + base := v_0.Args[0] + mem := v_1 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVWUload) +@@ -5417,8 +5441,10 @@ func rewriteValueRISCV64_OpRISCV64MOVWUreg(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVWload(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVWload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -5430,7 +5456,7 @@ func rewriteValueRISCV64_OpRISCV64MOVWload(v *Value) bool { + sym2 := auxToSym(v_0.Aux) + base := v_0.Args[0] + mem := v_1 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVWload) +@@ -5741,8 +5767,10 @@ func rewriteValueRISCV64_OpRISCV64MOVWstore(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] ++ b := v.Block ++ config := b.Func.Config + // match: (MOVWstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) +- // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) ++ // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) + // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := auxIntToInt32(v.AuxInt) +@@ -5755,7 +5783,7 @@ func rewriteValueRISCV64_OpRISCV64MOVWstore(v *Value) bool { + base := v_0.Args[0] + val := v_1 + mem := v_2 +- if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2)) { ++ if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVWstore) +@@ -5841,9 +5869,11 @@ func rewriteValueRISCV64_OpRISCV64MOVWstore(v *Value) bool { + func rewriteValueRISCV64_OpRISCV64MOVWstorezero(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] +- // match: (MOVWstorezero [off1] {sym1} (MOVaddr [off2] {sym2} ptr) mem) +- // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) +- // result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) ++ b := v.Block ++ config := b.Func.Config ++ // match: (MOVWstorezero [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) ++ // cond: canMergeSym(sym1,sym2) && is32Bit(int64(off1)+int64(off2)) && (base.Op != OpSB || !config.ctxt.Flag_dynlink) ++ // result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) + sym1 := auxToSym(v.Aux) +@@ -5852,20 +5882,20 @@ func rewriteValueRISCV64_OpRISCV64MOVWstorezero(v *Value) bool { + } + off2 := auxIntToInt32(v_0.AuxInt) + sym2 := auxToSym(v_0.Aux) +- ptr := v_0.Args[0] ++ base := v_0.Args[0] + mem := v_1 +- if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { ++ if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) { + break + } + v.reset(OpRISCV64MOVWstorezero) + v.AuxInt = int32ToAuxInt(off1 + off2) + v.Aux = symToAux(mergeSym(sym1, sym2)) +- v.AddArg2(ptr, mem) ++ v.AddArg2(base, mem) + return true + } +- // match: (MOVWstorezero [off1] {sym} (ADDI [off2] ptr) mem) ++ // match: (MOVWstorezero [off1] {sym} (ADDI [off2] base) mem) + // cond: is32Bit(int64(off1)+off2) +- // result: (MOVWstorezero [off1+int32(off2)] {sym} ptr mem) ++ // result: (MOVWstorezero [off1+int32(off2)] {sym} base mem) + for { + off1 := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) +@@ -5873,7 +5903,7 @@ func rewriteValueRISCV64_OpRISCV64MOVWstorezero(v *Value) bool { + break + } + off2 := auxIntToInt64(v_0.AuxInt) +- ptr := v_0.Args[0] ++ base := v_0.Args[0] + mem := v_1 + if !(is32Bit(int64(off1) + off2)) { + break +@@ -5881,7 +5911,7 @@ func rewriteValueRISCV64_OpRISCV64MOVWstorezero(v *Value) bool { + v.reset(OpRISCV64MOVWstorezero) + v.AuxInt = int32ToAuxInt(off1 + int32(off2)) + v.Aux = symToAux(sym) +- v.AddArg2(ptr, mem) ++ v.AddArg2(base, mem) + return true + } + return false +-- +2.48.1.windows.1 + diff --git a/backport-0001-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch b/backport-0001-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch deleted file mode 100644 index 7ee3178954539d2f4be6d3d16c008c9137cca16a..0000000000000000000000000000000000000000 --- a/backport-0001-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 5dfc2e6c42724349a9e9ecbcc69be920c18d90e9 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Thu, 18 Jan 2024 12:51:13 -0800 -Subject: [PATCH 1/4] [release-branch.go1.21] crypto/x509: make sure pub key is - non-nil before interface conversion - -alreadyInChain assumes all keys fit a interface which contains the -Equal method (which they do), but this ignores that certificates may -have a nil key when PublicKeyAlgorithm is UnknownPublicKeyAlgorithm. In -this case alreadyInChain panics. - -Check that the key is non-nil as part of considerCandidate (we are never -going to build a chain containing UnknownPublicKeyAlgorithm anyway). - -For #65390 -Fixes #65392 -Fixes CVE-2024-24783 - -Change-Id: Ibdccc0a487e3368b6812be35daad2512220243f3 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2137282 -Reviewed-by: Damien Neil -Run-TryBot: Roland Shoemaker -Reviewed-by: Tatiana Bradley -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173774 -Reviewed-by: Roland Shoemaker -Reviewed-by: Carlos Amedee -Reviewed-on: https://go-review.googlesource.com/c/go/+/569238 -Auto-Submit: Michael Knyszek -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Carlos Amedee ---- - src/crypto/x509/verify.go | 2 +- - src/crypto/x509/verify_test.go | 19 +++++++++++++++++++ - 2 files changed, 20 insertions(+), 1 deletion(-) - -diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go -index 345d434453c..56a1a1725cc 100644 ---- a/src/crypto/x509/verify.go -+++ b/src/crypto/x509/verify.go -@@ -899,7 +899,7 @@ func (c *Certificate) buildChains(currentChain []*Certificate, sigChecks *int, o - ) - - considerCandidate := func(certType int, candidate *Certificate) { -- if alreadyInChain(candidate, currentChain) { -+ if candidate.PublicKey == nil || alreadyInChain(candidate, currentChain) { - return - } - -diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go -index 3551b470ced..d8678d03f93 100644 ---- a/src/crypto/x509/verify_test.go -+++ b/src/crypto/x509/verify_test.go -@@ -2693,3 +2693,22 @@ func TestVerifyEKURootAsLeaf(t *testing.T) { - } - - } -+ -+func TestVerifyNilPubKey(t *testing.T) { -+ c := &Certificate{ -+ RawIssuer: []byte{1, 2, 3}, -+ AuthorityKeyId: []byte{1, 2, 3}, -+ } -+ opts := &VerifyOptions{} -+ opts.Roots = NewCertPool() -+ r := &Certificate{ -+ RawSubject: []byte{1, 2, 3}, -+ SubjectKeyId: []byte{1, 2, 3}, -+ } -+ opts.Roots.AddCert(r) -+ -+ _, err := c.buildChains([]*Certificate{r}, nil, opts) -+ if _, ok := err.(UnknownAuthorityError); !ok { -+ t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{}) -+ } -+} --- -2.33.0 - diff --git a/backport-0002-release-branch.go1.21-html-template-escape-additiona.patch b/backport-0002-release-branch.go1.21-html-template-escape-additiona.patch deleted file mode 100644 index 403cf6be5088fd97556b3871884641a3afa75d72..0000000000000000000000000000000000000000 --- a/backport-0002-release-branch.go1.21-html-template-escape-additiona.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 0787ee55dd0d42dd8bef97d4e7ed7584f44c16e9 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Wed, 14 Feb 2024 17:18:36 -0800 -Subject: [PATCH 2/4] [release-branch.go1.21] html/template: escape additional - tokens in MarshalJSON errors - -Escape " -Reviewed-by: Damien Neil -(cherry picked from commit ccbc725f2d678255df1bd326fa511a492aa3a0aa) -Reviewed-on: https://go-review.googlesource.com/c/go/+/567515 -Reviewed-by: Carlos Amedee ---- - src/html/template/js.go | 22 ++++++++- - src/html/template/js_test.go | 96 ++++++++++++++++++++---------------- - 2 files changed, 74 insertions(+), 44 deletions(-) - -diff --git a/src/html/template/js.go b/src/html/template/js.go -index 4e05c145572..f4d1303bebe 100644 ---- a/src/html/template/js.go -+++ b/src/html/template/js.go -@@ -171,13 +171,31 @@ func jsValEscaper(args ...any) string { - // cyclic data. This may be an unacceptable DoS risk. - b, err := json.Marshal(a) - if err != nil { -- // Put a space before comment so that if it is flush against -+ // While the standard JSON marshaller does not include user controlled -+ // information in the error message, if a type has a MarshalJSON method, -+ // the content of the error message is not guaranteed. Since we insert -+ // the error into the template, as part of a comment, we attempt to -+ // prevent the error from either terminating the comment, or the script -+ // block itself. -+ // -+ // In particular we: -+ // * replace "*/" comment end tokens with "* /", which does not -+ // terminate the comment -+ // * replace " 1 so this loses precision in JS - // but it is still a representable integer literal. -- {uint64(1)<<53 + 1, " 9007199254740993 "}, -- {float32(1.0), " 1 "}, -- {float32(-1.0), " -1 "}, -- {float32(0.5), " 0.5 "}, -- {float32(-0.5), " -0.5 "}, -- {float32(1.0) / float32(256), " 0.00390625 "}, -- {float32(0), " 0 "}, -- {math.Copysign(0, -1), " -0 "}, -- {float64(1.0), " 1 "}, -- {float64(-1.0), " -1 "}, -- {float64(0.5), " 0.5 "}, -- {float64(-0.5), " -0.5 "}, -- {float64(0), " 0 "}, -- {math.Copysign(0, -1), " -0 "}, -- {"", `""`}, -- {"foo", `"foo"`}, -+ {uint64(1)<<53 + 1, " 9007199254740993 ", false}, -+ {float32(1.0), " 1 ", false}, -+ {float32(-1.0), " -1 ", false}, -+ {float32(0.5), " 0.5 ", false}, -+ {float32(-0.5), " -0.5 ", false}, -+ {float32(1.0) / float32(256), " 0.00390625 ", false}, -+ {float32(0), " 0 ", false}, -+ {math.Copysign(0, -1), " -0 ", false}, -+ {float64(1.0), " 1 ", false}, -+ {float64(-1.0), " -1 ", false}, -+ {float64(0.5), " 0.5 ", false}, -+ {float64(-0.5), " -0.5 ", false}, -+ {float64(0), " 0 ", false}, -+ {math.Copysign(0, -1), " -0 ", false}, -+ {"", `""`, false}, -+ {"foo", `"foo"`, false}, - // Newlines. -- {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`}, -+ {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`, false}, - // "\v" == "v" on IE 6 so use "\u000b" instead. -- {"\t\x0b", `"\t\u000b"`}, -- {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`}, -- {[]any{}, "[]"}, -- {[]any{42, "foo", nil}, `[42,"foo",null]`}, -- {[]string{""}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`}, -- {"", `"--\u003e"`}, -- {"", `"]]\u003e"`}, -- {"", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`, false}, -+ {"", `"--\u003e"`, false}, -+ {"", `"]]\u003e"`, false}, -+ {" -Date: Tue, 16 Jan 2024 15:37:52 -0800 -Subject: [PATCH 3/4] [release-branch.go1.21] net/textproto, mime/multipart: - avoid unbounded read in MIME header - -mime/multipart.Reader.ReadForm allows specifying the maximum amount -of memory that will be consumed by the form. While this limit is -correctly applied to the parsed form data structure, it was not -being applied to individual header lines in a form. - -For example, when presented with a form containing a header line -that never ends, ReadForm will continue to read the line until it -runs out of memory. - -Limit the amount of data consumed when reading a header. - -Fixes CVE-2023-45290 -Fixes #65389 -For #65383 - -Change-Id: I7f9264d25752009e95f6b2c80e3d76aaf321d658 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2134435 -Reviewed-by: Roland Shoemaker -Reviewed-by: Tatiana Bradley -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173776 -Reviewed-by: Carlos Amedee -Reviewed-on: https://go-review.googlesource.com/c/go/+/569240 -Auto-Submit: Michael Knyszek -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Carlos Amedee ---- - src/mime/multipart/formdata_test.go | 42 +++++++++++++++++++++++++ - src/net/textproto/reader.go | 48 ++++++++++++++++++++--------- - src/net/textproto/reader_test.go | 12 ++++++++ - 3 files changed, 87 insertions(+), 15 deletions(-) - -diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go -index d422729c96a..bfa9f683825 100644 ---- a/src/mime/multipart/formdata_test.go -+++ b/src/mime/multipart/formdata_test.go -@@ -452,6 +452,48 @@ func TestReadFormLimits(t *testing.T) { - } - } - -+func TestReadFormEndlessHeaderLine(t *testing.T) { -+ for _, test := range []struct { -+ name string -+ prefix string -+ }{{ -+ name: "name", -+ prefix: "X-", -+ }, { -+ name: "value", -+ prefix: "X-Header: ", -+ }, { -+ name: "continuation", -+ prefix: "X-Header: foo\r\n ", -+ }} { -+ t.Run(test.name, func(t *testing.T) { -+ const eol = "\r\n" -+ s := `--boundary` + eol -+ s += `Content-Disposition: form-data; name="a"` + eol -+ s += `Content-Type: text/plain` + eol -+ s += test.prefix -+ fr := io.MultiReader( -+ strings.NewReader(s), -+ neverendingReader('X'), -+ ) -+ r := NewReader(fr, "boundary") -+ _, err := r.ReadForm(1 << 20) -+ if err != ErrMessageTooLarge { -+ t.Fatalf("ReadForm(1 << 20): %v, want ErrMessageTooLarge", err) -+ } -+ }) -+ } -+} -+ -+type neverendingReader byte -+ -+func (r neverendingReader) Read(p []byte) (n int, err error) { -+ for i := range p { -+ p[i] = byte(r) -+ } -+ return len(p), nil -+} -+ - func BenchmarkReadForm(b *testing.B) { - for _, test := range []struct { - name string -diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go -index fc2590b1cdc..fcd1a011ac7 100644 ---- a/src/net/textproto/reader.go -+++ b/src/net/textproto/reader.go -@@ -16,6 +16,10 @@ import ( - "sync" - ) - -+// TODO: This should be a distinguishable error (ErrMessageTooLarge) -+// to allow mime/multipart to detect it. -+var errMessageTooLarge = errors.New("message too large") -+ - // A Reader implements convenience methods for reading requests - // or responses from a text protocol network connection. - type Reader struct { -@@ -36,20 +40,23 @@ func NewReader(r *bufio.Reader) *Reader { - // ReadLine reads a single line from r, - // eliding the final \n or \r\n from the returned string. - func (r *Reader) ReadLine() (string, error) { -- line, err := r.readLineSlice() -+ line, err := r.readLineSlice(-1) - return string(line), err - } - - // ReadLineBytes is like ReadLine but returns a []byte instead of a string. - func (r *Reader) ReadLineBytes() ([]byte, error) { -- line, err := r.readLineSlice() -+ line, err := r.readLineSlice(-1) - if line != nil { - line = bytes.Clone(line) - } - return line, err - } - --func (r *Reader) readLineSlice() ([]byte, error) { -+// readLineSlice reads a single line from r, -+// up to lim bytes long (or unlimited if lim is less than 0), -+// eliding the final \r or \r\n from the returned string. -+func (r *Reader) readLineSlice(lim int64) ([]byte, error) { - r.closeDot() - var line []byte - for { -@@ -57,6 +64,9 @@ func (r *Reader) readLineSlice() ([]byte, error) { - if err != nil { - return nil, err - } -+ if lim >= 0 && int64(len(line))+int64(len(l)) > lim { -+ return nil, errMessageTooLarge -+ } - // Avoid the copy if the first call produced a full line. - if line == nil && !more { - return l, nil -@@ -88,7 +98,7 @@ func (r *Reader) readLineSlice() ([]byte, error) { - // - // Empty lines are never continued. - func (r *Reader) ReadContinuedLine() (string, error) { -- line, err := r.readContinuedLineSlice(noValidation) -+ line, err := r.readContinuedLineSlice(-1, noValidation) - return string(line), err - } - -@@ -109,7 +119,7 @@ func trim(s []byte) []byte { - // ReadContinuedLineBytes is like ReadContinuedLine but - // returns a []byte instead of a string. - func (r *Reader) ReadContinuedLineBytes() ([]byte, error) { -- line, err := r.readContinuedLineSlice(noValidation) -+ line, err := r.readContinuedLineSlice(-1, noValidation) - if line != nil { - line = bytes.Clone(line) - } -@@ -120,13 +130,14 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) { - // returning a byte slice with all lines. The validateFirstLine function - // is run on the first read line, and if it returns an error then this - // error is returned from readContinuedLineSlice. --func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) { -+// It reads up to lim bytes of data (or unlimited if lim is less than 0). -+func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) { - if validateFirstLine == nil { - return nil, fmt.Errorf("missing validateFirstLine func") - } - - // Read the first line. -- line, err := r.readLineSlice() -+ line, err := r.readLineSlice(lim) - if err != nil { - return nil, err - } -@@ -154,13 +165,21 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([ - // copy the slice into buf. - r.buf = append(r.buf[:0], trim(line)...) - -+ if lim < 0 { -+ lim = math.MaxInt64 -+ } -+ lim -= int64(len(r.buf)) -+ - // Read continuation lines. - for r.skipSpace() > 0 { -- line, err := r.readLineSlice() -+ r.buf = append(r.buf, ' ') -+ if int64(len(r.buf)) >= lim { -+ return nil, errMessageTooLarge -+ } -+ line, err := r.readLineSlice(lim - int64(len(r.buf))) - if err != nil { - break - } -- r.buf = append(r.buf, ' ') - r.buf = append(r.buf, trim(line)...) - } - return r.buf, nil -@@ -507,7 +526,8 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) - - // The first line cannot start with a leading space. - if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') { -- line, err := r.readLineSlice() -+ const errorLimit = 80 // arbitrary limit on how much of the line we'll quote -+ line, err := r.readLineSlice(errorLimit) - if err != nil { - return m, err - } -@@ -515,7 +535,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) - } - - for { -- kv, err := r.readContinuedLineSlice(mustHaveFieldNameColon) -+ kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon) - if len(kv) == 0 { - return m, err - } -@@ -544,7 +564,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) - - maxHeaders-- - if maxHeaders < 0 { -- return nil, errors.New("message too large") -+ return nil, errMessageTooLarge - } - - // Skip initial spaces in value. -@@ -557,9 +577,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) - } - maxMemory -= int64(len(value)) - if maxMemory < 0 { -- // TODO: This should be a distinguishable error (ErrMessageTooLarge) -- // to allow mime/multipart to detect it. -- return m, errors.New("message too large") -+ return m, errMessageTooLarge - } - if vv == nil && len(strs) > 0 { - // More than likely this will be a single-element key. -diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go -index 696ae406f38..26ff617470b 100644 ---- a/src/net/textproto/reader_test.go -+++ b/src/net/textproto/reader_test.go -@@ -36,6 +36,18 @@ func TestReadLine(t *testing.T) { - } - } - -+func TestReadLineLongLine(t *testing.T) { -+ line := strings.Repeat("12345", 10000) -+ r := reader(line + "\r\n") -+ s, err := r.ReadLine() -+ if err != nil { -+ t.Fatalf("Line 1: %v", err) -+ } -+ if s != line { -+ t.Fatalf("%v-byte line does not match expected %v-byte line", len(s), len(line)) -+ } -+} -+ - func TestReadContinuedLine(t *testing.T) { - r := reader("line1\nline\n 2\nline3\n") - s, err := r.ReadContinuedLine() --- -2.33.0 - diff --git a/backport-0004-release-branch.go1.21-net-http-net-http-cookiejar-av.patch b/backport-0004-release-branch.go1.21-net-http-net-http-cookiejar-av.patch deleted file mode 100644 index db25f1e17f2c3a6a2eb7dd1ff3330add6693d8a7..0000000000000000000000000000000000000000 --- a/backport-0004-release-branch.go1.21-net-http-net-http-cookiejar-av.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 6021dca711926c32959c2dc4c2a68c9494e9a4fc Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Thu, 11 Jan 2024 11:31:57 -0800 -Subject: [PATCH 4/4] [release-branch.go1.21] net/http, net/http/cookiejar: - avoid subdomain matches on IPv6 zones - -When deciding whether to forward cookies or sensitive headers -across a redirect, do not attempt to interpret an IPv6 address -as a domain name. - -Avoids a case where a maliciously-crafted redirect to an -IPv6 address with a scoped addressing zone could be -misinterpreted as a within-domain redirect. For example, -we could interpret "::1%.www.example.com" as a subdomain -of "www.example.com". - -Thanks to Juho Nurminen of Mattermost for reporting this issue. - -Fixes CVE-2023-45289 -Fixes #65385 -For #65065 - -Change-Id: I8f463f59f0e700c8a18733d2b264a8bcb3a19599 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2131938 -Reviewed-by: Tatiana Bradley -Reviewed-by: Roland Shoemaker -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173775 -Reviewed-by: Carlos Amedee -Reviewed-on: https://go-review.googlesource.com/c/go/+/569239 -Reviewed-by: Carlos Amedee -Auto-Submit: Michael Knyszek -TryBot-Bypass: Michael Knyszek ---- - src/net/http/client.go | 6 ++++++ - src/net/http/client_test.go | 1 + - src/net/http/cookiejar/jar.go | 7 +++++++ - src/net/http/cookiejar/jar_test.go | 10 ++++++++++ - 4 files changed, 24 insertions(+) - -diff --git a/src/net/http/client.go b/src/net/http/client.go -index 2cab53a585a..77a701b8061 100644 ---- a/src/net/http/client.go -+++ b/src/net/http/client.go -@@ -1014,6 +1014,12 @@ func isDomainOrSubdomain(sub, parent string) bool { - if sub == parent { - return true - } -+ // If sub contains a :, it's probably an IPv6 address (and is definitely not a hostname). -+ // Don't check the suffix in this case, to avoid matching the contents of a IPv6 zone. -+ // For example, "::1%.www.example.com" is not a subdomain of "www.example.com". -+ if strings.ContainsAny(sub, ":%") { -+ return false -+ } - // If sub is "foo.example.com" and parent is "example.com", - // that means sub must end in "."+parent. - // Do it without allocating. -diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go -index 0fe555af38f..fc1d7916124 100644 ---- a/src/net/http/client_test.go -+++ b/src/net/http/client_test.go -@@ -1725,6 +1725,7 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) { - {"authorization", "http://foo.com/", "https://foo.com/", true}, - {"authorization", "http://foo.com:1234/", "http://foo.com:4321/", true}, - {"www-authenticate", "http://foo.com/", "http://bar.com/", false}, -+ {"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false}, - - // But subdomains should work: - {"www-authenticate", "http://foo.com/", "http://foo.com/", true}, -diff --git a/src/net/http/cookiejar/jar.go b/src/net/http/cookiejar/jar.go -index 273b54c84c7..4b16266057b 100644 ---- a/src/net/http/cookiejar/jar.go -+++ b/src/net/http/cookiejar/jar.go -@@ -362,6 +362,13 @@ func jarKey(host string, psl PublicSuffixList) string { - - // isIP reports whether host is an IP address. - func isIP(host string) bool { -+ if strings.ContainsAny(host, ":%") { -+ // Probable IPv6 address. -+ // Hostnames can't contain : or %, so this is definitely not a valid host. -+ // Treating it as an IP is the more conservative option, and avoids the risk -+ // of interpeting ::1%.www.example.com as a subtomain of www.example.com. -+ return true -+ } - return net.ParseIP(host) != nil - } - -diff --git a/src/net/http/cookiejar/jar_test.go b/src/net/http/cookiejar/jar_test.go -index 56d0695a660..251f7c16171 100644 ---- a/src/net/http/cookiejar/jar_test.go -+++ b/src/net/http/cookiejar/jar_test.go -@@ -252,6 +252,7 @@ var isIPTests = map[string]bool{ - "127.0.0.1": true, - "1.2.3.4": true, - "2001:4860:0:2001::68": true, -+ "::1%zone": true, - "example.com": false, - "1.1.1.300": false, - "www.foo.bar.net": false, -@@ -629,6 +630,15 @@ var basicsTests = [...]jarTest{ - {"http://www.host.test:1234/", "a=1"}, - }, - }, -+ { -+ "IPv6 zone is not treated as a host.", -+ "https://example.com/", -+ []string{"a=1"}, -+ "a=1", -+ []query{ -+ {"https://[::1%25.example.com]:80/", ""}, -+ }, -+ }, - } - - func TestBasics(t *testing.T) { --- -2.33.0 - diff --git a/backport-0005-release-branch.go1.21-net-mail-properly-handle-speci.patch b/backport-0005-release-branch.go1.21-net-mail-properly-handle-speci.patch deleted file mode 100644 index fc7b26cbdba9a208f3b2b0e0ff1b998e2105de43..0000000000000000000000000000000000000000 --- a/backport-0005-release-branch.go1.21-net-mail-properly-handle-speci.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 11c0f19796e30484848a6c9c469364c0841c17ef Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Wed, 10 Jan 2024 11:02:14 -0800 -Subject: [PATCH] [release-branch.go1.21] net/mail: properly handle special - characters in phrase and obs-phrase - -Fixes a couple of misalignments with RFC 5322 which introduce -significant diffs between (mostly) conformant parsers. - -This change reverts the changes made in CL50911, which allowed certain -special RFC 5322 characters to appear unquoted in the "phrase" syntax. -It is unclear why this change was made in the first place, and created -a divergence from comformant parsers. In particular this resulted in -treating comments in display names incorrectly. - -Additionally properly handle trailing malformed comments in the group -syntax. - -For #65083 -Fixes #65848 - -Change-Id: I00dddc044c6ae3381154e43236632604c390f672 -Reviewed-on: https://go-review.googlesource.com/c/go/+/555596 -Reviewed-by: Damien Neil -LUCI-TryBot-Result: Go LUCI -Reviewed-on: https://go-review.googlesource.com/c/go/+/566195 -Reviewed-by: Carlos Amedee ---- - src/net/mail/message.go | 30 +++++++++++++++------------ - src/net/mail/message_test.go | 40 ++++++++++++++++++++++++++---------- - 2 files changed, 46 insertions(+), 24 deletions(-) - -diff --git a/src/net/mail/message.go b/src/net/mail/message.go -index af516fc30f..fc2a9e46f8 100644 ---- a/src/net/mail/message.go -+++ b/src/net/mail/message.go -@@ -280,7 +280,7 @@ func (a *Address) String() string { - // Add quotes if needed - quoteLocal := false - for i, r := range local { -- if isAtext(r, false, false) { -+ if isAtext(r, false) { - continue - } - if r == '.' { -@@ -444,7 +444,7 @@ func (p *addrParser) parseAddress(handleGroup bool) ([]*Address, error) { - if !p.consume('<') { - atext := true - for _, r := range displayName { -- if !isAtext(r, true, false) { -+ if !isAtext(r, true) { - atext = false - break - } -@@ -479,7 +479,9 @@ func (p *addrParser) consumeGroupList() ([]*Address, error) { - // handle empty group. - p.skipSpace() - if p.consume(';') { -- p.skipCFWS() -+ if !p.skipCFWS() { -+ return nil, errors.New("mail: misformatted parenthetical comment") -+ } - return group, nil - } - -@@ -496,7 +498,9 @@ func (p *addrParser) consumeGroupList() ([]*Address, error) { - return nil, errors.New("mail: misformatted parenthetical comment") - } - if p.consume(';') { -- p.skipCFWS() -+ if !p.skipCFWS() { -+ return nil, errors.New("mail: misformatted parenthetical comment") -+ } - break - } - if !p.consume(',') { -@@ -566,6 +570,12 @@ func (p *addrParser) consumePhrase() (phrase string, err error) { - var words []string - var isPrevEncoded bool - for { -+ // obs-phrase allows CFWS after one word -+ if len(words) > 0 { -+ if !p.skipCFWS() { -+ return "", errors.New("mail: misformatted parenthetical comment") -+ } -+ } - // word = atom / quoted-string - var word string - p.skipSpace() -@@ -661,7 +671,6 @@ Loop: - // If dot is true, consumeAtom parses an RFC 5322 dot-atom instead. - // If permissive is true, consumeAtom will not fail on: - // - leading/trailing/double dots in the atom (see golang.org/issue/4938) --// - special characters (RFC 5322 3.2.3) except '<', '>', ':' and '"' (see golang.org/issue/21018) - func (p *addrParser) consumeAtom(dot bool, permissive bool) (atom string, err error) { - i := 0 - -@@ -672,7 +681,7 @@ Loop: - case size == 1 && r == utf8.RuneError: - return "", fmt.Errorf("mail: invalid utf-8 in address: %q", p.s) - -- case size == 0 || !isAtext(r, dot, permissive): -+ case size == 0 || !isAtext(r, dot): - break Loop - - default: -@@ -850,18 +859,13 @@ func (e charsetError) Error() string { - - // isAtext reports whether r is an RFC 5322 atext character. - // If dot is true, period is included. --// If permissive is true, RFC 5322 3.2.3 specials is included, --// except '<', '>', ':' and '"'. --func isAtext(r rune, dot, permissive bool) bool { -+func isAtext(r rune, dot bool) bool { - switch r { - case '.': - return dot - - // RFC 5322 3.2.3. specials -- case '(', ')', '[', ']', ';', '@', '\\', ',': -- return permissive -- -- case '<', '>', '"', ':': -+ case '(', ')', '<', '>', '[', ']', ':', ';', '@', '\\', ',', '"': // RFC 5322 3.2.3. specials - return false - } - return isVchar(r) -diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go -index 1e1bb4092f..1f2f62afbf 100644 ---- a/src/net/mail/message_test.go -+++ b/src/net/mail/message_test.go -@@ -385,8 +385,11 @@ func TestAddressParsingError(t *testing.T) { - 13: {"group not closed: null@example.com", "expected comma"}, - 14: {"group: first@example.com, second@example.com;", "group with multiple addresses"}, - 15: {"john.doe", "missing '@' or angle-addr"}, -- 16: {"john.doe@", "no angle-addr"}, -+ 16: {"john.doe@", "missing '@' or angle-addr"}, - 17: {"John Doe@foo.bar", "no angle-addr"}, -+ 18: {" group: null@example.com; (asd", "misformatted parenthetical comment"}, -+ 19: {" group: ; (asd", "misformatted parenthetical comment"}, -+ 20: {`(John) Doe `, "missing word in phrase:"}, - } - - for i, tc := range mustErrTestCases { -@@ -436,24 +439,19 @@ func TestAddressParsing(t *testing.T) { - Address: "john.q.public@example.com", - }}, - }, -- { -- `"John (middle) Doe" `, -- []*Address{{ -- Name: "John (middle) Doe", -- Address: "jdoe@machine.example", -- }}, -- }, -+ // Comment in display name - { - `John (middle) Doe `, - []*Address{{ -- Name: "John (middle) Doe", -+ Name: "John Doe", - Address: "jdoe@machine.example", - }}, - }, -+ // Display name is quoted string, so comment is not a comment - { -- `John !@M@! Doe `, -+ `"John (middle) Doe" `, - []*Address{{ -- Name: "John !@M@! Doe", -+ Name: "John (middle) Doe", - Address: "jdoe@machine.example", - }}, - }, -@@ -788,6 +786,26 @@ func TestAddressParsing(t *testing.T) { - }, - }, - }, -+ // Comment in group display name -+ { -+ `group (comment:): a@example.com, b@example.com;`, -+ []*Address{ -+ { -+ Address: "a@example.com", -+ }, -+ { -+ Address: "b@example.com", -+ }, -+ }, -+ }, -+ { -+ `x(:"):"@a.example;("@b.example;`, -+ []*Address{ -+ { -+ Address: `@a.example;(@b.example`, -+ }, -+ }, -+ }, - } - for _, test := range tests { - if len(test.exp) == 1 { --- -2.33.0 - diff --git a/backport-0006-Backport-net-http-update-bundled-golang.org-x-net-ht.patch b/backport-0006-Backport-net-http-update-bundled-golang.org-x-net-ht.patch deleted file mode 100644 index ab4dfb26ee02452ab3fdfcf7861b42cc2f3818d9..0000000000000000000000000000000000000000 --- a/backport-0006-Backport-net-http-update-bundled-golang.org-x-net-ht.patch +++ /dev/null @@ -1,82 +0,0 @@ -From a65a2b54e18a7e269bff32526b4180ece22e9aa6 Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Thu, 28 Mar 2024 16:57:51 -0700 -Subject: [PATCH] [Backport] net/http: update bundled golang.org/x/net/http2 - -Offering: Cloud Core Network -CVE: CVE-2023-45288 -Reference: https://go-review.googlesource.com/c/go/+/576076 - -Disable cmd/internal/moddeps test, since this update includes PRIVATE -track fixes. - -Fixes CVE-2023-45288 -For #65051 -Fixes #66298 - -Change-Id: I5bbf774ebe7651e4bb7e55139d3794bd2b8e8fa8 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2197227 -Reviewed-by: Tatiana Bradley -Run-TryBot: Damien Neil -Reviewed-by: Dmitri Shuralyov -Reviewed-on: https://go-review.googlesource.com/c/go/+/576076 -Auto-Submit: Dmitri Shuralyov -TryBot-Bypass: Dmitri Shuralyov -Reviewed-by: Than McIntosh -Signed-off-by: Ma Chang Wang machangwang@huawei.com ---- - src/net/http/h2_bundle.go | 31 +++++++++++++++++++++++++++++++ - 1 file changed, 31 insertions(+) - -diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go -index dd59e1f4f2..cd95f84269 100644 ---- a/src/net/http/h2_bundle.go -+++ b/src/net/http/h2_bundle.go -@@ -2966,6 +2966,7 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - if size > remainSize { - hdec.SetEmitEnabled(false) - mh.Truncated = true -+ remainSize = 0 - return - } - remainSize -= size -@@ -2978,6 +2979,36 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - var hc http2headersOrContinuation = hf - for { - frag := hc.HeaderBlockFragment() -+ -+ // Avoid parsing large amounts of headers that we will then discard. -+ // If the sender exceeds the max header list size by too much, -+ // skip parsing the fragment and close the connection. -+ // -+ // "Too much" is either any CONTINUATION frame after we've already -+ // exceeded the max header list size (in which case remainSize is 0), -+ // or a frame whose encoded size is more than twice the remaining -+ // header list bytes we're willing to accept. -+ if int64(len(frag)) > int64(2*remainSize) { -+ if http2VerboseLogs { -+ log.Printf("http2: header list too large") -+ } -+ // It would be nice to send a RST_STREAM before sending the GOAWAY, -+ // but the struture of the server's frame writer makes this difficult. -+ return nil, http2ConnectionError(http2ErrCodeProtocol) -+ } -+ -+ // Also close the connection after any CONTINUATION frame following an -+ // invalid header, since we stop tracking the size of the headers after -+ // an invalid one. -+ if invalid != nil { -+ if http2VerboseLogs { -+ log.Printf("http2: invalid header: %v", invalid) -+ } -+ // It would be nice to send a RST_STREAM before sending the GOAWAY, -+ // but the struture of the server's frame writer makes this difficult. -+ return nil, http2ConnectionError(http2ErrCodeProtocol) -+ } -+ - if _, err := hdec.Write(frag); err != nil { - return nil, http2ConnectionError(http2ErrCodeCompression) - } --- -2.33.0 - diff --git a/backport-0007-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch b/backport-0007-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch deleted file mode 100644 index b1c16a57272a2bf324a3b7f41903651bea8b75bb..0000000000000000000000000000000000000000 --- a/backport-0007-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 7edadbad6c5ba7db3c4ab6925369096dedcf8e0b Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Thu, 25 Apr 2024 13:09:54 -0700 -Subject: [PATCH] [Backport] cmd/go: disallow -lto_library in LDFLAGS -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Offering: Cloud Core Network -CVE: CVE-2024-24787 -Reference: https://go-review.googlesource.com/c/go/+/583796 - -The darwin linker allows setting the LTO library with the -lto_library -flag. This wasn't caught by our "safe linker flags" check because it -was covered by the -lx flag used for linking libraries. This change -adds a specific check for excluded flags which otherwise satisfy our -existing checks. - -Loading a mallicious LTO library would allow an attacker to cause the -linker to execute abritrary code when "go build" was called. - -Thanks to Juho Forsén of Mattermost for reporting this issue. - -Fixes #67119 -Fixes #67122 -Fixes CVE-2024-24787 - -Change-Id: I77ac8585efbdbdfd5f39c39ed623b9408a0f9eaf -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1380 -Reviewed-by: Russ Cox -Reviewed-by: Damien Neil -(cherry picked from commit 9a79141fbbca1105e5c786f15e38741ca7843290) -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1420 -Reviewed-by: Tatiana Bradley -Reviewed-on: https://go-review.googlesource.com/c/go/+/583796 -Reviewed-by: David Chase -LUCI-TryBot-Result: Go LUCI -Signed-off-by: Ma Chang Wang machangwang@huawei.com ---- - src/cmd/go/internal/work/security.go | 19 +++++++++++++++---- - .../script/darwin_lto_library_ldflag.txt | 17 +++++++++++++++++ - 2 files changed, 32 insertions(+), 4 deletions(-) - create mode 100644 src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt - -diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go -index 270a34e9c7..db49eb6488 100644 ---- a/src/cmd/go/internal/work/security.go -+++ b/src/cmd/go/internal/work/security.go -@@ -141,6 +141,12 @@ var validCompilerFlagsWithNextArg = []string{ - "-x", - } - -+var invalidLinkerFlags = []*lazyregexp.Regexp{ -+ // On macOS this means the linker loads and executes the next argument. -+ // Have to exclude separately because -lfoo is allowed in general. -+ re(`-lto_library`), -+} -+ - var validLinkerFlags = []*lazyregexp.Regexp{ - re(`-F([^@\-].*)`), - re(`-l([^@\-].*)`), -@@ -231,12 +237,12 @@ var validLinkerFlagsWithNextArg = []string{ - - func checkCompilerFlags(name, source string, list []string) error { - checkOverrides := true -- return checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides) -+ return checkFlags(name, source, list, nil, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides) - } - - func checkLinkerFlags(name, source string, list []string) error { - checkOverrides := true -- return checkFlags(name, source, list, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides) -+ return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides) - } - - // checkCompilerFlagsForInternalLink returns an error if 'list' -@@ -245,7 +251,7 @@ func checkLinkerFlags(name, source string, list []string) error { - // external linker). - func checkCompilerFlagsForInternalLink(name, source string, list []string) error { - checkOverrides := false -- if err := checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides); err != nil { -+ if err := checkFlags(name, source, list, nil, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides); err != nil { - return err - } - // Currently the only flag on the allow list that causes problems -@@ -258,7 +264,7 @@ func checkCompilerFlagsForInternalLink(name, source string, list []string) error - return nil - } - --func checkFlags(name, source string, list []string, valid []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error { -+func checkFlags(name, source string, list []string, invalid, valid []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error { - // Let users override rules with $CGO_CFLAGS_ALLOW, $CGO_CFLAGS_DISALLOW, etc. - var ( - allow *regexp.Regexp -@@ -290,6 +296,11 @@ Args: - if allow != nil && allow.FindString(arg) == arg { - continue Args - } -+ for _, re := range invalid { -+ if re.FindString(arg) == arg { // must be complete match -+ goto Bad -+ } -+ } - for _, re := range valid { - if re.FindString(arg) == arg { // must be complete match - continue Args -diff --git a/src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt b/src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt -new file mode 100644 -index 0000000000..d7acefdbad ---- /dev/null -+++ b/src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt -@@ -0,0 +1,17 @@ -+[!GOOS:darwin] skip -+[!cgo] skip -+ -+! go build -+stderr 'invalid flag in #cgo LDFLAGS: -lto_library' -+ -+-- go.mod -- -+module ldflag -+ -+-- main.go -- -+package main -+ -+// #cgo CFLAGS: -flto -+// #cgo LDFLAGS: -lto_library bad.dylib -+import "C" -+ -+func main() {} -\ No newline at end of file --- -2.33.0 - diff --git a/backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch b/backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch deleted file mode 100644 index 261dbe02f2559fd4471dcbd66b6145aac482d504..0000000000000000000000000000000000000000 --- a/backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 051bdf3fd12a40307606ff9381138039c5f452f0 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Tue, 28 May 2024 13:26:31 -0700 -Subject: [PATCH] [release-branch.go1.21] net/netip: check if address is v6 - mapped in Is methods - -In all of the Is* methods, check if the address is a v6 mapped v4 -address, and unmap it if so. - -Thanks to Enze Wang of Alioth (@zer0yu) and Jianjun Chen of Zhongguancun -Lab (@chenjj) for reporting this issue. - -Fixes #67680 -Fixes #67681 -Fixes CVE-2024-24790 - -Change-Id: I6bd03ca1a5d93a0b59027d861c84060967b265b0 -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1460 -Reviewed-by: Russ Cox -Reviewed-by: Damien Neil -(cherry picked from commit f7f270c1621fdc7ee48e0487b2fac0356947d19b) -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1500 -Reviewed-by: Tatiana Bradley -Reviewed-on: https://go-review.googlesource.com/c/go/+/590315 -Auto-Submit: Michael Knyszek -LUCI-TryBot-Result: Go LUCI -Reviewed-by: David Chase ---- - src/net/netip/inlining_test.go | 2 -- - src/net/netip/netip.go | 26 +++++++++++++++++- - src/net/netip/netip_test.go | 50 +++++++++++++++++++++++++++++++--- - 3 files changed, 71 insertions(+), 7 deletions(-) - -diff --git a/src/net/netip/inlining_test.go b/src/net/netip/inlining_test.go -index b521eeebfd8f3..98584b098df1b 100644 ---- a/src/net/netip/inlining_test.go -+++ b/src/net/netip/inlining_test.go -@@ -36,8 +36,6 @@ func TestInlining(t *testing.T) { - "Addr.Is4", - "Addr.Is4In6", - "Addr.Is6", -- "Addr.IsLoopback", -- "Addr.IsMulticast", - "Addr.IsInterfaceLocalMulticast", - "Addr.IsValid", - "Addr.IsUnspecified", -diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go -index a44b09495549d..9e4d41f8fb7b9 100644 ---- a/src/net/netip/netip.go -+++ b/src/net/netip/netip.go -@@ -507,6 +507,10 @@ func (ip Addr) hasZone() bool { - - // IsLinkLocalUnicast reports whether ip is a link-local unicast address. - func (ip Addr) IsLinkLocalUnicast() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Dynamic Configuration of IPv4 Link-Local Addresses - // https://datatracker.ietf.org/doc/html/rfc3927#section-2.1 - if ip.Is4() { -@@ -522,6 +526,10 @@ func (ip Addr) IsLinkLocalUnicast() bool { - - // IsLoopback reports whether ip is a loopback address. - func (ip Addr) IsLoopback() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing) - // https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3 - if ip.Is4() { -@@ -537,6 +545,10 @@ func (ip Addr) IsLoopback() bool { - - // IsMulticast reports whether ip is a multicast address. - func (ip Addr) IsMulticast() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES) - // https://datatracker.ietf.org/doc/html/rfc1112#section-4 - if ip.Is4() { -@@ -555,7 +567,7 @@ func (ip Addr) IsMulticast() bool { - func (ip Addr) IsInterfaceLocalMulticast() bool { - // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses) - // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1 -- if ip.Is6() { -+ if ip.Is6() && !ip.Is4In6() { - return ip.v6u16(0)&0xff0f == 0xff01 - } - return false // zero value -@@ -563,6 +575,10 @@ func (ip Addr) IsInterfaceLocalMulticast() bool { - - // IsLinkLocalMulticast reports whether ip is a link-local multicast address. - func (ip Addr) IsLinkLocalMulticast() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24)) - // https://datatracker.ietf.org/doc/html/rfc5771#section-4 - if ip.Is4() { -@@ -591,6 +607,10 @@ func (ip Addr) IsGlobalUnicast() bool { - return false - } - -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses - // and ULA IPv6 addresses are still considered "global unicast". - if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) { -@@ -608,6 +628,10 @@ func (ip Addr) IsGlobalUnicast() bool { - // ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the - // same as net.IP.IsPrivate. - func (ip Addr) IsPrivate() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Match the stdlib's IsPrivate logic. - if ip.Is4() { - // RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as -diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go -index 0f80bb0ab0e56..5c7ad14c5c702 100644 ---- a/src/net/netip/netip_test.go -+++ b/src/net/netip/netip_test.go -@@ -589,10 +589,13 @@ func TestIPProperties(t *testing.T) { - ilm6 = mustIP("ff01::1") - ilmZone6 = mustIP("ff01::1%eth0") - -- private4a = mustIP("10.0.0.1") -- private4b = mustIP("172.16.0.1") -- private4c = mustIP("192.168.1.1") -- private6 = mustIP("fd00::1") -+ private4a = mustIP("10.0.0.1") -+ private4b = mustIP("172.16.0.1") -+ private4c = mustIP("192.168.1.1") -+ private6 = mustIP("fd00::1") -+ private6mapped4a = mustIP("::ffff:10.0.0.1") -+ private6mapped4b = mustIP("::ffff:172.16.0.1") -+ private6mapped4c = mustIP("::ffff:192.168.1.1") - ) - - tests := []struct { -@@ -616,6 +619,11 @@ func TestIPProperties(t *testing.T) { - ip: unicast4, - globalUnicast: true, - }, -+ { -+ name: "unicast v6 mapped v4Addr", -+ ip: AddrFrom16(unicast4.As16()), -+ globalUnicast: true, -+ }, - { - name: "unicast v6Addr", - ip: unicast6, -@@ -637,6 +645,12 @@ func TestIPProperties(t *testing.T) { - linkLocalMulticast: true, - multicast: true, - }, -+ { -+ name: "multicast v6 mapped v4Addr", -+ ip: AddrFrom16(multicast4.As16()), -+ linkLocalMulticast: true, -+ multicast: true, -+ }, - { - name: "multicast v6Addr", - ip: multicast6, -@@ -654,6 +668,11 @@ func TestIPProperties(t *testing.T) { - ip: llu4, - linkLocalUnicast: true, - }, -+ { -+ name: "link-local unicast v6 mapped v4Addr", -+ ip: AddrFrom16(llu4.As16()), -+ linkLocalUnicast: true, -+ }, - { - name: "link-local unicast v6Addr", - ip: llu6, -@@ -679,6 +698,11 @@ func TestIPProperties(t *testing.T) { - ip: IPv6Loopback(), - loopback: true, - }, -+ { -+ name: "loopback v6 mapped v4Addr", -+ ip: AddrFrom16(IPv6Loopback().As16()), -+ loopback: true, -+ }, - { - name: "interface-local multicast v6Addr", - ip: ilm6, -@@ -715,6 +739,24 @@ func TestIPProperties(t *testing.T) { - globalUnicast: true, - private: true, - }, -+ { -+ name: "private v6 mapped v4Addr 10/8", -+ ip: private6mapped4a, -+ globalUnicast: true, -+ private: true, -+ }, -+ { -+ name: "private v6 mapped v4Addr 172.16/12", -+ ip: private6mapped4b, -+ globalUnicast: true, -+ private: true, -+ }, -+ { -+ name: "private v6 mapped v4Addr 192.168/16", -+ ip: private6mapped4c, -+ globalUnicast: true, -+ private: true, -+ }, - { - name: "unspecified v4Addr", - ip: IPv4Unspecified(), diff --git a/backport-0009-Backport-cmd-go-internal-vcs-error-out-if-the-reques.patch b/backport-0009-Backport-cmd-go-internal-vcs-error-out-if-the-reques.patch deleted file mode 100644 index fb5d4bba65e97453590ced9ae1b4d0fa90afa1b1..0000000000000000000000000000000000000000 --- a/backport-0009-Backport-cmd-go-internal-vcs-error-out-if-the-reques.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 558cbc498c70278bea8297272f2d4fc50d67893b Mon Sep 17 00:00:00 2001 -From: "Bryan C. Mills" -Date: Thu, 2 Nov 2023 15:06:35 -0400 -Subject: [PATCH] [Backport] cmd/go/internal/vcs: error out if the requested - repo does not support a secure protocol - -CVE: CVE-2023-45285 -Reference: https://go-review.googlesource.com/c/go/+/540335 - -Updates #63845. -Fixes #63972. - -Change-Id: If86d6b13d3b55877b35c087112bd76388c9404b8 -Reviewed-on: https://go-review.googlesource.com/c/go/+/539321 -Reviewed-by: Michael Matloob -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Roland Shoemaker -Auto-Submit: Bryan Mills -(cherry picked from commit be26ae18caf7ddffca4073333f80d0d9e76483c3) -Reviewed-on: https://go-review.googlesource.com/c/go/+/540335 -Auto-Submit: Dmitri Shuralyov -Reviewed-by: Dmitri Shuralyov -Signed-off-by: wangbingyao 00557526 ---- - src/cmd/go/internal/vcs/vcs.go | 25 +++++++++++++---- - .../script/mod_insecure_issue63845.txt | 28 +++++++++++++++++++ - 2 files changed, 47 insertions(+), 6 deletions(-) - create mode 100644 src/cmd/go/testdata/script/mod_insecure_issue63845.txt - -diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go -index c65dd0f624..dbf16d1de7 100644 ---- a/src/cmd/go/internal/vcs/vcs.go -+++ b/src/cmd/go/internal/vcs/vcs.go -@@ -1204,18 +1204,31 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths - var ok bool - repoURL, ok = interceptVCSTest(repo, vcs, security) - if !ok { -- scheme := vcs.Scheme[0] // default to first scheme -- if vcs.PingCmd != "" { -- // If we know how to test schemes, scan to find one. -+ scheme, err := func() (string, error) { - for _, s := range vcs.Scheme { - if security == web.SecureOnly && !vcs.isSecureScheme(s) { - continue - } -- if vcs.Ping(s, repo) == nil { -- scheme = s -- break -+ -+ // If we know how to ping URL schemes for this VCS, -+ // check that this repo works. -+ // Otherwise, default to the first scheme -+ // that meets the requested security level. -+ if vcs.PingCmd == "" { -+ return s, nil -+ } -+ if err := vcs.Ping(s, repo); err == nil { -+ return s, nil - } - } -+ securityFrag := "" -+ if security == web.SecureOnly { -+ securityFrag = "secure " -+ } -+ return "", fmt.Errorf("no %sprotocol found for repository", securityFrag) -+ }() -+ if err != nil { -+ return nil, err - } - repoURL = scheme + "://" + repo - } -diff --git a/src/cmd/go/testdata/script/mod_insecure_issue63845.txt b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt -new file mode 100644 -index 0000000000..5fa6a4f12b ---- /dev/null -+++ b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt -@@ -0,0 +1,28 @@ -+# Regression test for https://go.dev/issue/63845: -+# If 'git ls-remote' fails for all secure protocols, -+# we should fail instead of falling back to an arbitrary protocol. -+# -+# Note that this test does not use the local vcweb test server -+# (vcs-test.golang.org), because the hook for redirecting to that -+# server bypasses the "ping to determine protocol" logic -+# in cmd/go/internal/vcs. -+ -+[!net] skip -+[!git] skip -+[short] skip 'tries to access a nonexistent external Git repo' -+ -+env GOPRIVATE=golang.org -+env CURLOPT_TIMEOUT_MS=100 -+env GIT_SSH_COMMAND=false -+ -+! go get -x golang.org/nonexist.git@latest -+stderr '^git ls-remote https://golang.org/nonexist$' -+stderr '^git ls-remote git\+ssh://golang.org/nonexist' -+stderr '^git ls-remote ssh://golang.org/nonexist$' -+! stderr 'git://' -+stderr '^go: golang.org/nonexist.git@latest: no secure protocol found for repository$' -+ -+-- go.mod -- -+module example -+ -+go 1.19 --- -2.33.0 - diff --git a/backport-0010-release-branch.go1.21-net-http-limit-chunked-data-ov.patch b/backport-0010-release-branch.go1.21-net-http-limit-chunked-data-ov.patch deleted file mode 100644 index 67367a4942d08229540ec978cdc78945705ee85f..0000000000000000000000000000000000000000 --- a/backport-0010-release-branch.go1.21-net-http-limit-chunked-data-ov.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 43c0e9116f26416de7454855852eba9083d94d03 Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Tue, 7 Nov 2023 10:47:56 -0800 -Subject: [PATCH 1/2] [release-branch.go1.21] net/http: limit chunked data - overhead - -The chunked transfer encoding adds some overhead to -the content transferred. When writing one byte per -chunk, for example, there are five bytes of overhead -per byte of data transferred: "1\r\nX\r\n" to send "X". - -Chunks may include "chunk extensions", -which we skip over and do not use. -For example: "1;chunk extension here\r\nX\r\n". - -A malicious sender can use chunk extensions to add -about 4k of overhead per byte of data. -(The maximum chunk header line size we will accept.) - -Track the amount of overhead read in chunked data, -and produce an error if it seems excessive. - -Updates #64433 -Fixes #64435 -Fixes CVE-2023-39326 - -Change-Id: I40f8d70eb6f9575fb43f506eb19132ccedafcf39 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2076135 -Reviewed-by: Tatiana Bradley -Reviewed-by: Roland Shoemaker -(cherry picked from commit 3473ae72ee66c60744665a24b2fde143e8964d4f) -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2095408 -Run-TryBot: Roland Shoemaker -Reviewed-by: Damien Neil -Reviewed-on: https://go-review.googlesource.com/c/go/+/547356 -Reviewed-by: Dmitri Shuralyov -LUCI-TryBot-Result: Go LUCI ---- - src/net/http/internal/chunked.go | 34 ++++++++++++--- - src/net/http/internal/chunked_test.go | 59 +++++++++++++++++++++++++++ - 2 files changed, 87 insertions(+), 6 deletions(-) - -diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go -index 5a174415dc4..aad8e5aa09e 100644 ---- a/src/net/http/internal/chunked.go -+++ b/src/net/http/internal/chunked.go -@@ -39,7 +39,8 @@ type chunkedReader struct { - n uint64 // unread bytes in chunk - err error - buf [2]byte -- checkEnd bool // whether need to check for \r\n chunk footer -+ checkEnd bool // whether need to check for \r\n chunk footer -+ excess int64 // "excessive" chunk overhead, for malicious sender detection - } - - func (cr *chunkedReader) beginChunk() { -@@ -49,10 +50,36 @@ func (cr *chunkedReader) beginChunk() { - if cr.err != nil { - return - } -+ cr.excess += int64(len(line)) + 2 // header, plus \r\n after the chunk data -+ line = trimTrailingWhitespace(line) -+ line, cr.err = removeChunkExtension(line) -+ if cr.err != nil { -+ return -+ } - cr.n, cr.err = parseHexUint(line) - if cr.err != nil { - return - } -+ // A sender who sends one byte per chunk will send 5 bytes of overhead -+ // for every byte of data. ("1\r\nX\r\n" to send "X".) -+ // We want to allow this, since streaming a byte at a time can be legitimate. -+ // -+ // A sender can use chunk extensions to add arbitrary amounts of additional -+ // data per byte read. ("1;very long extension\r\nX\r\n" to send "X".) -+ // We don't want to disallow extensions (although we discard them), -+ // but we also don't want to allow a sender to reduce the signal/noise ratio -+ // arbitrarily. -+ // -+ // We track the amount of excess overhead read, -+ // and produce an error if it grows too large. -+ // -+ // Currently, we say that we're willing to accept 16 bytes of overhead per chunk, -+ // plus twice the amount of real data in the chunk. -+ cr.excess -= 16 + (2 * int64(cr.n)) -+ cr.excess = max(cr.excess, 0) -+ if cr.excess > 16*1024 { -+ cr.err = errors.New("chunked encoding contains too much non-data") -+ } - if cr.n == 0 { - cr.err = io.EOF - } -@@ -140,11 +167,6 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) { - if len(p) >= maxLineLength { - return nil, ErrLineTooLong - } -- p = trimTrailingWhitespace(p) -- p, err = removeChunkExtension(p) -- if err != nil { -- return nil, err -- } - return p, nil - } - -diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go -index 5e29a786dd6..b99090c1f8a 100644 ---- a/src/net/http/internal/chunked_test.go -+++ b/src/net/http/internal/chunked_test.go -@@ -239,3 +239,62 @@ func TestChunkEndReadError(t *testing.T) { - t.Errorf("expected %v, got %v", readErr, err) - } - } -+ -+func TestChunkReaderTooMuchOverhead(t *testing.T) { -+ // If the sender is sending 100x as many chunk header bytes as chunk data, -+ // we should reject the stream at some point. -+ chunk := []byte("1;") -+ for i := 0; i < 100; i++ { -+ chunk = append(chunk, 'a') // chunk extension -+ } -+ chunk = append(chunk, "\r\nX\r\n"...) -+ const bodylen = 1 << 20 -+ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) { -+ if i < bodylen { -+ return chunk, nil -+ } -+ return []byte("0\r\n"), nil -+ }}) -+ _, err := io.ReadAll(r) -+ if err == nil { -+ t.Fatalf("successfully read body with excessive overhead; want error") -+ } -+} -+ -+func TestChunkReaderByteAtATime(t *testing.T) { -+ // Sending one byte per chunk should not trip the excess-overhead detection. -+ const bodylen = 1 << 20 -+ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) { -+ if i < bodylen { -+ return []byte("1\r\nX\r\n"), nil -+ } -+ return []byte("0\r\n"), nil -+ }}) -+ got, err := io.ReadAll(r) -+ if err != nil { -+ t.Errorf("unexpected error: %v", err) -+ } -+ if len(got) != bodylen { -+ t.Errorf("read %v bytes, want %v", len(got), bodylen) -+ } -+} -+ -+type funcReader struct { -+ f func(iteration int) ([]byte, error) -+ i int -+ b []byte -+ err error -+} -+ -+func (r *funcReader) Read(p []byte) (n int, err error) { -+ if len(r.b) == 0 && r.err == nil { -+ r.b, r.err = r.f(r.i) -+ r.i++ -+ } -+ n = copy(p, r.b) -+ r.b = r.b[n:] -+ if len(r.b) > 0 { -+ return n, nil -+ } -+ return n, r.err -+} --- -2.33.0 - diff --git a/backport-0011-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch b/backport-0011-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch deleted file mode 100644 index 55beba5543b0f50020df5f9ac2e93e73f850b63b..0000000000000000000000000000000000000000 --- a/backport-0011-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c69c5c62775d84aa56a43bedaa4fcacbb73d403d Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Tue, 14 May 2024 14:39:10 -0700 -Subject: [PATCH] [Backport] archive/zip: treat truncated EOCDR comment as an - error - -CVE: CVE-2024-24789 -Reference: https://go-review.googlesource.com/c/go/+/588796 - -When scanning for an end of central directory record, -treat an EOCDR signature with a record containing a truncated -comment as an error. Previously, we would skip over the invalid -record and look for another one. Other implementations do not -do this (they either consider this a hard error, or just ignore -the truncated comment). This parser misalignment allowed -presenting entirely different archive contents to Go programs -and other zip decoders. - -For #66869 -Fixes #67554 -Fixes CVE-2024-24789 - -Change-Id: I94e5cb028534bb5704588b8af27f1e22ea49c7c6 -Reviewed-on: https://go-review.googlesource.com/c/go/+/585397 -Reviewed-by: Joseph Tsai -Reviewed-by: Dmitri Shuralyov -LUCI-TryBot-Result: Go LUCI -(cherry picked from commit 33d725e5758bf1fea62e6c77fc70b57a828a49f5) -Reviewed-on: https://go-review.googlesource.com/c/go/+/588796 -Reviewed-by: Matthew Dempsky -Signed-off-by: Ma Chang Wang machangwang@huawei.com ---- - src/archive/zip/reader.go | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go -index 1fde1decc4..20356bde0e 100644 ---- a/src/archive/zip/reader.go -+++ b/src/archive/zip/reader.go -@@ -699,9 +699,13 @@ func findSignatureInBlock(b []byte) int { - if b[i] == 'P' && b[i+1] == 'K' && b[i+2] == 0x05 && b[i+3] == 0x06 { - // n is length of comment - n := int(b[i+directoryEndLen-2]) | int(b[i+directoryEndLen-1])<<8 -- if n+directoryEndLen+i <= len(b) { -- return i -+ if n+directoryEndLen+i > len(b) { -+ // Truncated comment. -+ // Some parsers (such as Info-ZIP) ignore the truncated comment -+ // rather than treating it as a hard error. -+ return -1 - } -+ return i - } - } - return -1 --- -2.33.0 - diff --git a/backport-0012-net-http-send-body-or-close-connection-on-expect-100.patch b/backport-0012-net-http-send-body-or-close-connection-on-expect-100.patch deleted file mode 100644 index 30501ff1b2c80b5dec252f3f0fd8d2347f1f2647..0000000000000000000000000000000000000000 --- a/backport-0012-net-http-send-body-or-close-connection-on-expect-100.patch +++ /dev/null @@ -1,353 +0,0 @@ -From c9be6ae748b7679b644a38182d456cb5a6ac06ee Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Thu, 6 Jun 2024 12:50:46 -0700 -Subject: [PATCH] [release-branch.go1.21] net/http: send body or close - connection on expect-100-continue requests - -When sending a request with an "Expect: 100-continue" header, -we must send the request body before sending any further requests -on the connection. - -When receiving a non-1xx response to an "Expect: 100-continue" request, -send the request body if the connection isn't being closed after -processing the response. In other words, if either the request -or response contains a "Connection: close" header, then skip sending -the request body (because the connection will not be used for -further requests), but otherwise send it. - -Correct a comment on the server-side Expect: 100-continue handling -that implied sending the request body is optional. It isn't. - -For #67555 -Fixes #68199 - -Change-Id: Ia2f12091bee697771087f32ac347509ec5922d54 -Reviewed-on: https://go-review.googlesource.com/c/go/+/591255 -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Jonathan Amsterdam -(cherry picked from commit cf501e05e138e6911f759a5db786e90b295499b9) -Reviewed-on: https://go-review.googlesource.com/c/go/+/595096 -Reviewed-by: Joedian Reid -Reviewed-by: Dmitri Shuralyov ---- - src/net/http/server.go | 25 ++-- - src/net/http/transport.go | 34 ++++-- - src/net/http/transport_test.go | 202 ++++++++++++++++++++------------- - 3 files changed, 164 insertions(+), 97 deletions(-) - -diff --git a/src/net/http/server.go b/src/net/http/server.go -index 8f63a90299..111adb0ecd 100644 ---- a/src/net/http/server.go -+++ b/src/net/http/server.go -@@ -1352,16 +1352,21 @@ func (cw *chunkWriter) writeHeader(p []byte) { - - // If the client wanted a 100-continue but we never sent it to - // them (or, more strictly: we never finished reading their -- // request body), don't reuse this connection because it's now -- // in an unknown state: we might be sending this response at -- // the same time the client is now sending its request body -- // after a timeout. (Some HTTP clients send Expect: -- // 100-continue but knowing that some servers don't support -- // it, the clients set a timer and send the body later anyway) -- // If we haven't seen EOF, we can't skip over the unread body -- // because we don't know if the next bytes on the wire will be -- // the body-following-the-timer or the subsequent request. -- // See Issue 11549. -+ // request body), don't reuse this connection. -+ // -+ // This behavior was first added on the theory that we don't know -+ // if the next bytes on the wire are going to be the remainder of -+ // the request body or the subsequent request (see issue 11549), -+ // but that's not correct: If we keep using the connection, -+ // the client is required to send the request body whether we -+ // asked for it or not. -+ // -+ // We probably do want to skip reusing the connection in most cases, -+ // however. If the client is offering a large request body that we -+ // don't intend to use, then it's better to close the connection -+ // than to read the body. For now, assume that if we're sending -+ // headers, the handler is done reading the body and we should -+ // drop the connection if we haven't seen EOF. - if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF.Load() { - w.closeAfterReply = true - } -diff --git a/src/net/http/transport.go b/src/net/http/transport.go -index c07352b018..30bce98736 100644 ---- a/src/net/http/transport.go -+++ b/src/net/http/transport.go -@@ -2313,17 +2313,12 @@ func (pc *persistConn) readResponse(rc requestAndChan, trace *httptrace.ClientTr - return - } - resCode := resp.StatusCode -- if continueCh != nil { -- if resCode == 100 { -- if trace != nil && trace.Got100Continue != nil { -- trace.Got100Continue() -- } -- continueCh <- struct{}{} -- continueCh = nil -- } else if resCode >= 200 { -- close(continueCh) -- continueCh = nil -+ if continueCh != nil && resCode == StatusContinue { -+ if trace != nil && trace.Got100Continue != nil { -+ trace.Got100Continue() - } -+ continueCh <- struct{}{} -+ continueCh = nil - } - is1xx := 100 <= resCode && resCode <= 199 - // treat 101 as a terminal status, see issue 26161 -@@ -2346,6 +2341,25 @@ func (pc *persistConn) readResponse(rc requestAndChan, trace *httptrace.ClientTr - if resp.isProtocolSwitch() { - resp.Body = newReadWriteCloserBody(pc.br, pc.conn) - } -+ if continueCh != nil { -+ // We send an "Expect: 100-continue" header, but the server -+ // responded with a terminal status and no 100 Continue. -+ // -+ // If we're going to keep using the connection, we need to send the request body. -+ // Tell writeLoop to skip sending the body if we're going to close the connection, -+ // or to send it otherwise. -+ // -+ // The case where we receive a 101 Switching Protocols response is a bit -+ // ambiguous, since we don't know what protocol we're switching to. -+ // Conceivably, it's one that doesn't need us to send the body. -+ // Given that we'll send the body if ExpectContinueTimeout expires, -+ // be consistent and always send it if we aren't closing the connection. -+ if resp.Close || rc.req.Close { -+ close(continueCh) // don't send the body; the connection will close -+ } else { -+ continueCh <- struct{}{} // send the body -+ } -+ } - - resp.TLS = pc.tlsState - return -diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go -index 028fecc961..b8c930ab8f 100644 ---- a/src/net/http/transport_test.go -+++ b/src/net/http/transport_test.go -@@ -1135,94 +1135,142 @@ func testTransportGzip(t *testing.T, mode testMode) { - } - } - --// If a request has Expect:100-continue header, the request blocks sending body until the first response. --// Premature consumption of the request body should not be occurred. --func TestTransportExpect100Continue(t *testing.T) { -- run(t, testTransportExpect100Continue, []testMode{http1Mode}) -+// A transport100Continue test exercises Transport behaviors when sending a -+// request with an Expect: 100-continue header. -+type transport100ContinueTest struct { -+ t *testing.T -+ -+ reqdone chan struct{} -+ resp *Response -+ respErr error -+ -+ conn net.Conn -+ reader *bufio.Reader - } --func testTransportExpect100Continue(t *testing.T, mode testMode) { -- ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) { -- switch req.URL.Path { -- case "/100": -- // This endpoint implicitly responds 100 Continue and reads body. -- if _, err := io.Copy(io.Discard, req.Body); err != nil { -- t.Error("Failed to read Body", err) -- } -- rw.WriteHeader(StatusOK) -- case "/200": -- // Go 1.5 adds Connection: close header if the client expect -- // continue but not entire request body is consumed. -- rw.WriteHeader(StatusOK) -- case "/500": -- rw.WriteHeader(StatusInternalServerError) -- case "/keepalive": -- // This hijacked endpoint responds error without Connection:close. -- _, bufrw, err := rw.(Hijacker).Hijack() -- if err != nil { -- log.Fatal(err) -- } -- bufrw.WriteString("HTTP/1.1 500 Internal Server Error\r\n") -- bufrw.WriteString("Content-Length: 0\r\n\r\n") -- bufrw.Flush() -- case "/timeout": -- // This endpoint tries to read body without 100 (Continue) response. -- // After ExpectContinueTimeout, the reading will be started. -- conn, bufrw, err := rw.(Hijacker).Hijack() -- if err != nil { -- log.Fatal(err) -- } -- if _, err := io.CopyN(io.Discard, bufrw, req.ContentLength); err != nil { -- t.Error("Failed to read Body", err) -- } -- bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n") -- bufrw.Flush() -- conn.Close() -- } - -- })).ts -+const transport100ContinueTestBody = "request body" - -- tests := []struct { -- path string -- body []byte -- sent int -- status int -- }{ -- {path: "/100", body: []byte("hello"), sent: 5, status: 200}, // Got 100 followed by 200, entire body is sent. -- {path: "/200", body: []byte("hello"), sent: 0, status: 200}, // Got 200 without 100. body isn't sent. -- {path: "/500", body: []byte("hello"), sent: 0, status: 500}, // Got 500 without 100. body isn't sent. -- {path: "/keepalive", body: []byte("hello"), sent: 0, status: 500}, // Although without Connection:close, body isn't sent. -- {path: "/timeout", body: []byte("hello"), sent: 5, status: 200}, // Timeout exceeded and entire body is sent. -+// newTransport100ContinueTest creates a Transport and sends an Expect: 100-continue -+// request on it. -+func newTransport100ContinueTest(t *testing.T, timeout time.Duration) *transport100ContinueTest { -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ test := &transport100ContinueTest{ -+ t: t, -+ reqdone: make(chan struct{}), - } - -- c := ts.Client() -- for i, v := range tests { -- tr := &Transport{ -- ExpectContinueTimeout: 2 * time.Second, -- } -- defer tr.CloseIdleConnections() -- c.Transport = tr -- body := bytes.NewReader(v.body) -- req, err := NewRequest("PUT", ts.URL+v.path, body) -- if err != nil { -- t.Fatal(err) -- } -+ tr := &Transport{ -+ ExpectContinueTimeout: timeout, -+ } -+ go func() { -+ defer close(test.reqdone) -+ body := strings.NewReader(transport100ContinueTestBody) -+ req, _ := NewRequest("PUT", "http://"+ln.Addr().String(), body) - req.Header.Set("Expect", "100-continue") -- req.ContentLength = int64(len(v.body)) -+ req.ContentLength = int64(len(transport100ContinueTestBody)) -+ test.resp, test.respErr = tr.RoundTrip(req) -+ test.resp.Body.Close() -+ }() - -- resp, err := c.Do(req) -- if err != nil { -- t.Fatal(err) -+ c, err := ln.Accept() -+ if err != nil { -+ t.Fatalf("Accept: %v", err) -+ } -+ t.Cleanup(func() { -+ c.Close() -+ }) -+ br := bufio.NewReader(c) -+ _, err = ReadRequest(br) -+ if err != nil { -+ t.Fatalf("ReadRequest: %v", err) -+ } -+ test.conn = c -+ test.reader = br -+ t.Cleanup(func() { -+ <-test.reqdone -+ tr.CloseIdleConnections() -+ got, _ := io.ReadAll(test.reader) -+ if len(got) > 0 { -+ t.Fatalf("Transport sent unexpected bytes: %q", got) - } -- resp.Body.Close() -+ }) - -- sent := len(v.body) - body.Len() -- if v.status != resp.StatusCode { -- t.Errorf("test %d: status code should be %d but got %d. (%s)", i, v.status, resp.StatusCode, v.path) -- } -- if v.sent != sent { -- t.Errorf("test %d: sent body should be %d but sent %d. (%s)", i, v.sent, sent, v.path) -+ return test -+} -+ -+// respond sends response lines from the server to the transport. -+func (test *transport100ContinueTest) respond(lines ...string) { -+ for _, line := range lines { -+ if _, err := test.conn.Write([]byte(line + "\r\n")); err != nil { -+ test.t.Fatalf("Write: %v", err) - } - } -+ if _, err := test.conn.Write([]byte("\r\n")); err != nil { -+ test.t.Fatalf("Write: %v", err) -+ } -+} -+ -+// wantBodySent ensures the transport has sent the request body to the server. -+func (test *transport100ContinueTest) wantBodySent() { -+ got, err := io.ReadAll(io.LimitReader(test.reader, int64(len(transport100ContinueTestBody)))) -+ if err != nil { -+ test.t.Fatalf("unexpected error reading body: %v", err) -+ } -+ if got, want := string(got), transport100ContinueTestBody; got != want { -+ test.t.Fatalf("unexpected body: got %q, want %q", got, want) -+ } -+} -+ -+// wantRequestDone ensures the Transport.RoundTrip has completed with the expected status. -+func (test *transport100ContinueTest) wantRequestDone(want int) { -+ <-test.reqdone -+ if test.respErr != nil { -+ test.t.Fatalf("unexpected RoundTrip error: %v", test.respErr) -+ } -+ if got := test.resp.StatusCode; got != want { -+ test.t.Fatalf("unexpected response code: got %v, want %v", got, want) -+ } -+} -+ -+func TestTransportExpect100ContinueSent(t *testing.T) { -+ test := newTransport100ContinueTest(t, 1*time.Hour) -+ // Server sends a 100 Continue response, and the client sends the request body. -+ test.respond("HTTP/1.1 100 Continue") -+ test.wantBodySent() -+ test.respond("HTTP/1.1 200", "Content-Length: 0") -+ test.wantRequestDone(200) -+} -+ -+func TestTransportExpect100Continue200ResponseNoConnClose(t *testing.T) { -+ test := newTransport100ContinueTest(t, 1*time.Hour) -+ // No 100 Continue response, no Connection: close header. -+ test.respond("HTTP/1.1 200", "Content-Length: 0") -+ test.wantBodySent() -+ test.wantRequestDone(200) -+} -+ -+func TestTransportExpect100Continue200ResponseWithConnClose(t *testing.T) { -+ test := newTransport100ContinueTest(t, 1*time.Hour) -+ // No 100 Continue response, Connection: close header set. -+ test.respond("HTTP/1.1 200", "Connection: close", "Content-Length: 0") -+ test.wantRequestDone(200) -+} -+ -+func TestTransportExpect100Continue500ResponseNoConnClose(t *testing.T) { -+ test := newTransport100ContinueTest(t, 1*time.Hour) -+ // No 100 Continue response, no Connection: close header. -+ test.respond("HTTP/1.1 500", "Content-Length: 0") -+ test.wantBodySent() -+ test.wantRequestDone(500) -+} -+ -+func TestTransportExpect100Continue500ResponseTimeout(t *testing.T) { -+ test := newTransport100ContinueTest(t, 5*time.Millisecond) // short timeout -+ test.wantBodySent() // after timeout -+ test.respond("HTTP/1.1 200", "Content-Length: 0") -+ test.wantRequestDone(200) - } - - func TestSOCKS5Proxy(t *testing.T) { --- -2.41.0 - diff --git a/backport-0013-release-branch.go1.21-net-http-update-bundled-golang.patch b/backport-0013-release-branch.go1.21-net-http-update-bundled-golang.patch deleted file mode 100644 index e6db2741763df402343c5a10914cc9ab186dfe83..0000000000000000000000000000000000000000 --- a/backport-0013-release-branch.go1.21-net-http-update-bundled-golang.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0574d64ad35b51eb770d6cb59b46c9b3d8540999 Mon Sep 17 00:00:00 2001 -From: Dmitri Shuralyov -Date: Fri, 12 Apr 2024 15:46:59 -0400 -Subject: [PATCH] [release-branch.go1.21] net/http: update bundled - golang.org/x/net/http2 - -Reference:https://go-review.googlesource.com/c/go/+/578357 -Conflict:NA -Pull in CL 578336: - - ef58d90f http2: send correct LastStreamID in stream-caused GOAWAY - -For #66668. -Fixes #66697. - -Change-Id: I91fc8a67f21fadcb1801ff29d5e2b0453db89617 -Reviewed-on: https://go-review.googlesource.com/c/go/+/578357 -Reviewed-by: Carlos Amedee -Reviewed-by: Dmitri Shuralyov -LUCI-TryBot-Result: Go LUCI ---- - src/net/http/h2_bundle.go | 22 +++++++++++++++------- - 1 file changed, 15 insertions(+), 7 deletions(-) - -diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go -index cd95f84269..5ad0c2819b 100644 ---- a/src/net/http/h2_bundle.go -+++ b/src/net/http/h2_bundle.go -@@ -1891,6 +1891,9 @@ func http2terminalReadFrameError(err error) bool { - // returned error is ErrFrameTooLarge. Other errors may be of type - // ConnectionError, StreamError, or anything else from the underlying - // reader. -+// -+// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID -+// indicates the stream responsible for the error. - func (fr *http2Framer) ReadFrame() (http2Frame, error) { - fr.errDetail = nil - if fr.lastFrame != nil { -@@ -2923,7 +2926,7 @@ func (fr *http2Framer) maxHeaderStringLen() int { - // readMetaFrame returns 0 or more CONTINUATION frames from fr and - // merge them into the provided hf and returns a MetaHeadersFrame - // with the decoded hpack values. --func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFrame, error) { -+func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (http2Frame, error) { - if fr.AllowIllegalReads { - return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders") - } -@@ -2993,8 +2996,8 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - log.Printf("http2: header list too large") - } - // It would be nice to send a RST_STREAM before sending the GOAWAY, -- // but the struture of the server's frame writer makes this difficult. -- return nil, http2ConnectionError(http2ErrCodeProtocol) -+ // but the structure of the server's frame writer makes this difficult. -+ return mh, http2ConnectionError(http2ErrCodeProtocol) - } - - // Also close the connection after any CONTINUATION frame following an -@@ -3005,12 +3008,12 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - log.Printf("http2: invalid header: %v", invalid) - } - // It would be nice to send a RST_STREAM before sending the GOAWAY, -- // but the struture of the server's frame writer makes this difficult. -- return nil, http2ConnectionError(http2ErrCodeProtocol) -+ // but the structure of the server's frame writer makes this difficult. -+ return mh, http2ConnectionError(http2ErrCodeProtocol) - } - - if _, err := hdec.Write(frag); err != nil { -- return nil, http2ConnectionError(http2ErrCodeCompression) -+ return mh, http2ConnectionError(http2ErrCodeCompression) - } - - if hc.HeadersEnded() { -@@ -3027,7 +3030,7 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - mh.http2HeadersFrame.invalidate() - - if err := hdec.Close(); err != nil { -- return nil, http2ConnectionError(http2ErrCodeCompression) -+ return mh, http2ConnectionError(http2ErrCodeCompression) - } - if invalid != nil { - fr.errDetail = invalid -@@ -5337,6 +5340,11 @@ func (sc *http2serverConn) processFrameFromReader(res http2readFrameResult) bool - sc.goAway(http2ErrCodeFlowControl) - return true - case http2ConnectionError: -+ if res.f != nil { -+ if id := res.f.Header().StreamID; id > sc.maxClientStreamID { -+ sc.maxClientStreamID = id -+ } -+ } - sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev) - sc.goAway(http2ErrCode(ev)) - return true // goAway will handle shutdown --- -2.33.0 - diff --git a/backport-0014-cmd-compile-handle-constant-pointer-offsets-in-dead-.patch b/backport-0014-cmd-compile-handle-constant-pointer-offsets-in-dead-.patch deleted file mode 100644 index 80c9bbc435bc29922bb31de2ca8c5d820bafd1f4..0000000000000000000000000000000000000000 --- a/backport-0014-cmd-compile-handle-constant-pointer-offsets-in-dead-.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 131f773664fa2d0dbc870e11c388a3131a3a2029 Mon Sep 17 00:00:00 2001 -From: Keith Randall -Date: Sun, 29 Oct 2023 21:00:29 -0700 -Subject: cmd/compile: handle constant pointer offsets in dead store elimination - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/538595 - -Update #63657 -Update #45573 - -Change-Id: I163c6038c13d974dc0ca9f02144472bc05331826 -Reviewed-on: https://go-review.googlesource.com/c/go/+/538595 -LUCI-TryBot-Result: Go LUCI -Reviewed-by: David Chase -Reviewed-by: Keith Randall ---- - src/cmd/compile/internal/ssa/deadstore.go | 64 ++++++++++++++++++++--- - src/cmd/compile/internal/ssa/rewrite.go | 6 +++ - 2 files changed, 62 insertions(+), 8 deletions(-) - -diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go -index 648b68af78b1..7656e45cb9d5 100644 ---- a/src/cmd/compile/internal/ssa/deadstore.go -+++ b/src/cmd/compile/internal/ssa/deadstore.go -@@ -73,9 +73,9 @@ func dse(f *Func) { - } - - // Walk backwards looking for dead stores. Keep track of shadowed addresses. -- // A "shadowed address" is a pointer and a size describing a memory region that -- // is known to be written. We keep track of shadowed addresses in the shadowed -- // map, mapping the ID of the address to the size of the shadowed region. -+ // A "shadowed address" is a pointer, offset, and size describing a memory region that -+ // is known to be written. We keep track of shadowed addresses in the shadowed map, -+ // mapping the ID of the address to a shadowRange where future writes will happen. - // Since we're walking backwards, writes to a shadowed region are useless, - // as they will be immediately overwritten. - shadowed.clear() -@@ -88,13 +88,20 @@ func dse(f *Func) { - shadowed.clear() - } - if v.Op == OpStore || v.Op == OpZero { -+ ptr := v.Args[0] -+ var off int64 -+ for ptr.Op == OpOffPtr { // Walk to base pointer -+ off += ptr.AuxInt -+ ptr = ptr.Args[0] -+ } - var sz int64 - if v.Op == OpStore { - sz = v.Aux.(*types.Type).Size() - } else { // OpZero - sz = v.AuxInt - } -- if shadowedSize := int64(shadowed.get(v.Args[0].ID)); shadowedSize != -1 && shadowedSize >= sz { -+ sr := shadowRange(shadowed.get(ptr.ID)) -+ if sr.contains(off, off+sz) { - // Modify the store/zero into a copy of the memory state, - // effectively eliding the store operation. - if v.Op == OpStore { -@@ -108,10 +115,8 @@ func dse(f *Func) { - v.AuxInt = 0 - v.Op = OpCopy - } else { -- if sz > 0x7fffffff { // work around sparseMap's int32 value type -- sz = 0x7fffffff -- } -- shadowed.set(v.Args[0].ID, int32(sz)) -+ // Extend shadowed region. -+ shadowed.set(ptr.ID, int32(sr.merge(off, off+sz))) - } - } - // walk to previous store -@@ -131,6 +136,49 @@ func dse(f *Func) { - } - } - -+// A shadowRange encodes a set of byte offsets [lo():hi()] from -+// a given pointer that will be written to later in the block. -+// A zero shadowRange encodes an empty shadowed range (and so -+// does a -1 shadowRange, which is what sparsemap.get returns -+// on a failed lookup). -+type shadowRange int32 -+ -+func (sr shadowRange) lo() int64 { -+ return int64(sr & 0xffff) -+} -+func (sr shadowRange) hi() int64 { -+ return int64((sr >> 16) & 0xffff) -+} -+ -+// contains reports whether [lo:hi] is completely within sr. -+func (sr shadowRange) contains(lo, hi int64) bool { -+ return lo >= sr.lo() && hi <= sr.hi() -+} -+ -+// merge returns the union of sr and [lo:hi]. -+// merge is allowed to return something smaller than the union. -+func (sr shadowRange) merge(lo, hi int64) shadowRange { -+ if lo < 0 || hi > 0xffff { -+ // Ignore offsets that are too large or small. -+ return sr -+ } -+ if sr.lo() == sr.hi() { -+ // Old range is empty - use new one. -+ return shadowRange(lo + hi<<16) -+ } -+ if hi < sr.lo() || lo > sr.hi() { -+ // The two regions don't overlap or abut, so we would -+ // have to keep track of multiple disjoint ranges. -+ // Because we can only keep one, keep the larger one. -+ if sr.hi()-sr.lo() >= hi-lo { -+ return sr -+ } -+ return shadowRange(lo + hi<<16) -+ } -+ // Regions overlap or abut - compute the union. -+ return shadowRange(min(lo, sr.lo()) + max(hi, sr.hi())<<16) -+} -+ - // elimDeadAutosGeneric deletes autos that are never accessed. To achieve this - // we track the operations that the address of each auto reaches and if it only - // reaches stores then we delete all the stores. The other operations will then -diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go -index 43843bda5536..5c7ed16f12be 100644 ---- a/src/cmd/compile/internal/ssa/rewrite.go -+++ b/src/cmd/compile/internal/ssa/rewrite.go -@@ -1183,6 +1183,12 @@ func min(x, y int64) int64 { - } - return y - } -+func max(x, y int64) int64 { -+ if x > y { -+ return x -+ } -+ return y -+} - - func isConstZero(v *Value) bool { - switch v.Op { --- -2.33.0 - diff --git a/backport-0015-release-branch.go1.21-cmd-compile-ensure-pointer-ari.patch b/backport-0015-release-branch.go1.21-cmd-compile-ensure-pointer-ari.patch deleted file mode 100644 index 19223d4f424cf18282f3b633985ebe11cf44284b..0000000000000000000000000000000000000000 --- a/backport-0015-release-branch.go1.21-cmd-compile-ensure-pointer-ari.patch +++ /dev/null @@ -1,650 +0,0 @@ -From 8aa0b89560d65438d18fb8ed5ea90d7db2e18fa0 Mon Sep 17 00:00:00 2001 -From: Keith Randall -Date: Wed, 25 Oct 2023 13:35:13 -0700 -Subject: [release-branch.go1.21] cmd/compile: ensure pointer arithmetic - happens after the nil check - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/537775 - -Have nil checks return a pointer that is known non-nil. Users of -that pointer can use the result, ensuring that they are ordered -after the nil check itself. - -The order dependence goes away after scheduling, when we've fixed -an order. At that point we move uses back to the original pointer -so it doesn't change regalloc any. - -This prevents pointer arithmetic on nil from being spilled to the -stack and then observed by a stack scan. - -Fixes #63743 - -Change-Id: I1a5fa4f2e6d9000d672792b4f90dfc1b7b67f6ea -Reviewed-on: https://go-review.googlesource.com/c/go/+/537775 -Reviewed-by: David Chase -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Keith Randall -(cherry picked from commit 962ccbef91057f91518443b648e02fc3afe8c764) -Reviewed-on: https://go-review.googlesource.com/c/go/+/538717 -Auto-Submit: Heschi Kreinick -Reviewed-by: Heschi Kreinick ---- - .../compile/internal/ssa/_gen/generic.rules | 14 ++-- - .../compile/internal/ssa/_gen/genericOps.go | 2 +- - src/cmd/compile/internal/ssa/check.go | 23 ++++++- - src/cmd/compile/internal/ssa/deadcode.go | 7 +- - src/cmd/compile/internal/ssa/deadstore.go | 2 +- - src/cmd/compile/internal/ssa/fuse.go | 2 +- - src/cmd/compile/internal/ssa/fuse_test.go | 2 +- - src/cmd/compile/internal/ssa/nilcheck.go | 42 ++++++------ - src/cmd/compile/internal/ssa/opGen.go | 7 +- - src/cmd/compile/internal/ssa/rewrite.go | 3 + - .../compile/internal/ssa/rewritegeneric.go | 67 ++++++++++--------- - src/cmd/compile/internal/ssa/schedule.go | 18 ++++- - src/cmd/compile/internal/ssa/value.go | 6 +- - src/cmd/compile/internal/ssagen/ssa.go | 17 +++-- - test/fixedbugs/issue63657.go | 48 +++++++++++++ - 15 files changed, 179 insertions(+), 81 deletions(-) - create mode 100644 test/fixedbugs/issue63657.go - -diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules -index cdb346321e56..d3af465d0e0d 100644 ---- a/src/cmd/compile/internal/ssa/_gen/generic.rules -+++ b/src/cmd/compile/internal/ssa/_gen/generic.rules -@@ -981,7 +981,7 @@ - (ConstNil ) - (ConstNil )) - --(NilCheck (GetG mem) mem) => mem -+(NilCheck ptr:(GetG mem) mem) => ptr - - (If (Not cond) yes no) => (If cond no yes) - (If (ConstBool [c]) yes no) && c => (First yes no) -@@ -2055,19 +2055,19 @@ - && isSameCall(call.Aux, "runtime.newobject") - => mem - --(NilCheck (SelectN [0] call:(StaticLECall _ _)) _) -+(NilCheck ptr:(SelectN [0] call:(StaticLECall _ _)) _) - && isSameCall(call.Aux, "runtime.newobject") - && warnRule(fe.Debug_checknil(), v, "removed nil check") -- => (Invalid) -+ => ptr - --(NilCheck (OffPtr (SelectN [0] call:(StaticLECall _ _))) _) -+(NilCheck ptr:(OffPtr (SelectN [0] call:(StaticLECall _ _))) _) - && isSameCall(call.Aux, "runtime.newobject") - && warnRule(fe.Debug_checknil(), v, "removed nil check") -- => (Invalid) -+ => ptr - - // Addresses of globals are always non-nil. --(NilCheck (Addr {_} (SB)) _) => (Invalid) --(NilCheck (Convert (Addr {_} (SB)) _) _) => (Invalid) -+(NilCheck ptr:(Addr {_} (SB)) _) => ptr -+(NilCheck ptr:(Convert (Addr {_} (SB)) _) _) => ptr - - // for late-expanded calls, recognize memequal applied to a single constant byte - // Support is limited by 1, 2, 4, 8 byte sizes -diff --git a/src/cmd/compile/internal/ssa/_gen/genericOps.go b/src/cmd/compile/internal/ssa/_gen/genericOps.go -index 53ff57f6b12e..aa5fb0e03e66 100644 ---- a/src/cmd/compile/internal/ssa/_gen/genericOps.go -+++ b/src/cmd/compile/internal/ssa/_gen/genericOps.go -@@ -471,7 +471,7 @@ var genericOps = []opData{ - {name: "IsNonNil", argLength: 1, typ: "Bool"}, // arg0 != nil - {name: "IsInBounds", argLength: 2, typ: "Bool"}, // 0 <= arg0 < arg1. arg1 is guaranteed >= 0. - {name: "IsSliceInBounds", argLength: 2, typ: "Bool"}, // 0 <= arg0 <= arg1. arg1 is guaranteed >= 0. -- {name: "NilCheck", argLength: 2, typ: "Void"}, // arg0=ptr, arg1=mem. Panics if arg0 is nil. Returns void. -+ {name: "NilCheck", argLength: 2, nilCheck: true}, // arg0=ptr, arg1=mem. Panics if arg0 is nil. Returns the ptr unmodified. - - // Pseudo-ops - {name: "GetG", argLength: 1, zeroWidth: true}, // runtime.getg() (read g pointer). arg0=mem -diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go -index f34b9074197b..bbfdaceaad90 100644 ---- a/src/cmd/compile/internal/ssa/check.go -+++ b/src/cmd/compile/internal/ssa/check.go -@@ -317,7 +317,28 @@ func checkFunc(f *Func) { - if !v.Aux.(*ir.Name).Type().HasPointers() { - f.Fatalf("vardef must have pointer type %s", v.Aux.(*ir.Name).Type().String()) - } -- -+ case OpNilCheck: -+ // nil checks have pointer type before scheduling, and -+ // void type after scheduling. -+ if f.scheduled { -+ if v.Uses != 0 { -+ f.Fatalf("nilcheck must have 0 uses %s", v.Uses) -+ } -+ if !v.Type.IsVoid() { -+ f.Fatalf("nilcheck must have void type %s", v.Type.String()) -+ } -+ } else { -+ if !v.Type.IsPtrShaped() && !v.Type.IsUintptr() { -+ f.Fatalf("nilcheck must have pointer type %s", v.Type.String()) -+ } -+ } -+ if !v.Args[0].Type.IsPtrShaped() && !v.Args[0].Type.IsUintptr() { -+ f.Fatalf("nilcheck must have argument of pointer type %s", v.Args[0].Type.String()) -+ } -+ if !v.Args[1].Type.IsMemory() { -+ f.Fatalf("bad arg 1 type to %s: want mem, have %s", -+ v.Op, v.Args[1].Type.String()) -+ } - } - - // TODO: check for cycles in values -diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go -index 52cc7f2ca74d..ae9fd2ef2426 100644 ---- a/src/cmd/compile/internal/ssa/deadcode.go -+++ b/src/cmd/compile/internal/ssa/deadcode.go -@@ -110,16 +110,15 @@ func liveValues(f *Func, reachable []bool) (live []bool, liveOrderStmts []*Value - } - } - for _, v := range b.Values { -- if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects) && !live[v.ID] { -+ if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects || opcodeTable[v.Op].nilCheck) && !live[v.ID] { - live[v.ID] = true - q = append(q, v) - if v.Pos.IsStmt() != src.PosNotStmt { - liveOrderStmts = append(liveOrderStmts, v) - } - } -- if v.Type.IsVoid() && !live[v.ID] { -- // The only Void ops are nil checks and inline marks. We must keep these. -- if v.Op == OpInlMark && !liveInlIdx[int(v.AuxInt)] { -+ if v.Op == OpInlMark { -+ if !liveInlIdx[int(v.AuxInt)] { - // We don't need marks for bodies that - // have been completely optimized away. - // TODO: save marks only for bodies which -diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go -index 7656e45cb9d5..cb3427103c50 100644 ---- a/src/cmd/compile/internal/ssa/deadstore.go -+++ b/src/cmd/compile/internal/ssa/deadstore.go -@@ -249,7 +249,7 @@ func elimDeadAutosGeneric(f *Func) { - } - - if v.Uses == 0 && v.Op != OpNilCheck && !v.Op.IsCall() && !v.Op.HasSideEffects() || len(args) == 0 { -- // Nil check has no use, but we need to keep it. -+ // We need to keep nil checks even if they have no use. - // Also keep calls and values that have side effects. - return - } -diff --git a/src/cmd/compile/internal/ssa/fuse.go b/src/cmd/compile/internal/ssa/fuse.go -index 6d3fb7078059..68defde7b4b9 100644 ---- a/src/cmd/compile/internal/ssa/fuse.go -+++ b/src/cmd/compile/internal/ssa/fuse.go -@@ -169,7 +169,7 @@ func fuseBlockIf(b *Block) bool { - // There may be false positives. - func isEmpty(b *Block) bool { - for _, v := range b.Values { -- if v.Uses > 0 || v.Op.IsCall() || v.Op.HasSideEffects() || v.Type.IsVoid() { -+ if v.Uses > 0 || v.Op.IsCall() || v.Op.HasSideEffects() || v.Type.IsVoid() || opcodeTable[v.Op].nilCheck { - return false - } - } -diff --git a/src/cmd/compile/internal/ssa/fuse_test.go b/src/cmd/compile/internal/ssa/fuse_test.go -index fa7921a18f6f..2f89938d1d92 100644 ---- a/src/cmd/compile/internal/ssa/fuse_test.go -+++ b/src/cmd/compile/internal/ssa/fuse_test.go -@@ -254,7 +254,7 @@ func TestFuseSideEffects(t *testing.T) { - Valu("p", OpArg, c.config.Types.IntPtr, 0, nil), - If("c1", "z0", "exit")), - Bloc("z0", -- Valu("nilcheck", OpNilCheck, types.TypeVoid, 0, nil, "p", "mem"), -+ Valu("nilcheck", OpNilCheck, c.config.Types.IntPtr, 0, nil, "p", "mem"), - Goto("exit")), - Bloc("exit", - Exit("mem"), -diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go -index 4f797a473f71..c69cd8c32ed3 100644 ---- a/src/cmd/compile/internal/ssa/nilcheck.go -+++ b/src/cmd/compile/internal/ssa/nilcheck.go -@@ -38,11 +38,14 @@ func nilcheckelim(f *Func) { - work := make([]bp, 0, 256) - work = append(work, bp{block: f.Entry}) - -- // map from value ID to bool indicating if value is known to be non-nil -- // in the current dominator path being walked. This slice is updated by -+ // map from value ID to known non-nil version of that value ID -+ // (in the current dominator path being walked). This slice is updated by - // walkStates to maintain the known non-nil values. -- nonNilValues := f.Cache.allocBoolSlice(f.NumValues()) -- defer f.Cache.freeBoolSlice(nonNilValues) -+ // If there is extrinsic information about non-nil-ness, this map -+ // points a value to itself. If a value is known non-nil because we -+ // already did a nil check on it, it points to the nil check operation. -+ nonNilValues := f.Cache.allocValueSlice(f.NumValues()) -+ defer f.Cache.freeValueSlice(nonNilValues) - - // make an initial pass identifying any non-nil values - for _, b := range f.Blocks { -@@ -54,7 +57,7 @@ func nilcheckelim(f *Func) { - // We assume that SlicePtr is non-nil because we do a bounds check - // before the slice access (and all cap>0 slices have a non-nil ptr). See #30366. - if v.Op == OpAddr || v.Op == OpLocalAddr || v.Op == OpAddPtr || v.Op == OpOffPtr || v.Op == OpAdd32 || v.Op == OpAdd64 || v.Op == OpSub32 || v.Op == OpSub64 || v.Op == OpSlicePtr { -- nonNilValues[v.ID] = true -+ nonNilValues[v.ID] = v - } - } - } -@@ -68,16 +71,16 @@ func nilcheckelim(f *Func) { - if v.Op == OpPhi { - argsNonNil := true - for _, a := range v.Args { -- if !nonNilValues[a.ID] { -+ if nonNilValues[a.ID] == nil { - argsNonNil = false - break - } - } - if argsNonNil { -- if !nonNilValues[v.ID] { -+ if nonNilValues[v.ID] == nil { - changed = true - } -- nonNilValues[v.ID] = true -+ nonNilValues[v.ID] = v - } - } - } -@@ -103,8 +106,8 @@ func nilcheckelim(f *Func) { - if len(b.Preds) == 1 { - p := b.Preds[0].b - if p.Kind == BlockIf && p.Controls[0].Op == OpIsNonNil && p.Succs[0].b == b { -- if ptr := p.Controls[0].Args[0]; !nonNilValues[ptr.ID] { -- nonNilValues[ptr.ID] = true -+ if ptr := p.Controls[0].Args[0]; nonNilValues[ptr.ID] == nil { -+ nonNilValues[ptr.ID] = ptr - work = append(work, bp{op: ClearPtr, ptr: ptr}) - } - } -@@ -117,14 +120,11 @@ func nilcheckelim(f *Func) { - pendingLines.clear() - - // Next, process values in the block. -- i := 0 - for _, v := range b.Values { -- b.Values[i] = v -- i++ - switch v.Op { - case OpIsNonNil: - ptr := v.Args[0] -- if nonNilValues[ptr.ID] { -+ if nonNilValues[ptr.ID] != nil { - if v.Pos.IsStmt() == src.PosIsStmt { // Boolean true is a terrible statement boundary. - pendingLines.add(v.Pos) - v.Pos = v.Pos.WithNotStmt() -@@ -135,7 +135,7 @@ func nilcheckelim(f *Func) { - } - case OpNilCheck: - ptr := v.Args[0] -- if nonNilValues[ptr.ID] { -+ if nilCheck := nonNilValues[ptr.ID]; nilCheck != nil { - // This is a redundant implicit nil check. - // Logging in the style of the former compiler -- and omit line 1, - // which is usually in generated code. -@@ -145,14 +145,13 @@ func nilcheckelim(f *Func) { - if v.Pos.IsStmt() == src.PosIsStmt { // About to lose a statement boundary - pendingLines.add(v.Pos) - } -- v.reset(OpUnknown) -- f.freeValue(v) -- i-- -+ v.Op = OpCopy -+ v.SetArgs1(nilCheck) - continue - } - // Record the fact that we know ptr is non nil, and remember to - // undo that information when this dominator subtree is done. -- nonNilValues[ptr.ID] = true -+ nonNilValues[ptr.ID] = v - work = append(work, bp{op: ClearPtr, ptr: ptr}) - fallthrough // a non-eliminated nil check might be a good place for a statement boundary. - default: -@@ -163,7 +162,7 @@ func nilcheckelim(f *Func) { - } - } - // This reduces the lost statement count in "go" by 5 (out of 500 total). -- for j := 0; j < i; j++ { // is this an ordering problem? -+ for j := range b.Values { // is this an ordering problem? - v := b.Values[j] - if v.Pos.IsStmt() != src.PosNotStmt && !isPoorStatementOp(v.Op) && pendingLines.contains(v.Pos) { - v.Pos = v.Pos.WithIsStmt() -@@ -174,7 +173,6 @@ func nilcheckelim(f *Func) { - b.Pos = b.Pos.WithIsStmt() - pendingLines.remove(b.Pos) - } -- b.truncateValues(i) - - // Add all dominated blocks to the work list. - for w := sdom[node.block.ID].child; w != nil; w = sdom[w.ID].sibling { -@@ -182,7 +180,7 @@ func nilcheckelim(f *Func) { - } - - case ClearPtr: -- nonNilValues[node.ptr.ID] = false -+ nonNilValues[node.ptr.ID] = nil - continue - } - } -diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go -index 1480fcf45bfd..e7caf9050c15 100644 ---- a/src/cmd/compile/internal/ssa/opGen.go -+++ b/src/cmd/compile/internal/ssa/opGen.go -@@ -39373,9 +39373,10 @@ var opcodeTable = [...]opInfo{ - generic: true, - }, - { -- name: "NilCheck", -- argLen: 2, -- generic: true, -+ name: "NilCheck", -+ argLen: 2, -+ nilCheck: true, -+ generic: true, - }, - { - name: "GetG", -diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go -index 5c7ed16f12be..1cfdc3e10d10 100644 ---- a/src/cmd/compile/internal/ssa/rewrite.go -+++ b/src/cmd/compile/internal/ssa/rewrite.go -@@ -859,6 +859,9 @@ func disjoint(p1 *Value, n1 int64, p2 *Value, n2 int64) bool { - offset += base.AuxInt - base = base.Args[0] - } -+ if opcodeTable[base.Op].nilCheck { -+ base = base.Args[0] -+ } - return base, offset - } - p1, off1 := baseAndOffset(p1) -diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go -index e5bd8bc36f7d..574ac7a1a3ab 100644 ---- a/src/cmd/compile/internal/ssa/rewritegeneric.go -+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go -@@ -18967,79 +18967,84 @@ func rewriteValuegeneric_OpNilCheck(v *Value) bool { - v_0 := v.Args[0] - b := v.Block - fe := b.Func.fe -- // match: (NilCheck (GetG mem) mem) -- // result: mem -+ // match: (NilCheck ptr:(GetG mem) mem) -+ // result: ptr - for { -- if v_0.Op != OpGetG { -+ ptr := v_0 -+ if ptr.Op != OpGetG { - break - } -- mem := v_0.Args[0] -+ mem := ptr.Args[0] - if mem != v_1 { - break - } -- v.copyOf(mem) -+ v.copyOf(ptr) - return true - } -- // match: (NilCheck (SelectN [0] call:(StaticLECall _ _)) _) -+ // match: (NilCheck ptr:(SelectN [0] call:(StaticLECall _ _)) _) - // cond: isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check") -- // result: (Invalid) -+ // result: ptr - for { -- if v_0.Op != OpSelectN || auxIntToInt64(v_0.AuxInt) != 0 { -+ ptr := v_0 -+ if ptr.Op != OpSelectN || auxIntToInt64(ptr.AuxInt) != 0 { - break - } -- call := v_0.Args[0] -+ call := ptr.Args[0] - if call.Op != OpStaticLECall || len(call.Args) != 2 || !(isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")) { - break - } -- v.reset(OpInvalid) -+ v.copyOf(ptr) - return true - } -- // match: (NilCheck (OffPtr (SelectN [0] call:(StaticLECall _ _))) _) -+ // match: (NilCheck ptr:(OffPtr (SelectN [0] call:(StaticLECall _ _))) _) - // cond: isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check") -- // result: (Invalid) -+ // result: ptr - for { -- if v_0.Op != OpOffPtr { -+ ptr := v_0 -+ if ptr.Op != OpOffPtr { - break - } -- v_0_0 := v_0.Args[0] -- if v_0_0.Op != OpSelectN || auxIntToInt64(v_0_0.AuxInt) != 0 { -+ ptr_0 := ptr.Args[0] -+ if ptr_0.Op != OpSelectN || auxIntToInt64(ptr_0.AuxInt) != 0 { - break - } -- call := v_0_0.Args[0] -+ call := ptr_0.Args[0] - if call.Op != OpStaticLECall || len(call.Args) != 2 || !(isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")) { - break - } -- v.reset(OpInvalid) -+ v.copyOf(ptr) - return true - } -- // match: (NilCheck (Addr {_} (SB)) _) -- // result: (Invalid) -+ // match: (NilCheck ptr:(Addr {_} (SB)) _) -+ // result: ptr - for { -- if v_0.Op != OpAddr { -+ ptr := v_0 -+ if ptr.Op != OpAddr { - break - } -- v_0_0 := v_0.Args[0] -- if v_0_0.Op != OpSB { -+ ptr_0 := ptr.Args[0] -+ if ptr_0.Op != OpSB { - break - } -- v.reset(OpInvalid) -+ v.copyOf(ptr) - return true - } -- // match: (NilCheck (Convert (Addr {_} (SB)) _) _) -- // result: (Invalid) -+ // match: (NilCheck ptr:(Convert (Addr {_} (SB)) _) _) -+ // result: ptr - for { -- if v_0.Op != OpConvert { -+ ptr := v_0 -+ if ptr.Op != OpConvert { - break - } -- v_0_0 := v_0.Args[0] -- if v_0_0.Op != OpAddr { -+ ptr_0 := ptr.Args[0] -+ if ptr_0.Op != OpAddr { - break - } -- v_0_0_0 := v_0_0.Args[0] -- if v_0_0_0.Op != OpSB { -+ ptr_0_0 := ptr_0.Args[0] -+ if ptr_0_0.Op != OpSB { - break - } -- v.reset(OpInvalid) -+ v.copyOf(ptr) - return true - } - return false -diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go -index 19b98cc4b83b..0a7425c01729 100644 ---- a/src/cmd/compile/internal/ssa/schedule.go -+++ b/src/cmd/compile/internal/ssa/schedule.go -@@ -312,14 +312,21 @@ func schedule(f *Func) { - } - - // Remove SPanchored now that we've scheduled. -+ // Also unlink nil checks now that ordering is assured -+ // between the nil check and the uses of the nil-checked pointer. - for _, b := range f.Blocks { - for _, v := range b.Values { - for i, a := range v.Args { -- if a.Op == OpSPanchored { -+ if a.Op == OpSPanchored || opcodeTable[a.Op].nilCheck { - v.SetArg(i, a.Args[0]) - } - } - } -+ for i, c := range b.ControlValues() { -+ if c.Op == OpSPanchored || opcodeTable[c.Op].nilCheck { -+ b.ReplaceControl(i, c.Args[0]) -+ } -+ } - } - for _, b := range f.Blocks { - i := 0 -@@ -332,6 +339,15 @@ func schedule(f *Func) { - v.resetArgs() - f.freeValue(v) - } else { -+ if opcodeTable[v.Op].nilCheck { -+ if v.Uses != 0 { -+ base.Fatalf("nilcheck still has %d uses", v.Uses) -+ } -+ // We can't delete the nil check, but we mark -+ // it as having void type so regalloc won't -+ // try to allocate a register for it. -+ v.Type = types.TypeVoid -+ } - b.Values[i] = v - i++ - } -diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go -index e89024b3c665..9b52da1c58a9 100644 ---- a/src/cmd/compile/internal/ssa/value.go -+++ b/src/cmd/compile/internal/ssa/value.go -@@ -552,7 +552,11 @@ func (v *Value) LackingPos() bool { - // if its use count drops to 0. - func (v *Value) removeable() bool { - if v.Type.IsVoid() { -- // Void ops, like nil pointer checks, must stay. -+ // Void ops (inline marks), must stay. -+ return false -+ } -+ if opcodeTable[v.Op].nilCheck { -+ // Nil pointer checks must stay. - return false - } - if v.Type.IsMemory() { -diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go -index 597a196ba8c4..e994577c641d 100644 ---- a/src/cmd/compile/internal/ssagen/ssa.go -+++ b/src/cmd/compile/internal/ssagen/ssa.go -@@ -1991,7 +1991,8 @@ func (s *state) stmt(n ir.Node) { - case ir.OCHECKNIL: - n := n.(*ir.UnaryExpr) - p := s.expr(n.X) -- s.nilCheck(p) -+ _ = s.nilCheck(p) -+ // TODO: check that throwing away the nilcheck result is ok. - - case ir.OINLMARK: - n := n.(*ir.InlineMarkStmt) -@@ -5621,18 +5622,20 @@ func (s *state) exprPtr(n ir.Node, bounded bool, lineno src.XPos) *ssa.Value { - } - return p - } -- s.nilCheck(p) -+ p = s.nilCheck(p) - return p - } - - // nilCheck generates nil pointer checking code. - // Used only for automatically inserted nil checks, - // not for user code like 'x != nil'. --func (s *state) nilCheck(ptr *ssa.Value) { -+// Returns a "definitely not nil" copy of x to ensure proper ordering -+// of the uses of the post-nilcheck pointer. -+func (s *state) nilCheck(ptr *ssa.Value) *ssa.Value { - if base.Debug.DisableNil != 0 || s.curfn.NilCheckDisabled() { -- return -+ return ptr - } -- s.newValue2(ssa.OpNilCheck, types.TypeVoid, ptr, s.mem()) -+ return s.newValue2(ssa.OpNilCheck, ptr.Type, ptr, s.mem()) - } - - // boundsCheck generates bounds checking code. Checks if 0 <= idx <[=] len, branches to exit if not. -@@ -5984,8 +5987,8 @@ func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) - if !t.Elem().IsArray() { - s.Fatalf("bad ptr to array in slice %v\n", t) - } -- s.nilCheck(v) -- ptr = s.newValue1(ssa.OpCopy, types.NewPtr(t.Elem().Elem()), v) -+ nv := s.nilCheck(v) -+ ptr = s.newValue1(ssa.OpCopy, types.NewPtr(t.Elem().Elem()), nv) - len = s.constInt(types.Types[types.TINT], t.Elem().NumElem()) - cap = len - default: -diff --git a/test/fixedbugs/issue63657.go b/test/fixedbugs/issue63657.go -new file mode 100644 -index 000000000000..e32a4a34fbb6 ---- /dev/null -+++ b/test/fixedbugs/issue63657.go -@@ -0,0 +1,48 @@ -+// run -+ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Make sure address calculations don't float up before -+// the corresponding nil check. -+ -+package main -+ -+type T struct { -+ a, b int -+} -+ -+//go:noinline -+func f(x *T, p *bool, n int) { -+ *p = n != 0 -+ useStack(1000) -+ g(&x.b) -+} -+ -+//go:noinline -+func g(p *int) { -+} -+ -+func useStack(n int) { -+ if n == 0 { -+ return -+ } -+ useStack(n - 1) -+} -+ -+func main() { -+ mustPanic(func() { -+ var b bool -+ f(nil, &b, 3) -+ }) -+} -+ -+func mustPanic(f func()) { -+ defer func() { -+ if recover() == nil { -+ panic("expected panic, got nil") -+ } -+ }() -+ f() -+} --- -2.33.0 - diff --git a/backport-0016-release-branch.go1.21-internal-poll-add-SPLICE_F_NON.patch b/backport-0016-release-branch.go1.21-internal-poll-add-SPLICE_F_NON.patch deleted file mode 100644 index 134d88f55bbf2f5a1f485d2ce03bdaa272aaae56..0000000000000000000000000000000000000000 --- a/backport-0016-release-branch.go1.21-internal-poll-add-SPLICE_F_NON.patch +++ /dev/null @@ -1,79 +0,0 @@ -From fef8644451930464ffd9f13c82bcd451f58fa575 Mon Sep 17 00:00:00 2001 -From: Andy Pan -Date: Tue, 17 Oct 2023 22:38:17 +0800 -Subject: [PATCH 03/20] [release-branch.go1.21] internal/poll: add - SPLICE_F_NONBLOCK flag for splice to avoid inconsistency with O_NONBLOCK - -Fixes #63801 -Updates #59041 -Updates #63795 - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/536015 - -Details: https://github.com/golang/go/issues/59041#issuecomment-1766610087 - -Change-Id: Id3fc1df6d86b7c4cc383d09f9465fa8f4cc2a559 -Reviewed-on: https://go-review.googlesource.com/c/go/+/536015 -Reviewed-by: Bryan Mills -Reviewed-by: Ian Lance Taylor -LUCI-TryBot-Result: Go LUCI -Auto-Submit: Ian Lance Taylor -(cherry picked from commit 40cdf69fc9279ab28f84a6e0f965de8382c578fe) -Reviewed-on: https://go-review.googlesource.com/c/go/+/538117 -Auto-Submit: Heschi Kreinick -Reviewed-by: Mauri de Souza Meneguzzo -Reviewed-by: Heschi Kreinick ---- - src/internal/poll/splice_linux.go | 21 +++++++++++++++++++-- - 1 file changed, 19 insertions(+), 2 deletions(-) - -diff --git a/src/internal/poll/splice_linux.go b/src/internal/poll/splice_linux.go -index 9505c5dcfc1e..72cca34fe4ae 100644 ---- a/src/internal/poll/splice_linux.go -+++ b/src/internal/poll/splice_linux.go -@@ -13,6 +13,12 @@ import ( - ) - - const ( -+ // spliceNonblock doesn't make the splice itself necessarily nonblocking -+ // (because the actual file descriptors that are spliced from/to may block -+ // unless they have the O_NONBLOCK flag set), but it makes the splice pipe -+ // operations nonblocking. -+ spliceNonblock = 0x2 -+ - // maxSpliceSize is the maximum amount of data Splice asks - // the kernel to move in a single call to splice(2). - // We use 1MB as Splice writes data through a pipe, and 1MB is the default maximum pipe buffer size, -@@ -89,7 +95,11 @@ func spliceDrain(pipefd int, sock *FD, max int) (int, error) { - return 0, err - } - for { -- n, err := splice(pipefd, sock.Sysfd, max, 0) -+ // In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here, -+ // because it could return EAGAIN ceaselessly when the write end of the pipe is full, -+ // but this shouldn't be a concern here, since the pipe buffer must be sufficient for -+ // this data transmission on the basis of the workflow in Splice. -+ n, err := splice(pipefd, sock.Sysfd, max, spliceNonblock) - if err == syscall.EINTR { - continue - } -@@ -127,7 +137,14 @@ func splicePump(sock *FD, pipefd int, inPipe int) (int, error) { - } - written := 0 - for inPipe > 0 { -- n, err := splice(sock.Sysfd, pipefd, inPipe, 0) -+ // In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here, -+ // because it could return EAGAIN ceaselessly when the read end of the pipe is empty, -+ // but this shouldn't be a concern here, since the pipe buffer must contain inPipe size of -+ // data on the basis of the workflow in Splice. -+ n, err := splice(sock.Sysfd, pipefd, inPipe, spliceNonblock) -+ if err == syscall.EINTR { -+ continue -+ } - // Here, the condition n == 0 && err == nil should never be - // observed, since Splice controls the write side of the pipe. - if n > 0 { --- -2.33.0 - diff --git a/backport-0017-release-branch.go1.21-runtime-call-enableMetadataHug.patch b/backport-0017-release-branch.go1.21-runtime-call-enableMetadataHug.patch deleted file mode 100644 index dec6f61483b459de5946ef69b7ca9f4580255393..0000000000000000000000000000000000000000 --- a/backport-0017-release-branch.go1.21-runtime-call-enableMetadataHug.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 05bf700ebeec865b73500bd6a2ae93ddbd051692 Mon Sep 17 00:00:00 2001 -From: Michael Anthony Knyszek -Date: Fri, 10 Nov 2023 21:23:38 +0000 -Subject: [PATCH 04/20] [release-branch.go1.21] runtime: call - enableMetadataHugePages and its callees on the systemstack - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/541635 - -These functions acquire the heap lock. If they're not called on the -systemstack, a stack growth could cause a self-deadlock since stack -growth may allocate memory from the page heap. - -This has been a problem for a while. If this is what's plaguing the -ppc64 port right now, it's very surprising (and probably just -coincidental) that it's showing up now. - -For #64050. -For #64062. -For #64067. -Fixes #64073. - -Change-Id: I2b95dc134d17be63b9fe8f7a3370fe5b5438682f -Reviewed-on: https://go-review.googlesource.com/c/go/+/541635 -LUCI-TryBot-Result: Go LUCI -Run-TryBot: Michael Knyszek -Auto-Submit: Michael Knyszek -TryBot-Result: Gopher Robot -Reviewed-by: Michael Pratt -Reviewed-by: Paul Murphy -(cherry picked from commit 5f08b4479930af266d4a84c1533b320ed75edba7) -Reviewed-on: https://go-review.googlesource.com/c/go/+/541955 -Reviewed-by: Dmitri Shuralyov -Reviewed-by: Dmitri Shuralyov -Auto-Submit: Dmitri Shuralyov ---- - src/runtime/malloc.go | 4 ++++ - src/runtime/mgc.go | 4 +++- - src/runtime/mpagealloc.go | 4 ++++ - 3 files changed, 11 insertions(+), 1 deletion(-) - -diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go -index 44479cc2be26..b2026ad0dc72 100644 ---- a/src/runtime/malloc.go -+++ b/src/runtime/malloc.go -@@ -853,6 +853,10 @@ retry: - // - // The heap lock must not be held over this operation, since it will briefly acquire - // the heap lock. -+// -+// Must be called on the system stack because it acquires the heap lock. -+// -+//go:systemstack - func (h *mheap) enableMetadataHugePages() { - // Enable huge pages for page structure. - h.pages.enableChunkHugePages() -diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go -index de5ae0ae00c4..a12dbfe9df29 100644 ---- a/src/runtime/mgc.go -+++ b/src/runtime/mgc.go -@@ -1186,7 +1186,9 @@ func gcMarkTermination() { - - // Enable huge pages on some metadata if we cross a heap threshold. - if gcController.heapGoal() > minHeapForMetadataHugePages { -- mheap_.enableMetadataHugePages() -+ systemstack(func() { -+ mheap_.enableMetadataHugePages() -+ }) - } - - semrelease(&worldsema) -diff --git a/src/runtime/mpagealloc.go b/src/runtime/mpagealloc.go -index 3e789ab85cc0..2861fa93ebf0 100644 ---- a/src/runtime/mpagealloc.go -+++ b/src/runtime/mpagealloc.go -@@ -437,6 +437,10 @@ func (p *pageAlloc) grow(base, size uintptr) { - // - // The heap lock must not be held over this operation, since it will briefly acquire - // the heap lock. -+// -+// Must be called on the system stack because it acquires the heap lock. -+// -+//go:systemstack - func (p *pageAlloc) enableChunkHugePages() { - // Grab the heap lock to turn on huge pages for new chunks and clone the current - // heap address space ranges. --- -2.33.0 - diff --git a/backport-0018-release-branch.go1.21-cmd-compile-fix-findIndVar-so-.patch b/backport-0018-release-branch.go1.21-cmd-compile-fix-findIndVar-so-.patch deleted file mode 100644 index fbd8b6a600b340a0173205e7cec69ac8c5e1da15..0000000000000000000000000000000000000000 --- a/backport-0018-release-branch.go1.21-cmd-compile-fix-findIndVar-so-.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 4ef68a16e21a2e63f2f6bdc498fe34c9ca994011 Mon Sep 17 00:00:00 2001 -From: Jorropo -Date: Sun, 5 Nov 2023 22:40:01 +0100 -Subject: [PATCH 05/20] [release-branch.go1.21] cmd/compile: fix findIndVar so - it does not match disjointed loop headers - -Fix #63984 - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/539977 - -parseIndVar, prove and maybe more are on the assumption that the loop header -is a single block. This can be wrong, ensure we don't match theses cases we -don't know how to handle. - -In the future we could update them so that they know how to handle such cases -but theses cases seems rare so I don't think the value would be really high. -We could also run a loop canonicalization pass first which could handle this. - -The repro case looks weird because I massaged it so it would crash with the -previous compiler. - -Change-Id: I4aa8afae9e90a17fa1085832250fc1139c97faa6 -Reviewed-on: https://go-review.googlesource.com/c/go/+/539977 -Reviewed-by: Heschi Kreinick -Reviewed-by: Keith Randall -Reviewed-by: Keith Randall -LUCI-TryBot-Result: Go LUCI -(cherry picked from commit 8b4e1259d0e82c8fe38a1456f997a4e9d63573a2) -Reviewed-on: https://go-review.googlesource.com/c/go/+/540535 -Reviewed-by: Jorropo -Reviewed-by: Mauri de Souza Meneguzzo -Reviewed-by: Dmitri Shuralyov -Reviewed-by: Dmitri Shuralyov -Auto-Submit: Dmitri Shuralyov -Reviewed-by: Michael Knyszek ---- - src/cmd/compile/internal/ssa/loopbce.go | 7 +++++++ - test/fixedbugs/issue63955.go | 22 ++++++++++++++++++++++ - 2 files changed, 29 insertions(+) - create mode 100644 test/fixedbugs/issue63955.go - -diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go -index b7dfaa33e3bf..7f432e61ba50 100644 ---- a/src/cmd/compile/internal/ssa/loopbce.go -+++ b/src/cmd/compile/internal/ssa/loopbce.go -@@ -127,6 +127,13 @@ func findIndVar(f *Func) []indVar { - less = false - } - -+ if ind.Block != b { -+ // TODO: Could be extended to include disjointed loop headers. -+ // I don't think this is causing missed optimizations in real world code often. -+ // See https://go.dev/issue/63955 -+ continue -+ } -+ - // Expect the increment to be a nonzero constant. - if !inc.isGenericIntConst() { - continue -diff --git a/test/fixedbugs/issue63955.go b/test/fixedbugs/issue63955.go -new file mode 100644 -index 000000000000..258e874220f0 ---- /dev/null -+++ b/test/fixedbugs/issue63955.go -@@ -0,0 +1,22 @@ -+// compile -+ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package j -+ -+func f(try func() int, shouldInc func() bool, N func(int) int) { -+ var n int -+loop: // we want to have 3 preds here, the function entry and both gotos -+ if v := try(); v == 42 || v == 1337 { // the two || are to trick findIndVar -+ if n < 30 { // this aims to be the matched block -+ if shouldInc() { -+ n++ -+ goto loop -+ } -+ n = N(n) // try to prevent some block joining -+ goto loop -+ } -+ } -+} --- -2.33.0 - diff --git a/backport-0019-release-branch.go1.21-cmd-compile-fix-escape-analysi.patch b/backport-0019-release-branch.go1.21-cmd-compile-fix-escape-analysi.patch deleted file mode 100644 index 8aa6e2e6589c8a1a2243dd94781268b2b2a65a0d..0000000000000000000000000000000000000000 --- a/backport-0019-release-branch.go1.21-cmd-compile-fix-escape-analysi.patch +++ /dev/null @@ -1,112 +0,0 @@ -From ce09caaeea688251e21a1749ccb89d9160fe2fb2 Mon Sep 17 00:00:00 2001 -From: Matthew Dempsky -Date: Tue, 5 Dec 2023 12:56:04 -0800 -Subject: [PATCH 06/20] [release-branch.go1.21] cmd/compile: fix escape - analysis of string min/max - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/547715 - -When I was plumbing min/max support through the compiler, I was -thinking mostly about numeric argument types. As a result, I forgot -that escape analysis would need to be aware that min/max can operate -on string values, which contain pointers. - -Updates #64565. -Fixes #64567. - -Change-Id: I36127ce5a2da942401910fa0f9de922726c9f94d -Reviewed-on: https://go-review.googlesource.com/c/go/+/547715 -Reviewed-by: Keith Randall -Reviewed-by: Mauri de Souza Meneguzzo -Auto-Submit: Matthew Dempsky -LUCI-TryBot-Result: Go LUCI -(cherry picked from commit 34416d7f6f93cd6562636e311c362ebe421f1a4c) -Reviewed-on: https://go-review.googlesource.com/c/go/+/547757 -Reviewed-by: Cuong Manh Le -Reviewed-by: Keith Randall ---- - src/cmd/compile/internal/escape/call.go | 10 +++++++++- - test/escape_calls.go | 7 +++++++ - test/fixedbugs/issue64565.go | 15 +++++++++++++++ - test/fixedbugs/issue64565.out | 3 +++ - 4 files changed, 34 insertions(+), 1 deletion(-) - create mode 100644 test/fixedbugs/issue64565.go - create mode 100644 test/fixedbugs/issue64565.out - -diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go -index c69eca199877..36e606bf2090 100644 ---- a/src/cmd/compile/internal/escape/call.go -+++ b/src/cmd/compile/internal/escape/call.go -@@ -186,7 +186,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir - argument(e.discardHole(), &call.X) - argument(e.discardHole(), &call.Y) - -- case ir.ODELETE, ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: -+ case ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: - call := call.(*ir.CallExpr) - fixRecoverCall(call) - for i := range call.Args { -@@ -194,6 +194,14 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir - } - argumentRType(&call.RType) - -+ case ir.OMIN, ir.OMAX: -+ call := call.(*ir.CallExpr) -+ fixRecoverCall(call) -+ for i := range call.Args { -+ argument(ks[0], &call.Args[i]) -+ } -+ argumentRType(&call.RType) -+ - case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE, ir.OCLEAR: - call := call.(*ir.UnaryExpr) - argument(e.discardHole(), &call.X) -diff --git a/test/escape_calls.go b/test/escape_calls.go -index aa7c7f516cf9..5424c006ee4d 100644 ---- a/test/escape_calls.go -+++ b/test/escape_calls.go -@@ -52,3 +52,10 @@ func bar() { - s := "string" - f([]string{s}) // ERROR "\[\]string{...} escapes to heap" - } -+ -+func strmin(a, b, c string) string { // ERROR "leaking param: a to result ~r0 level=0" "leaking param: b to result ~r0 level=0" "leaking param: c to result ~r0 level=0" -+ return min(a, b, c) -+} -+func strmax(a, b, c string) string { // ERROR "leaking param: a to result ~r0 level=0" "leaking param: b to result ~r0 level=0" "leaking param: c to result ~r0 level=0" -+ return max(a, b, c) -+} -diff --git a/test/fixedbugs/issue64565.go b/test/fixedbugs/issue64565.go -new file mode 100644 -index 000000000000..634025ce3ece ---- /dev/null -+++ b/test/fixedbugs/issue64565.go -@@ -0,0 +1,15 @@ -+// run -+ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package main -+ -+func main() { -+ m := "0" -+ for _, c := range "321" { -+ m = max(string(c), m) -+ println(m) -+ } -+} -diff --git a/test/fixedbugs/issue64565.out b/test/fixedbugs/issue64565.out -new file mode 100644 -index 000000000000..1f242fa6f000 ---- /dev/null -+++ b/test/fixedbugs/issue64565.out -@@ -0,0 +1,3 @@ -+3 -+3 -+3 --- -2.33.0 - diff --git a/backport-0020-CVE-2024-34155-track-depth-in-nested-element-lists.patch b/backport-0020-CVE-2024-34155-track-depth-in-nested-element-lists.patch deleted file mode 100644 index a1a761f8455d4242a5a9135e019073fafa8018dd..0000000000000000000000000000000000000000 --- a/backport-0020-CVE-2024-34155-track-depth-in-nested-element-lists.patch +++ /dev/null @@ -1,60 +0,0 @@ -commit b232596139dbe96a62edbe3a2a203e856bf556eb -Author: Roland Shoemaker -Date: Mon Jun 10 15:34:12 2024 -0700 - - [release-branch.go1.22] go/parser: track depth in nested element lists - - Prevents stack exhaustion with extremely deeply nested literal values, - i.e. field values in structs. - - Updates #69138 - Fixes #69142 - Fixes CVE-2024-34155 - - Change-Id: I2e8e33b44105cc169d7ed1ae83fb56df0c10f1ee - Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1520 - Reviewed-by: Robert Griesemer - Reviewed-by: Damien Neil - Reviewed-by: Russ Cox - (cherry picked from commit eb1b038c0d01761694e7a735ef87ac9164c6568e) - Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1561 - Reviewed-by: Tatiana Bradley - Reviewed-on: https://go-review.googlesource.com/c/go/+/611181 - Reviewed-by: Michael Pratt - TryBot-Bypass: Dmitri Shuralyov - Auto-Submit: Dmitri Shuralyov - Reviewed-by: Dmitri Shuralyov - -diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go -index 17808b366f..f268dea1a6 100644 ---- a/src/go/parser/parser.go -+++ b/src/go/parser/parser.go -@@ -1676,6 +1676,8 @@ func (p *parser) parseElementList() (list []ast.Expr) { - } - - func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr { -+ defer decNestLev(incNestLev(p)) -+ - if p.trace { - defer un(trace(p, "LiteralValue")) - } -diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go -index 43b3416b27..c6dca66760 100644 ---- a/src/go/parser/parser_test.go -+++ b/src/go/parser/parser_test.go -@@ -598,10 +598,11 @@ var parseDepthTests = []struct { - {name: "chan2", format: "package main; var x «<-chan »int"}, - {name: "interface", format: "package main; var x «interface { M() «int» }»", scope: true, scopeMultiplier: 2}, // Scopes: InterfaceType, FuncType - {name: "map", format: "package main; var x «map[int]»int"}, -- {name: "slicelit", format: "package main; var x = «[]any{«»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit -- {name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit -- {name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit -- {name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 2}, // Parser nodes: CompositeLit, KeyValueExpr -+ {name: "slicelit", format: "package main; var x = []any{«[]any{«»}»}", parseMultiplier: 3}, // Parser nodes: UnaryExpr, CompositeLit -+ {name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 3}, // Parser nodes: UnaryExpr, CompositeLit -+ {name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 3}, // Parser nodes: UnaryExpr, CompositeLit -+ {name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 3}, // Parser nodes: CompositeLit, KeyValueExpr -+ {name: "element", format: "package main; var x = struct{x any}{x: «{«»}»}"}, - {name: "dot", format: "package main; var x = «x.»x"}, - {name: "index", format: "package main; var x = x«[1]»"}, - {name: "slice", format: "package main; var x = x«[1:2]»"}, diff --git a/backport-0021-release-branch.go1.21-runtime-pprof-fix-generics-fun.patch b/backport-0021-release-branch.go1.21-runtime-pprof-fix-generics-fun.patch deleted file mode 100644 index fe0998db53fc39474afb8a25fc4b9f5d3b53d186..0000000000000000000000000000000000000000 --- a/backport-0021-release-branch.go1.21-runtime-pprof-fix-generics-fun.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 2e4454a248c40017e922db682f231c5a0330f4b2 Mon Sep 17 00:00:00 2001 -From: Tolya Korniltsev -Date: Mon, 4 Dec 2023 17:53:29 +0700 -Subject: [PATCH 07/20] [release-branch.go1.21] runtime/pprof: fix generics - function names - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/546815 - -profileBuilder is using Frame->Function as key for checking if we already -emitted a function. However for generics functions it has dots there [...], -so sometimes for different functions with different generics types, -the profileBuilder emits wrong functions. - -For #64528 -For #64609 - -Change-Id: I8b39245e0b18f4288ce758c912c6748f87cba39a -Reviewed-on: https://go-review.googlesource.com/c/go/+/546815 -Reviewed-by: Cherry Mui -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Michael Pratt -(cherry picked from commit 20a03fc7130d8d99b513071c7e413b436ea649a2) -Reviewed-on: https://go-review.googlesource.com/c/go/+/549535 -Auto-Submit: Matthew Dempsky ---- - src/runtime/pprof/proto.go | 7 ++-- - src/runtime/pprof/protomem_test.go | 62 ++++++++++++++++++++++++++++++ - 2 files changed, 66 insertions(+), 3 deletions(-) - -diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go -index cdc4bd7c80d8..db9384eb214e 100644 ---- a/src/runtime/pprof/proto.go -+++ b/src/runtime/pprof/proto.go -@@ -611,13 +611,14 @@ func (b *profileBuilder) emitLocation() uint64 { - b.pb.uint64Opt(tagLocation_Address, uint64(firstFrame.PC)) - for _, frame := range b.deck.frames { - // Write out each line in frame expansion. -- funcID := uint64(b.funcs[frame.Function]) -+ funcName := runtime_FrameSymbolName(&frame) -+ funcID := uint64(b.funcs[funcName]) - if funcID == 0 { - funcID = uint64(len(b.funcs)) + 1 -- b.funcs[frame.Function] = int(funcID) -+ b.funcs[funcName] = int(funcID) - newFuncs = append(newFuncs, newFunc{ - id: funcID, -- name: runtime_FrameSymbolName(&frame), -+ name: funcName, - file: frame.File, - startLine: int64(runtime_FrameStartLine(&frame)), - }) -diff --git a/src/runtime/pprof/protomem_test.go b/src/runtime/pprof/protomem_test.go -index 156f6286a92f..505c323d6867 100644 ---- a/src/runtime/pprof/protomem_test.go -+++ b/src/runtime/pprof/protomem_test.go -@@ -6,8 +6,11 @@ package pprof - - import ( - "bytes" -+ "fmt" - "internal/profile" - "runtime" -+ "slices" -+ "strings" - "testing" - ) - -@@ -82,3 +85,62 @@ func TestConvertMemProfile(t *testing.T) { - }) - } - } -+ -+func genericAllocFunc[T interface{ uint32 | uint64 }](n int) []T { -+ return make([]T, n) -+} -+ -+func profileToString(p *profile.Profile) []string { -+ var res []string -+ for _, s := range p.Sample { -+ var funcs []string -+ for i := len(s.Location) - 1; i >= 0; i-- { -+ loc := s.Location[i] -+ for j := len(loc.Line) - 1; j >= 0; j-- { -+ line := loc.Line[j] -+ funcs = append(funcs, line.Function.Name) -+ } -+ } -+ res = append(res, fmt.Sprintf("%s %v", strings.Join(funcs, ";"), s.Value)) -+ } -+ return res -+} -+ -+// This is a regression test for https://go.dev/issue/64528 . -+func TestGenericsHashKeyInPprofBuilder(t *testing.T) { -+ previousRate := runtime.MemProfileRate -+ runtime.MemProfileRate = 1 -+ defer func() { -+ runtime.MemProfileRate = previousRate -+ }() -+ for _, sz := range []int{128, 256} { -+ genericAllocFunc[uint32](sz / 4) -+ } -+ for _, sz := range []int{32, 64} { -+ genericAllocFunc[uint64](sz / 8) -+ } -+ -+ runtime.GC() -+ buf := bytes.NewBuffer(nil) -+ if err := WriteHeapProfile(buf); err != nil { -+ t.Fatalf("writing profile: %v", err) -+ } -+ p, err := profile.Parse(buf) -+ if err != nil { -+ t.Fatalf("profile.Parse: %v", err) -+ } -+ -+ actual := profileToString(p) -+ expected := []string{ -+ "testing.tRunner;runtime/pprof.TestGenericsHashKeyInPprofBuilder;runtime/pprof.genericAllocFunc[go.shape.uint32] [1 128 0 0]", -+ "testing.tRunner;runtime/pprof.TestGenericsHashKeyInPprofBuilder;runtime/pprof.genericAllocFunc[go.shape.uint32] [1 256 0 0]", -+ "testing.tRunner;runtime/pprof.TestGenericsHashKeyInPprofBuilder;runtime/pprof.genericAllocFunc[go.shape.uint64] [1 32 0 0]", -+ "testing.tRunner;runtime/pprof.TestGenericsHashKeyInPprofBuilder;runtime/pprof.genericAllocFunc[go.shape.uint64] [1 64 0 0]", -+ } -+ -+ for _, l := range expected { -+ if !slices.Contains(actual, l) { -+ t.Errorf("profile = %v\nwant = %v", strings.Join(actual, "\n"), l) -+ } -+ } -+} --- -2.33.0 - diff --git a/backport-0022-encoding-gob-cover-missed-cases-when-checking-ignore.patch b/backport-0022-encoding-gob-cover-missed-cases-when-checking-ignore.patch deleted file mode 100644 index b101a9fa31c444ec68111f363bfc26429f61394f..0000000000000000000000000000000000000000 --- a/backport-0022-encoding-gob-cover-missed-cases-when-checking-ignore.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 08c84420bc40d1cd5eb71b85cbe3a36f707bdb3f Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Fri, 03 May 2024 09:21:39 -0400 -Subject: [PATCH] encoding/gob: cover missed cases when checking ignore depth - -This change makes sure that we are properly checking the ignored field -recursion depth in decIgnoreOpFor consistently. This prevents stack -exhaustion when attempting to decode a message that contains an -extremely deeply nested struct which is ignored. - -Thanks to Md Sakib Anwar of The Ohio State University (anwar.40@osu.edu) -for reporting this issue. - -Fixes #69139 -Fixes CVE-2024-34156 - -Edited-by: Wang Shuo - -Change-Id: Iacce06be95a5892b3064f1c40fcba2e2567862d6 -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1440 -Reviewed-by: Russ Cox -Reviewed-by: Damien Neil -Reviewed-on: https://go-review.googlesource.com/c/go/+/611239 -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Dmitri Shuralyov -Reviewed-by: Roland Shoemaker -Auto-Submit: Dmitri Shuralyov ---- - src/encoding/gob/decode.go | 19 +++++++++++-------- - src/encoding/gob/decoder.go | 2 ++ - src/encoding/gob/gobencdec_test.go | 14 ++++++++++++++ - 3 files changed, 27 insertions(+), 8 deletions(-) - -diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go -index c0b054e..a2d4eab 100644 ---- a/src/encoding/gob/decode.go -+++ b/src/encoding/gob/decode.go -@@ -911,8 +911,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg - var maxIgnoreNestingDepth = 10000 - - // decIgnoreOpFor returns the decoding op for a field that has no destination. --func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp { -- if depth > maxIgnoreNestingDepth { -+func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp { -+ // Track how deep we've recursed trying to skip nested ignored fields. -+ dec.ignoreDepth++ -+ defer func() { dec.ignoreDepth-- }() -+ if dec.ignoreDepth > maxIgnoreNestingDepth { - error_(errors.New("invalid nesting depth")) - } - // If this type is already in progress, it's a recursive type (e.g. map[string]*T). -@@ -938,7 +941,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, - errorf("bad data: undefined type %s", wireId.string()) - case wire.ArrayT != nil: - elemId := wire.ArrayT.Elem -- elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) -+ elemOp := dec.decIgnoreOpFor(elemId, inProgress) - op = func(i *decInstr, state *decoderState, value reflect.Value) { - state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len) - } -@@ -946,15 +949,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, - case wire.MapT != nil: - keyId := dec.wireType[wireId].MapT.Key - elemId := dec.wireType[wireId].MapT.Elem -- keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1) -- elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) -+ keyOp := dec.decIgnoreOpFor(keyId, inProgress) -+ elemOp := dec.decIgnoreOpFor(elemId, inProgress) - op = func(i *decInstr, state *decoderState, value reflect.Value) { - state.dec.ignoreMap(state, *keyOp, *elemOp) - } - - case wire.SliceT != nil: - elemId := wire.SliceT.Elem -- elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) -+ elemOp := dec.decIgnoreOpFor(elemId, inProgress) - op = func(i *decInstr, state *decoderState, value reflect.Value) { - state.dec.ignoreSlice(state, *elemOp) - } -@@ -1115,7 +1118,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de - func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine { - engine := new(decEngine) - engine.instr = make([]decInstr, 1) // one item -- op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0) -+ op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp)) - ovfl := overflow(dec.typeString(remoteId)) - engine.instr[0] = decInstr{*op, 0, nil, ovfl} - engine.numInstr = 1 -@@ -1160,7 +1163,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn - localField, present := srt.FieldByName(wireField.Name) - // TODO(r): anonymous names - if !present || !isExported(wireField.Name) { -- op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0) -+ op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp)) - engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl} - continue - } -diff --git a/src/encoding/gob/decoder.go b/src/encoding/gob/decoder.go -index 5b77adc..4da5717 100644 ---- a/src/encoding/gob/decoder.go -+++ b/src/encoding/gob/decoder.go -@@ -35,6 +35,8 @@ type Decoder struct { - freeList *decoderState // list of free decoderStates; avoids reallocation - countBuf []byte // used for decoding integers while parsing messages - err error -+ // ignoreDepth tracks the depth of recursively parsed ignored fields -+ ignoreDepth int - } - - // NewDecoder returns a new decoder that reads from the io.Reader. -diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go -index 6fefd36..3955e28 100644 ---- a/src/encoding/gob/gobencdec_test.go -+++ b/src/encoding/gob/gobencdec_test.go -@@ -806,6 +806,8 @@ func TestIgnoreDepthLimit(t *testing.T) { - defer func() { maxIgnoreNestingDepth = oldNestingDepth }() - b := new(bytes.Buffer) - enc := NewEncoder(b) -+ -+ // Nested slice - typ := reflect.TypeOf(int(0)) - nested := reflect.ArrayOf(1, typ) - for i := 0; i < 100; i++ { -@@ -819,4 +821,16 @@ func TestIgnoreDepthLimit(t *testing.T) { - if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { - t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) - } -+ -+ // Nested struct -+ nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: typ}}) -+ for i := 0; i < 100; i++ { -+ nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}) -+ } -+ badStruct = reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})) -+ enc.Encode(badStruct.Interface()) -+ dec = NewDecoder(b) -+ if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { -+ t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) -+ } - } --- -2.27.0 - diff --git a/backport-0023-go-build-constraint-add-parsing-limits.patch b/backport-0023-go-build-constraint-add-parsing-limits.patch deleted file mode 100644 index 2070bc4abf74e5926ebce032b0cee0cbdc333fbd..0000000000000000000000000000000000000000 --- a/backport-0023-go-build-constraint-add-parsing-limits.patch +++ /dev/null @@ -1,198 +0,0 @@ -From f22d73197635b23c13bb852e330e5339eefaf910 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Thu, 20 Jun 2024 10:45:30 -0700 -Subject: [PATCH] go/build/constraint: add parsing limits - -Limit the size of build constraints that we will parse. This prevents a -number of stack exhaustions that can be hit when parsing overly complex -constraints. The imposed limits are unlikely to ever be hit in real -world usage. - -Fixes #69141 -Fixes CVE-2024-34158 - -Edited-by: Wang Shuo - -Change-Id: I38b614bf04caa36eefc6a4350d848588c4cef3c4 -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1540 -Reviewed-by: Damien Neil -Reviewed-by: Russ Cox -Reviewed-on: https://go-review.googlesource.com/c/go/+/611240 -Reviewed-by: Dmitri Shuralyov -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Roland Shoemaker -Auto-Submit: Dmitri Shuralyov ---- - src/go/build/constraint/expr.go | 28 ++++++++++-- - src/go/build/constraint/expr_test.go | 65 +++++++++++++++++++++++++++- - 2 files changed, 89 insertions(+), 4 deletions(-) - -diff --git a/src/go/build/constraint/expr.go b/src/go/build/constraint/expr.go -index 505cbff..c438a8a 100644 ---- a/src/go/build/constraint/expr.go -+++ b/src/go/build/constraint/expr.go -@@ -16,6 +16,10 @@ import ( - "unicode/utf8" - ) - -+// maxSize is a limit used to control the complexity of expressions, in order -+// to prevent stack exhaustion issues due to recursion. -+const maxSize = 1000 -+ - // An Expr is a build tag constraint expression. - // The underlying concrete type is *AndExpr, *OrExpr, *NotExpr, or *TagExpr. - type Expr interface { -@@ -151,7 +155,7 @@ func Parse(line string) (Expr, error) { - return parseExpr(text) - } - if text, ok := splitPlusBuild(line); ok { -- return parsePlusBuildExpr(text), nil -+ return parsePlusBuildExpr(text) - } - return nil, errNotConstraint - } -@@ -201,6 +205,8 @@ type exprParser struct { - tok string // last token read - isTag bool - pos int // position (start) of last token -+ -+ size int - } - - // parseExpr parses a boolean build tag expression. -@@ -249,6 +255,10 @@ func (p *exprParser) and() Expr { - // On entry, the next input token has not yet been lexed. - // On exit, the next input token has been lexed and is in p.tok. - func (p *exprParser) not() Expr { -+ p.size++ -+ if p.size > maxSize { -+ panic(&SyntaxError{Offset: p.pos, Err: "build expression too large"}) -+ } - p.lex() - if p.tok == "!" { - p.lex() -@@ -388,7 +398,13 @@ func splitPlusBuild(line string) (expr string, ok bool) { - } - - // parsePlusBuildExpr parses a legacy build tag expression (as used with “// +build”). --func parsePlusBuildExpr(text string) Expr { -+func parsePlusBuildExpr(text string) (Expr, error) { -+ // Only allow up to 100 AND/OR operators for "old" syntax. -+ // This is much less than the limit for "new" syntax, -+ // but uses of old syntax were always very simple. -+ const maxOldSize = 100 -+ size := 0 -+ - var x Expr - for _, clause := range strings.Fields(text) { - var y Expr -@@ -414,19 +430,25 @@ func parsePlusBuildExpr(text string) Expr { - if y == nil { - y = z - } else { -+ if size++; size > maxOldSize { -+ return nil, errComplex -+ } - y = and(y, z) - } - } - if x == nil { - x = y - } else { -+ if size++; size > maxOldSize { -+ return nil, errComplex -+ } - x = or(x, y) - } - } - if x == nil { - x = tag("ignore") - } -- return x -+ return x, nil - } - - // isValidTag reports whether the word is a valid build tag. -diff --git a/src/go/build/constraint/expr_test.go b/src/go/build/constraint/expr_test.go -index 15d1890..ac38ba6 100644 ---- a/src/go/build/constraint/expr_test.go -+++ b/src/go/build/constraint/expr_test.go -@@ -222,7 +222,7 @@ var parsePlusBuildExprTests = []struct { - func TestParsePlusBuildExpr(t *testing.T) { - for i, tt := range parsePlusBuildExprTests { - t.Run(fmt.Sprint(i), func(t *testing.T) { -- x := parsePlusBuildExpr(tt.in) -+ x, _ := parsePlusBuildExpr(tt.in) - if x.String() != tt.x.String() { - t.Errorf("parsePlusBuildExpr(%q):\nhave %v\nwant %v", tt.in, x, tt.x) - } -@@ -319,3 +319,66 @@ func TestPlusBuildLines(t *testing.T) { - }) - } - } -+ -+func TestSizeLimits(t *testing.T) { -+ for _, tc := range []struct { -+ name string -+ expr string -+ }{ -+ { -+ name: "go:build or limit", -+ expr: "//go:build " + strings.Repeat("a || ", maxSize+2), -+ }, -+ { -+ name: "go:build and limit", -+ expr: "//go:build " + strings.Repeat("a && ", maxSize+2), -+ }, -+ { -+ name: "go:build and depth limit", -+ expr: "//go:build " + strings.Repeat("(a &&", maxSize+2), -+ }, -+ { -+ name: "go:build or depth limit", -+ expr: "//go:build " + strings.Repeat("(a ||", maxSize+2), -+ }, -+ } { -+ t.Run(tc.name, func(t *testing.T) { -+ _, err := Parse(tc.expr) -+ if err == nil { -+ t.Error("expression did not trigger limit") -+ } else if syntaxErr, ok := err.(*SyntaxError); !ok || syntaxErr.Err != "build expression too large" { -+ if !ok { -+ t.Errorf("unexpected error: %v", err) -+ } else { -+ t.Errorf("unexpected syntax error: %s", syntaxErr.Err) -+ } -+ } -+ }) -+ } -+} -+ -+func TestPlusSizeLimits(t *testing.T) { -+ maxOldSize := 100 -+ for _, tc := range []struct { -+ name string -+ expr string -+ }{ -+ { -+ name: "+build or limit", -+ expr: "// +build " + strings.Repeat("a ", maxOldSize+2), -+ }, -+ { -+ name: "+build and limit", -+ expr: "// +build " + strings.Repeat("a,", maxOldSize+2), -+ }, -+ } { -+ t.Run(tc.name, func(t *testing.T) { -+ _, err := Parse(tc.expr) -+ if err == nil { -+ t.Error("expression did not trigger limit") -+ } else if err != errComplex { -+ t.Errorf("unexpected error: got %q, want %q", err, errComplex) -+ } -+ }) -+ } -+} --- -2.27.0 - diff --git a/backport-0024-release-branch.go1.21-runtime-add-the-disablethp-GOD.patch b/backport-0024-release-branch.go1.21-runtime-add-the-disablethp-GOD.patch deleted file mode 100644 index b3cbcc3fd81f171157084db518ce3c1ddc8e9c83..0000000000000000000000000000000000000000 --- a/backport-0024-release-branch.go1.21-runtime-add-the-disablethp-GOD.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 8440c7cdaf2aa9e52fc63c731564e98fbcdbb806 Mon Sep 17 00:00:00 2001 -From: Michael Anthony Knyszek -Date: Tue, 5 Dec 2023 17:31:34 +0000 -Subject: [PATCH 08/20] [release-branch.go1.21] runtime: add the disablethp - GODEBUG setting - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/547475 - -Go 1.21.1 and Go 1.22 have ceased working around an issue with Linux -kernel defaults for transparent huge pages that can result in excessive -memory overheads. (https://bugzilla.kernel.org/show_bug.cgi?id=93111) - -Many Linux distributions disable huge pages altogether these days, so -this problem isn't quite as far-reaching as it used to be. Also, the -problem only affects Go programs with very particular memory usage -patterns. - -That being said, because the runtime used to actively deal with this -problem (but with some unpredictable behavior), it's preventing users -that don't have a lot of control over their execution environment from -upgrading to Go beyond Go 1.20. - -This change adds a GODEBUG to smooth over the transition. The GODEBUG -setting disables transparent huge pages for all heap memory on Linux, -which is much more predictable than restoring the old behavior. - -For #64332. -Fixes #64561. - -Change-Id: I73b1894337f0f0b1a5a17b90da1221e118e0b145 -Reviewed-on: https://go-review.googlesource.com/c/go/+/547475 -Reviewed-by: Michael Pratt -Auto-Submit: Michael Knyszek -LUCI-TryBot-Result: Go LUCI -(cherry picked from commit c915215af65897cc9cffed75630cbfbc6b2462cc) -Reviewed-on: https://go-review.googlesource.com/c/go/+/547636 -Reviewed-by: Mauri de Souza Meneguzzo -TryBot-Bypass: Michael Knyszek -Auto-Submit: Matthew Dempsky ---- - doc/godebug.md | 13 +++++++++++++ - src/runtime/extern.go | 7 +++++++ - src/runtime/mem_linux.go | 8 ++++++++ - src/runtime/runtime1.go | 2 ++ - 4 files changed, 30 insertions(+) - -diff --git a/doc/godebug.md b/doc/godebug.md -index d26555503e05..4b71e4d46985 100644 ---- a/doc/godebug.md -+++ b/doc/godebug.md -@@ -134,6 +134,19 @@ The default is tlsmaxrsasize=8192, limiting RSA to 8192-bit keys. To avoid - denial of service attacks, this setting and default was backported to Go - 1.19.13, Go 1.20.8, and Go 1.21.1. - -+Go 1.22 changed how the runtime interacts with transparent huge pages on Linux. -+In particular, a common default Linux kernel configuration can result in -+significant memory overheads, and Go 1.22 no longer works around this default. -+To work around this issue without adjusting kernel settings, transparent huge -+pages can be disabled for Go memory with the -+[`disablethp` setting](/pkg/runtime#hdr-Environment_Variable). -+This behavior was backported to Go 1.21.1, but the setting is only available -+starting with Go 1.21.6. -+This setting may be removed in a future release, and users impacted by this issue -+should adjust their Linux configuration according to the recommendations in the -+[GC guide](/doc/gc-guide#Linux_transparent_huge_pages), or switch to a Linux -+distribution that disables transparent huge pages altogether. -+ - ### Go 1.21 - - Go 1.21 made it a run-time error to call `panic` with a nil interface value, -diff --git a/src/runtime/extern.go b/src/runtime/extern.go -index 26dcf0bd52b2..de4a0ca2dade 100644 ---- a/src/runtime/extern.go -+++ b/src/runtime/extern.go -@@ -55,6 +55,13 @@ It is a comma-separated list of name=val pairs setting these named variables: - cgocheck mode can be enabled using GOEXPERIMENT (which - requires a rebuild), see https://pkg.go.dev/internal/goexperiment for details. - -+ disablethp: setting disablethp=1 on Linux disables transparent huge pages for the heap. -+ It has no effect on other platforms. disablethp is meant for compatibility with versions -+ of Go before 1.21, which stopped working around a Linux kernel default that can result -+ in significant memory overuse. See https://go.dev/issue/64332. This setting will be -+ removed in a future release, so operators should tweak their Linux configuration to suit -+ their needs before then. See https://go.dev/doc/gc-guide#Linux_transparent_huge_pages. -+ - dontfreezetheworld: by default, the start of a fatal panic or throw - "freezes the world", preempting all threads to stop all running - goroutines, which makes it possible to traceback all goroutines, and -diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go -index c9823d301133..d63c38c209d8 100644 ---- a/src/runtime/mem_linux.go -+++ b/src/runtime/mem_linux.go -@@ -170,4 +170,12 @@ func sysMapOS(v unsafe.Pointer, n uintptr) { - print("runtime: mmap(", v, ", ", n, ") returned ", p, ", ", err, "\n") - throw("runtime: cannot map pages in arena address space") - } -+ -+ // Disable huge pages if the GODEBUG for it is set. -+ // -+ // Note that there are a few sysHugePage calls that can override this, but -+ // they're all for GC metadata. -+ if debug.disablethp != 0 { -+ sysNoHugePageOS(v, n) -+ } - } -diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go -index 92a7e021ee23..7174c63af354 100644 ---- a/src/runtime/runtime1.go -+++ b/src/runtime/runtime1.go -@@ -309,6 +309,7 @@ type dbgVar struct { - var debug struct { - cgocheck int32 - clobberfree int32 -+ disablethp int32 - dontfreezetheworld int32 - efence int32 - gccheckmark int32 -@@ -342,6 +343,7 @@ var dbgvars = []*dbgVar{ - {name: "allocfreetrace", value: &debug.allocfreetrace}, - {name: "clobberfree", value: &debug.clobberfree}, - {name: "cgocheck", value: &debug.cgocheck}, -+ {name: "disablethp", value: &debug.disablethp}, - {name: "dontfreezetheworld", value: &debug.dontfreezetheworld}, - {name: "efence", value: &debug.efence}, - {name: "gccheckmark", value: &debug.gccheckmark}, --- -2.33.0 - diff --git a/backport-0025-release-branch.go1.21-runtime-put-ReadMemStats-debug.patch b/backport-0025-release-branch.go1.21-runtime-put-ReadMemStats-debug.patch deleted file mode 100644 index 1c9e5b43c994568063676f7d32dbc4eb3999b723..0000000000000000000000000000000000000000 --- a/backport-0025-release-branch.go1.21-runtime-put-ReadMemStats-debug.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 398023279e53f4e847d598afa41c2d3d163baa94 Mon Sep 17 00:00:00 2001 -From: Michael Anthony Knyszek -Date: Mon, 27 Nov 2023 22:27:32 +0000 -Subject: [PATCH 09/20] [release-branch.go1.21] runtime: put ReadMemStats debug - assertions behind a double-check mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/545277 -ReadMemStats has a few assertions it makes about the consistency of the -stats it's about to produce. Specifically, how those stats line up with -runtime-internal stats. These checks are generally useful, but crashing -just because some stats are wrong is a heavy price to pay. - -For a long time this wasn't a problem, but very recently it became a -real problem. It turns out that there's real benign skew that can happen -wherein sysmon (which doesn't synchronize with a STW) generates a trace -event when tracing is enabled, and may mutate some stats while -ReadMemStats is running its checks. - -Fix this by synchronizing with both sysmon and the tracer. This is a bit -heavy-handed, but better that than false positives. - -Also, put the checks behind a debug mode. We want to reduce the risk of -backporting this change, and again, it's not great to crash just because -user-facing stats are off. Still, enable this debug mode during the -runtime tests so we don't lose quite as much coverage from disabling -these checks by default. - -For #64401. -Fixes #64410. - -Change-Id: I9adb3e5c7161d207648d07373a11da8a5f0fda9a -Reviewed-on: https://go-review.googlesource.com/c/go/+/545277 -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Michael Pratt -Reviewed-by: Felix Geisendörfer -(cherry picked from commit b2efd1de97402ec4b8fb4e9e0ec29c8e49e8e200) -Reviewed-on: https://go-review.googlesource.com/c/go/+/545557 -Auto-Submit: Matthew Dempsky -TryBot-Bypass: Matthew Dempsky ---- - src/runtime/export_test.go | 2 + - src/runtime/gc_test.go | 5 ++ - src/runtime/mstats.go | 114 +++++++++++++++++++++---------------- - 3 files changed, 71 insertions(+), 50 deletions(-) - -diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go -index f7ce5033f587..a740993c5878 100644 ---- a/src/runtime/export_test.go -+++ b/src/runtime/export_test.go -@@ -436,6 +436,8 @@ func ReadMetricsSlow(memStats *MemStats, samplesp unsafe.Pointer, len, cap int) - startTheWorld() - } - -+var DoubleCheckReadMemStats = &doubleCheckReadMemStats -+ - // ReadMemStatsSlow returns both the runtime-computed MemStats and - // MemStats accumulated by scanning the heap. - func ReadMemStatsSlow() (base, slow MemStats) { -diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go -index bd01e3610300..9302ea32c3f1 100644 ---- a/src/runtime/gc_test.go -+++ b/src/runtime/gc_test.go -@@ -570,6 +570,11 @@ func TestPageAccounting(t *testing.T) { - } - } - -+func init() { -+ // Enable ReadMemStats' double-check mode. -+ *runtime.DoubleCheckReadMemStats = true -+} -+ - func TestReadMemStats(t *testing.T) { - base, slow := runtime.ReadMemStatsSlow() - if base != slow { -diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go -index 9cdc56513719..308bed67d7b3 100644 ---- a/src/runtime/mstats.go -+++ b/src/runtime/mstats.go -@@ -367,6 +367,11 @@ func ReadMemStats(m *MemStats) { - startTheWorld() - } - -+// doubleCheckReadMemStats controls a double-check mode for ReadMemStats that -+// ensures consistency between the values that ReadMemStats is using and the -+// runtime-internal stats. -+var doubleCheckReadMemStats = false -+ - // readmemstats_m populates stats for internal runtime values. - // - // The world must be stopped. -@@ -441,56 +446,65 @@ func readmemstats_m(stats *MemStats) { - - heapGoal := gcController.heapGoal() - -- // The world is stopped, so the consistent stats (after aggregation) -- // should be identical to some combination of memstats. In particular: -- // -- // * memstats.heapInUse == inHeap -- // * memstats.heapReleased == released -- // * memstats.heapInUse + memstats.heapFree == committed - inStacks - inWorkBufs - inPtrScalarBits -- // * memstats.totalAlloc == totalAlloc -- // * memstats.totalFree == totalFree -- // -- // Check if that's actually true. -- // -- // TODO(mknyszek): Maybe don't throw here. It would be bad if a -- // bug in otherwise benign accounting caused the whole application -- // to crash. -- if gcController.heapInUse.load() != uint64(consStats.inHeap) { -- print("runtime: heapInUse=", gcController.heapInUse.load(), "\n") -- print("runtime: consistent value=", consStats.inHeap, "\n") -- throw("heapInUse and consistent stats are not equal") -- } -- if gcController.heapReleased.load() != uint64(consStats.released) { -- print("runtime: heapReleased=", gcController.heapReleased.load(), "\n") -- print("runtime: consistent value=", consStats.released, "\n") -- throw("heapReleased and consistent stats are not equal") -- } -- heapRetained := gcController.heapInUse.load() + gcController.heapFree.load() -- consRetained := uint64(consStats.committed - consStats.inStacks - consStats.inWorkBufs - consStats.inPtrScalarBits) -- if heapRetained != consRetained { -- print("runtime: global value=", heapRetained, "\n") -- print("runtime: consistent value=", consRetained, "\n") -- throw("measures of the retained heap are not equal") -- } -- if gcController.totalAlloc.Load() != totalAlloc { -- print("runtime: totalAlloc=", gcController.totalAlloc.Load(), "\n") -- print("runtime: consistent value=", totalAlloc, "\n") -- throw("totalAlloc and consistent stats are not equal") -- } -- if gcController.totalFree.Load() != totalFree { -- print("runtime: totalFree=", gcController.totalFree.Load(), "\n") -- print("runtime: consistent value=", totalFree, "\n") -- throw("totalFree and consistent stats are not equal") -- } -- // Also check that mappedReady lines up with totalMapped - released. -- // This isn't really the same type of "make sure consistent stats line up" situation, -- // but this is an opportune time to check. -- if gcController.mappedReady.Load() != totalMapped-uint64(consStats.released) { -- print("runtime: mappedReady=", gcController.mappedReady.Load(), "\n") -- print("runtime: totalMapped=", totalMapped, "\n") -- print("runtime: released=", uint64(consStats.released), "\n") -- print("runtime: totalMapped-released=", totalMapped-uint64(consStats.released), "\n") -- throw("mappedReady and other memstats are not equal") -+ if doubleCheckReadMemStats { -+ // Only check this if we're debugging. It would be bad to crash an application -+ // just because the debugging stats are wrong. We mostly rely on tests to catch -+ // these issues, and we enable the double check mode for tests. -+ // -+ // The world is stopped, so the consistent stats (after aggregation) -+ // should be identical to some combination of memstats. In particular: -+ // -+ // * memstats.heapInUse == inHeap -+ // * memstats.heapReleased == released -+ // * memstats.heapInUse + memstats.heapFree == committed - inStacks - inWorkBufs - inPtrScalarBits -+ // * memstats.totalAlloc == totalAlloc -+ // * memstats.totalFree == totalFree -+ // -+ // Check if that's actually true. -+ // -+ // Prevent sysmon and the tracer from skewing the stats since they can -+ // act without synchronizing with a STW. See #64401. -+ lock(&sched.sysmonlock) -+ lock(&trace.lock) -+ if gcController.heapInUse.load() != uint64(consStats.inHeap) { -+ print("runtime: heapInUse=", gcController.heapInUse.load(), "\n") -+ print("runtime: consistent value=", consStats.inHeap, "\n") -+ throw("heapInUse and consistent stats are not equal") -+ } -+ if gcController.heapReleased.load() != uint64(consStats.released) { -+ print("runtime: heapReleased=", gcController.heapReleased.load(), "\n") -+ print("runtime: consistent value=", consStats.released, "\n") -+ throw("heapReleased and consistent stats are not equal") -+ } -+ heapRetained := gcController.heapInUse.load() + gcController.heapFree.load() -+ consRetained := uint64(consStats.committed - consStats.inStacks - consStats.inWorkBufs - consStats.inPtrScalarBits) -+ if heapRetained != consRetained { -+ print("runtime: global value=", heapRetained, "\n") -+ print("runtime: consistent value=", consRetained, "\n") -+ throw("measures of the retained heap are not equal") -+ } -+ if gcController.totalAlloc.Load() != totalAlloc { -+ print("runtime: totalAlloc=", gcController.totalAlloc.Load(), "\n") -+ print("runtime: consistent value=", totalAlloc, "\n") -+ throw("totalAlloc and consistent stats are not equal") -+ } -+ if gcController.totalFree.Load() != totalFree { -+ print("runtime: totalFree=", gcController.totalFree.Load(), "\n") -+ print("runtime: consistent value=", totalFree, "\n") -+ throw("totalFree and consistent stats are not equal") -+ } -+ // Also check that mappedReady lines up with totalMapped - released. -+ // This isn't really the same type of "make sure consistent stats line up" situation, -+ // but this is an opportune time to check. -+ if gcController.mappedReady.Load() != totalMapped-uint64(consStats.released) { -+ print("runtime: mappedReady=", gcController.mappedReady.Load(), "\n") -+ print("runtime: totalMapped=", totalMapped, "\n") -+ print("runtime: released=", uint64(consStats.released), "\n") -+ print("runtime: totalMapped-released=", totalMapped-uint64(consStats.released), "\n") -+ throw("mappedReady and other memstats are not equal") -+ } -+ unlock(&trace.lock) -+ unlock(&sched.sysmonlock) - } - - // We've calculated all the values we need. Now, populate stats. --- -2.33.0 - diff --git a/backport-0026-release-branch.go1.21-runtime-add-race-annotations-i.patch b/backport-0026-release-branch.go1.21-runtime-add-race-annotations-i.patch deleted file mode 100644 index 754a4d4d7056ac9d4ecc2602655430fb9c66fb9a..0000000000000000000000000000000000000000 --- a/backport-0026-release-branch.go1.21-runtime-add-race-annotations-i.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 3a0f84cabae57c185cd18564e6371ce2b50181aa Mon Sep 17 00:00:00 2001 -From: David Chase -Date: Thu, 14 Dec 2023 14:20:12 -0500 -Subject: [PATCH 10/20] [release-branch.go1.21] runtime: add race annotations - in IncNonDefault - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/549796 - -Also use CompareAndSwap to make the code actually less racy. - -Added a test which will be meaningful when run under the race -detector (tested it -race with broken fix in runtime, it failed). - -This backport incorporates the correction in CL 551856, -using racereleasemerge instead of racerelease. - -Fixes #64757 - -Change-Id: I5972e08901d1adc8ba74858edad7eba91be1b0ce -Reviewed-on: https://go-review.googlesource.com/c/go/+/549796 -Run-TryBot: David Chase -Reviewed-by: Mauri de Souza Meneguzzo -Reviewed-by: Cherry Mui -TryBot-Result: Gopher Robot -(cherry picked from commit 3313bbb4055f38f53cd43c6c5782a229f445f230) -Reviewed-on: https://go-review.googlesource.com/c/go/+/550236 -Auto-Submit: Matthew Dempsky -TryBot-Bypass: Matthew Dempsky -Reviewed-by: Michael Knyszek -Reviewed-by: Matthew Dempsky ---- - src/internal/godebug/godebug_test.go | 31 ++++++++++++++++++++++++++++ - src/runtime/runtime.go | 13 ++++++++---- - 2 files changed, 40 insertions(+), 4 deletions(-) - -diff --git a/src/internal/godebug/godebug_test.go b/src/internal/godebug/godebug_test.go -index 8e46283adab3..65dd256e8e7d 100644 ---- a/src/internal/godebug/godebug_test.go -+++ b/src/internal/godebug/godebug_test.go -@@ -7,6 +7,7 @@ package godebug_test - import ( - "fmt" - . "internal/godebug" -+ "internal/race" - "internal/testenv" - "os" - "os/exec" -@@ -70,6 +71,36 @@ func TestMetrics(t *testing.T) { - } - } - -+// TestPanicNilRace checks for a race in the runtime caused by use of runtime -+// atomics (not visible to usual race detection) to install the counter for -+// non-default panic(nil) semantics. For #64649. -+func TestPanicNilRace(t *testing.T) { -+ if !race.Enabled { -+ t.Skip("Skipping test intended for use with -race.") -+ } -+ if os.Getenv("GODEBUG") != "panicnil=1" { -+ cmd := testenv.CleanCmdEnv(testenv.Command(t, os.Args[0], "-test.run=^TestPanicNilRace$", "-test.v", "-test.parallel=2", "-test.count=1")) -+ cmd.Env = append(cmd.Env, "GODEBUG=panicnil=1") -+ out, err := cmd.CombinedOutput() -+ t.Logf("output:\n%s", out) -+ -+ if err != nil { -+ t.Errorf("Was not expecting a crash") -+ } -+ return -+ } -+ -+ test := func(t *testing.T) { -+ t.Parallel() -+ defer func() { -+ recover() -+ }() -+ panic(nil) -+ } -+ t.Run("One", test) -+ t.Run("Two", test) -+} -+ - func TestCmdBisect(t *testing.T) { - testenv.MustHaveGoBuild(t) - out, err := exec.Command("go", "run", "cmd/vendor/golang.org/x/tools/cmd/bisect", "GODEBUG=buggy=1#PATTERN", os.Args[0], "-test.run=BisectTestCase").CombinedOutput() -diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go -index 0822d0e8054e..15119cf5dfc7 100644 ---- a/src/runtime/runtime.go -+++ b/src/runtime/runtime.go -@@ -101,12 +101,17 @@ func (g *godebugInc) IncNonDefault() { - if newInc == nil { - return - } -- // If other goroutines are racing here, no big deal. One will win, -- // and all the inc functions will be using the same underlying -- // *godebug.Setting. - inc = new(func()) - *inc = (*newInc)(g.name) -- g.inc.Store(inc) -+ if raceenabled { -+ racereleasemerge(unsafe.Pointer(&g.inc)) -+ } -+ if !g.inc.CompareAndSwap(nil, inc) { -+ inc = g.inc.Load() -+ } -+ } -+ if raceenabled { -+ raceacquire(unsafe.Pointer(&g.inc)) - } - (*inc)() - } --- -2.33.0 - diff --git a/backport-0027-crypto-tls-fix-Config.Time-in-tests-using-expired-ce.patch b/backport-0027-crypto-tls-fix-Config.Time-in-tests-using-expired-ce.patch deleted file mode 100644 index 57981af6809a195b9adcc0c0376fb0d2b5c88471..0000000000000000000000000000000000000000 --- a/backport-0027-crypto-tls-fix-Config.Time-in-tests-using-expired-ce.patch +++ /dev/null @@ -1,256 +0,0 @@ -From d1d93129506c78cc8ee25644384286822d93c81a Mon Sep 17 00:00:00 2001 -From: Filippo Valsorda -Date: Thu, 02 Jan 2025 01:34:40 +0100 -Subject: [PATCH] crypto/tls: fix Config.Time in tests using expired certificates - -Fixes #71077 - -Edited-by(backport to go1.21): Wang Shuo - -Change-Id: I6a6a465685f3bd50a5bb35a160f87b59b74fa6af -Reviewed-on: https://go-review.googlesource.com/c/go/+/639655 -Auto-Submit: Ian Lance Taylor -Reviewed-by: Damien Neil -LUCI-TryBot-Result: Go LUCI -Auto-Submit: Filippo Valsorda -Auto-Submit: Damien Neil -Reviewed-by: Joel Sing -Reviewed-by: Ian Lance Taylor ---- - src/crypto/tls/handshake_client_test.go | 30 +++++++++++++++---------- - src/crypto/tls/handshake_server_test.go | 2 ++ - src/crypto/tls/handshake_test.go | 5 +++++ - src/crypto/tls/tls_test.go | 6 ++--- - 4 files changed, 27 insertions(+), 16 deletions(-) - -diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go -index a2052ce..7f5cb67 100644 ---- a/src/crypto/tls/handshake_client_test.go -+++ b/src/crypto/tls/handshake_client_test.go -@@ -881,6 +881,7 @@ func testResumption(t *testing.T, version uint16) { - MaxVersion: version, - CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, - Certificates: testConfig.Certificates, -+ Time: testTime, - } - - issuer, err := x509.ParseCertificate(testRSACertificateIssuer) -@@ -897,6 +898,7 @@ func testResumption(t *testing.T, version uint16) { - ClientSessionCache: NewLRUClientSessionCache(32), - RootCAs: rootCAs, - ServerName: "example.golang", -+ Time: testTime, - } - - testResumeState := func(test string, didResume bool) { -@@ -943,7 +945,7 @@ func testResumption(t *testing.T, version uint16) { - - // An old session ticket is replaced with a ticket encrypted with a fresh key. - ticket = getTicket() -- serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } -+ serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) } - testResumeState("ResumeWithOldTicket", true) - if bytes.Equal(ticket, getTicket()) { - t.Fatal("old first ticket matches the fresh one") -@@ -951,13 +953,13 @@ func testResumption(t *testing.T, version uint16) { - - // Once the session master secret is expired, a full handshake should occur. - ticket = getTicket() -- serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } -+ serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + time.Minute) } - testResumeState("ResumeWithExpiredTicket", false) - if bytes.Equal(ticket, getTicket()) { - t.Fatal("expired first ticket matches the fresh one") - } - -- serverConfig.Time = func() time.Time { return time.Now() } // reset the time back -+ serverConfig.Time = testTime // reset the time back - key1 := randomKey() - serverConfig.SetSessionTicketKeys([][32]byte{key1}) - -@@ -974,11 +976,11 @@ func testResumption(t *testing.T, version uint16) { - testResumeState("KeyChangeFinish", true) - - // Age the session ticket a bit, but not yet expired. -- serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } -+ serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) } - testResumeState("OldSessionTicket", true) - ticket = getTicket() - // Expire the session ticket, which would force a full handshake. -- serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } -+ serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + 2*time.Minute) } - testResumeState("ExpiredSessionTicket", false) - if bytes.Equal(ticket, getTicket()) { - t.Fatal("new ticket wasn't provided after old ticket expired") -@@ -986,7 +988,7 @@ func testResumption(t *testing.T, version uint16) { - - // Age the session ticket a bit at a time, but don't expire it. - d := 0 * time.Hour -- serverConfig.Time = func() time.Time { return time.Now().Add(d) } -+ serverConfig.Time = func() time.Time { return testTime().Add(d) } - deleteTicket() - testResumeState("GetFreshSessionTicket", false) - for i := 0; i < 13; i++ { -@@ -997,7 +999,7 @@ func testResumption(t *testing.T, version uint16) { - // handshake occurs for TLS 1.2. Resumption should still occur for - // TLS 1.3 since the client should be using a fresh ticket sent over - // by the server. -- d += 12 * time.Hour -+ d += 12*time.Hour + time.Minute - if version == VersionTLS13 { - testResumeState("ExpiredSessionTicket", true) - } else { -@@ -1013,6 +1015,7 @@ func testResumption(t *testing.T, version uint16) { - MaxVersion: version, - CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, - Certificates: testConfig.Certificates, -+ Time: testTime, - } - serverConfig.SetSessionTicketKeys([][32]byte{key2}) - -@@ -1038,6 +1041,7 @@ func testResumption(t *testing.T, version uint16) { - CurvePreferences: []CurveID{CurveP521, CurveP384, CurveP256}, - MaxVersion: version, - Certificates: testConfig.Certificates, -+ Time: testTime, - } - testResumeState("InitialHandshake", false) - testResumeState("WithHelloRetryRequest", true) -@@ -1047,6 +1051,7 @@ func testResumption(t *testing.T, version uint16) { - MaxVersion: version, - CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, - Certificates: testConfig.Certificates, -+ Time: testTime, - } - } - -@@ -1761,6 +1766,7 @@ func testVerifyConnection(t *testing.T, version uint16) { - serverConfig := &Config{ - MaxVersion: version, - Certificates: []Certificate{testConfig.Certificates[0]}, -+ Time: testTime, - ClientCAs: rootCAs, - NextProtos: []string{"protocol1"}, - } -@@ -1774,6 +1780,7 @@ func testVerifyConnection(t *testing.T, version uint16) { - RootCAs: rootCAs, - ServerName: "example.golang", - Certificates: []Certificate{testConfig.Certificates[0]}, -+ Time: testTime, - NextProtos: []string{"protocol1"}, - } - test.configureClient(clientConfig, &clientCalled) -@@ -1816,8 +1823,6 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { - rootCAs := x509.NewCertPool() - rootCAs.AddCert(issuer) - -- now := func() time.Time { return time.Unix(1476984729, 0) } -- - sentinelErr := errors.New("TestVerifyPeerCertificate") - - verifyPeerCertificateCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { -@@ -2063,7 +2068,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { - config.ServerName = "example.golang" - config.ClientAuth = RequireAndVerifyClientCert - config.ClientCAs = rootCAs -- config.Time = now -+ config.Time = testTime - config.MaxVersion = version - config.Certificates = make([]Certificate, 1) - config.Certificates[0].Certificate = [][]byte{testRSACertificate} -@@ -2080,7 +2085,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { - config := testConfig.Clone() - config.ServerName = "example.golang" - config.RootCAs = rootCAs -- config.Time = now -+ config.Time = testTime - config.MaxVersion = version - test.configureClient(config, &clientCalled) - clientErr := Client(c, config).Handshake() -@@ -2393,7 +2398,7 @@ func testGetClientCertificate(t *testing.T, version uint16) { - serverConfig.RootCAs = x509.NewCertPool() - serverConfig.RootCAs.AddCert(issuer) - serverConfig.ClientCAs = serverConfig.RootCAs -- serverConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } -+ serverConfig.Time = testTime - serverConfig.MaxVersion = version - - clientConfig := testConfig.Clone() -@@ -2564,6 +2569,7 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { - ClientSessionCache: NewLRUClientSessionCache(32), - ServerName: "example.golang", - RootCAs: roots, -+ Time: testTime, - } - serverConfig := testConfig.Clone() - serverConfig.MaxVersion = ver -diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go -index 04abdcc..9f0b1d3 100644 ---- a/src/crypto/tls/handshake_server_test.go -+++ b/src/crypto/tls/handshake_server_test.go -@@ -481,6 +481,7 @@ func testCrossVersionResume(t *testing.T, version uint16) { - serverConfig := &Config{ - CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, - Certificates: testConfig.Certificates, -+ Time: testTime, - } - clientConfig := &Config{ - CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, -@@ -488,6 +489,7 @@ func testCrossVersionResume(t *testing.T, version uint16) { - ClientSessionCache: NewLRUClientSessionCache(1), - ServerName: "servername", - MinVersion: VersionTLS10, -+ Time: testTime, - } - - // Establish a session at TLS 1.1. -diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go -index bacc8b7..27ab19e 100644 ---- a/src/crypto/tls/handshake_test.go -+++ b/src/crypto/tls/handshake_test.go -@@ -429,6 +429,11 @@ func fromHex(s string) []byte { - return b - } - -+// testTime is 2016-10-20T17:32:09.000Z, which is within the validity period of -+// [testRSACertificate], [testRSACertificateIssuer], [testRSA2048Certificate], -+// [testRSA2048CertificateIssuer], and [testECDSACertificate]. -+var testTime = func() time.Time { return time.Unix(1476984729, 0) } -+ - var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7") - - var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76") -diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go -index c3f16c7..83100a7 100644 ---- a/src/crypto/tls/tls_test.go -+++ b/src/crypto/tls/tls_test.go -@@ -1098,8 +1098,6 @@ func TestConnectionState(t *testing.T) { - rootCAs := x509.NewCertPool() - rootCAs.AddCert(issuer) - -- now := func() time.Time { return time.Unix(1476984729, 0) } -- - const alpnProtocol = "golang" - const serverName = "example.golang" - var scts = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} -@@ -1115,7 +1113,7 @@ func TestConnectionState(t *testing.T) { - } - t.Run(name, func(t *testing.T) { - config := &Config{ -- Time: now, -+ Time: testTime, - Rand: zeroSource{}, - Certificates: make([]Certificate, 1), - MaxVersion: v, -@@ -1726,7 +1724,7 @@ func testVerifyCertificates(t *testing.T, version uint16) { - var serverVerifyPeerCertificates, clientVerifyPeerCertificates bool - - clientConfig := testConfig.Clone() -- clientConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } -+ clientConfig.Time = testTime - clientConfig.MaxVersion = version - clientConfig.MinVersion = version - clientConfig.RootCAs = rootCAs --- -2.43.0 - diff --git a/backport-0028-release-branch.go1.21-runtime-allow-update-of-system.patch b/backport-0028-release-branch.go1.21-runtime-allow-update-of-system.patch deleted file mode 100644 index 42169c1fb10c3318e01f035a9dc298a1f7d08bdb..0000000000000000000000000000000000000000 --- a/backport-0028-release-branch.go1.21-runtime-allow-update-of-system.patch +++ /dev/null @@ -1,392 +0,0 @@ -From 66f3c19e6a577682595b62d428df9e63430ad1be Mon Sep 17 00:00:00 2001 -From: Michael Pratt -Date: Mon, 4 Sep 2023 09:55:01 -0400 -Subject: [PATCH 11/20] [release-branch.go1.21] runtime: allow update of system - stack bounds on callback from C thread - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/527715 - -[This cherry-pick combines CL 527715, CL 527775, CL 527797, and -CL 529216.] - -[This is a redo of CL 525455 with the test fixed on darwin by defining -_XOPEN_SOURCE, and disabled with android, musl, and openbsd, which do -not provide getcontext.] - -Since CL 495855, Ms are cached for C threads calling into Go, including -the stack bounds of the system stack. - -Some C libraries (e.g., coroutine libraries) do manual stack management -and may change stacks between calls to Go on the same thread. - -Changing the stack if there is more Go up the stack would be -problematic. But if the calls are completely independent there is no -particular reason for Go to care about the changing stack boundary. - -Thus, this CL allows the stack bounds to change in such cases. The -primary downside here (besides additional complexity) is that normal -systems that do not manipulate the stack may not notice unintentional -stack corruption as quickly as before. - -Note that callbackUpdateSystemStack is written to be usable for the -initial setup in needm as well as updating the stack in cgocallbackg. - -For #62440. -For #62130. -For #63209. - -Change-Id: I0fe0134f865932bbaff1fc0da377c35c013bd768 -Reviewed-on: https://go-review.googlesource.com/c/go/+/527715 -Run-TryBot: Michael Pratt -TryBot-Result: Gopher Robot -Auto-Submit: Michael Pratt -Reviewed-by: Cherry Mui -(cherry picked from commit 4f9fe6d50965020053ab80bf115f08070ce97f33) -(cherry picked from commit e8ba0579e2913f96c65b96e0696d64ff5f1599c5) -(cherry picked from commit a843991fdd079c931d4e98c0a17c9ac6dc254fe8) -(cherry picked from commit d110d7c42dd8025465153e4008ba807f1e69b359) -Reviewed-on: https://go-review.googlesource.com/c/go/+/530480 -Auto-Submit: Dmitri Shuralyov -TryBot-Bypass: Michael Pratt ---- - src/runtime/cgocall.go | 70 ++++++++++++ - src/runtime/crash_cgo_test.go | 17 +++ - src/runtime/proc.go | 33 ++---- - .../testdata/testprogcgo/stackswitch.c | 106 ++++++++++++++++++ - .../testdata/testprogcgo/stackswitch.go | 43 +++++++ - 5 files changed, 245 insertions(+), 24 deletions(-) - create mode 100644 src/runtime/testdata/testprogcgo/stackswitch.c - create mode 100644 src/runtime/testdata/testprogcgo/stackswitch.go - -diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go -index 1da7249abc5a..d226c2e907fd 100644 ---- a/src/runtime/cgocall.go -+++ b/src/runtime/cgocall.go -@@ -206,6 +206,73 @@ func cgocall(fn, arg unsafe.Pointer) int32 { - return errno - } - -+// Set or reset the system stack bounds for a callback on sp. -+// -+// Must be nosplit because it is called by needm prior to fully initializing -+// the M. -+// -+//go:nosplit -+func callbackUpdateSystemStack(mp *m, sp uintptr, signal bool) { -+ g0 := mp.g0 -+ if sp > g0.stack.lo && sp <= g0.stack.hi { -+ // Stack already in bounds, nothing to do. -+ return -+ } -+ -+ if mp.ncgo > 0 { -+ // ncgo > 0 indicates that this M was in Go further up the stack -+ // (it called C and is now receiving a callback). It is not -+ // safe for the C call to change the stack out from under us. -+ -+ // Note that this case isn't possible for signal == true, as -+ // that is always passing a new M from needm. -+ -+ // Stack is bogus, but reset the bounds anyway so we can print. -+ hi := g0.stack.hi -+ lo := g0.stack.lo -+ g0.stack.hi = sp + 1024 -+ g0.stack.lo = sp - 32*1024 -+ g0.stackguard0 = g0.stack.lo + stackGuard -+ -+ print("M ", mp.id, " procid ", mp.procid, " runtime: cgocallback with sp=", hex(sp), " out of bounds [", hex(lo), ", ", hex(hi), "]") -+ print("\n") -+ exit(2) -+ } -+ -+ // This M does not have Go further up the stack. However, it may have -+ // previously called into Go, initializing the stack bounds. Between -+ // that call returning and now the stack may have changed (perhaps the -+ // C thread is running a coroutine library). We need to update the -+ // stack bounds for this case. -+ // -+ // Set the stack bounds to match the current stack. If we don't -+ // actually know how big the stack is, like we don't know how big any -+ // scheduling stack is, but we assume there's at least 32 kB. If we -+ // can get a more accurate stack bound from pthread, use that, provided -+ // it actually contains SP.. -+ g0.stack.hi = sp + 1024 -+ g0.stack.lo = sp - 32*1024 -+ if !signal && _cgo_getstackbound != nil { -+ // Don't adjust if called from the signal handler. -+ // We are on the signal stack, not the pthread stack. -+ // (We could get the stack bounds from sigaltstack, but -+ // we're getting out of the signal handler very soon -+ // anyway. Not worth it.) -+ var bounds [2]uintptr -+ asmcgocall(_cgo_getstackbound, unsafe.Pointer(&bounds)) -+ // getstackbound is an unsupported no-op on Windows. -+ // -+ // Don't use these bounds if they don't contain SP. Perhaps we -+ // were called by something not using the standard thread -+ // stack. -+ if bounds[0] != 0 && sp > bounds[0] && sp <= bounds[1] { -+ g0.stack.lo = bounds[0] -+ g0.stack.hi = bounds[1] -+ } -+ } -+ g0.stackguard0 = g0.stack.lo + stackGuard -+} -+ - // Call from C back to Go. fn must point to an ABIInternal Go entry-point. - // - //go:nosplit -@@ -216,6 +283,9 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) { - exit(2) - } - -+ sp := gp.m.g0.sched.sp // system sp saved by cgocallback. -+ callbackUpdateSystemStack(gp.m, sp, false) -+ - // The call from C is on gp.m's g0 stack, so we must ensure - // that we stay on that M. We have to do this before calling - // exitsyscall, since it would otherwise be free to move us to -diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go -index e1851808f319..424aedb4ef7e 100644 ---- a/src/runtime/crash_cgo_test.go -+++ b/src/runtime/crash_cgo_test.go -@@ -853,3 +853,20 @@ func TestEnsureBindM(t *testing.T) { - t.Errorf("expected %q, got %v", want, got) - } - } -+ -+func TestStackSwitchCallback(t *testing.T) { -+ t.Parallel() -+ switch runtime.GOOS { -+ case "windows", "plan9", "android", "ios", "openbsd": // no getcontext -+ t.Skipf("skipping test on %s", runtime.GOOS) -+ } -+ got := runTestProg(t, "testprogcgo", "StackSwitchCallback") -+ skip := "SKIP\n" -+ if got == skip { -+ t.Skip("skipping on musl/bionic libc") -+ } -+ want := "OK\n" -+ if got != want { -+ t.Errorf("expected %q, got %v", want, got) -+ } -+} -diff --git a/src/runtime/proc.go b/src/runtime/proc.go -index afb33c1e8b73..eaea523ab5c5 100644 ---- a/src/runtime/proc.go -+++ b/src/runtime/proc.go -@@ -2037,30 +2037,10 @@ func needm(signal bool) { - osSetupTLS(mp) - - // Install g (= m->g0) and set the stack bounds -- // to match the current stack. If we don't actually know -- // how big the stack is, like we don't know how big any -- // scheduling stack is, but we assume there's at least 32 kB. -- // If we can get a more accurate stack bound from pthread, -- // use that. -+ // to match the current stack. - setg(mp.g0) -- gp := getg() -- gp.stack.hi = getcallersp() + 1024 -- gp.stack.lo = getcallersp() - 32*1024 -- if !signal && _cgo_getstackbound != nil { -- // Don't adjust if called from the signal handler. -- // We are on the signal stack, not the pthread stack. -- // (We could get the stack bounds from sigaltstack, but -- // we're getting out of the signal handler very soon -- // anyway. Not worth it.) -- var bounds [2]uintptr -- asmcgocall(_cgo_getstackbound, unsafe.Pointer(&bounds)) -- // getstackbound is an unsupported no-op on Windows. -- if bounds[0] != 0 { -- gp.stack.lo = bounds[0] -- gp.stack.hi = bounds[1] -- } -- } -- gp.stackguard0 = gp.stack.lo + stackGuard -+ sp := getcallersp() -+ callbackUpdateSystemStack(mp, sp, signal) - - // Should mark we are already in Go now. - // Otherwise, we may call needm again when we get a signal, before cgocallbackg1, -@@ -2177,9 +2157,14 @@ func oneNewExtraM() { - // So that the destructor would invoke dropm while the non-Go thread is exiting. - // This is much faster since it avoids expensive signal-related syscalls. - // --// NOTE: this always runs without a P, so, nowritebarrierrec required. -+// This always runs without a P, so //go:nowritebarrierrec is required. -+// -+// This may run with a different stack than was recorded in g0 (there is no -+// call to callbackUpdateSystemStack prior to dropm), so this must be -+// //go:nosplit to avoid the stack bounds check. - // - //go:nowritebarrierrec -+//go:nosplit - func dropm() { - // Clear m and g, and return m to the extra list. - // After the call to setg we can only call nosplit functions -diff --git a/src/runtime/testdata/testprogcgo/stackswitch.c b/src/runtime/testdata/testprogcgo/stackswitch.c -new file mode 100644 -index 000000000000..2f79cc28ed95 ---- /dev/null -+++ b/src/runtime/testdata/testprogcgo/stackswitch.c -@@ -0,0 +1,106 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build unix && !android && !openbsd -+ -+// Required for darwin ucontext. -+#define _XOPEN_SOURCE -+// Required for netbsd stack_t if _XOPEN_SOURCE is set. -+#define _XOPEN_SOURCE_EXTENDED 1 -+#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+// musl libc does not provide getcontext, etc. Skip the test there. -+// -+// musl libc doesn't provide any direct detection mechanism. So assume any -+// non-glibc linux is using musl. -+// -+// Note that bionic does not provide getcontext either, but that is skipped via -+// the android build tag. -+#if defined(__linux__) && !defined(__GLIBC__) -+#define MUSL 1 -+#endif -+#if defined(MUSL) -+void callStackSwitchCallbackFromThread(void) { -+ printf("SKIP\n"); -+ exit(0); -+} -+#else -+ -+// Use a stack size larger than the 32kb estimate in -+// runtime.callbackUpdateSystemStack. This ensures that a second stack -+// allocation won't accidentally count as in bounds of the first stack -+#define STACK_SIZE (64ull << 10) -+ -+static ucontext_t uctx_save, uctx_switch; -+ -+extern void stackSwitchCallback(void); -+ -+static void *stackSwitchThread(void *arg) { -+ // Simple test: callback works from the normal system stack. -+ stackSwitchCallback(); -+ -+ // Next, verify that switching stacks doesn't break callbacks. -+ -+ char *stack1 = malloc(STACK_SIZE); -+ if (stack1 == NULL) { -+ perror("malloc"); -+ exit(1); -+ } -+ -+ // Allocate the second stack before freeing the first to ensure we don't get -+ // the same address from malloc. -+ char *stack2 = malloc(STACK_SIZE); -+ if (stack1 == NULL) { -+ perror("malloc"); -+ exit(1); -+ } -+ -+ if (getcontext(&uctx_switch) == -1) { -+ perror("getcontext"); -+ exit(1); -+ } -+ uctx_switch.uc_stack.ss_sp = stack1; -+ uctx_switch.uc_stack.ss_size = STACK_SIZE; -+ uctx_switch.uc_link = &uctx_save; -+ makecontext(&uctx_switch, stackSwitchCallback, 0); -+ -+ if (swapcontext(&uctx_save, &uctx_switch) == -1) { -+ perror("swapcontext"); -+ exit(1); -+ } -+ -+ if (getcontext(&uctx_switch) == -1) { -+ perror("getcontext"); -+ exit(1); -+ } -+ uctx_switch.uc_stack.ss_sp = stack2; -+ uctx_switch.uc_stack.ss_size = STACK_SIZE; -+ uctx_switch.uc_link = &uctx_save; -+ makecontext(&uctx_switch, stackSwitchCallback, 0); -+ -+ if (swapcontext(&uctx_save, &uctx_switch) == -1) { -+ perror("swapcontext"); -+ exit(1); -+ } -+ -+ free(stack1); -+ free(stack2); -+ -+ return NULL; -+} -+ -+void callStackSwitchCallbackFromThread(void) { -+ pthread_t thread; -+ assert(pthread_create(&thread, NULL, stackSwitchThread, NULL) == 0); -+ assert(pthread_join(thread, NULL) == 0); -+} -+ -+#endif -diff --git a/src/runtime/testdata/testprogcgo/stackswitch.go b/src/runtime/testdata/testprogcgo/stackswitch.go -new file mode 100644 -index 000000000000..a2e422f0777f ---- /dev/null -+++ b/src/runtime/testdata/testprogcgo/stackswitch.go -@@ -0,0 +1,43 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build unix && !android && !openbsd -+ -+package main -+ -+/* -+void callStackSwitchCallbackFromThread(void); -+*/ -+import "C" -+ -+import ( -+ "fmt" -+ "runtime/debug" -+) -+ -+func init() { -+ register("StackSwitchCallback", StackSwitchCallback) -+} -+ -+//export stackSwitchCallback -+func stackSwitchCallback() { -+ // We want to trigger a bounds check on the g0 stack. To do this, we -+ // need to call a splittable function through systemstack(). -+ // SetGCPercent contains such a systemstack call. -+ gogc := debug.SetGCPercent(100) -+ debug.SetGCPercent(gogc) -+} -+ -+ -+// Regression test for https://go.dev/issue/62440. It should be possible for C -+// threads to call into Go from different stacks without crashing due to g0 -+// stack bounds checks. -+// -+// N.B. This is only OK for threads created in C. Threads with Go frames up the -+// stack must not change the stack out from under us. -+func StackSwitchCallback() { -+ C.callStackSwitchCallbackFromThread(); -+ -+ fmt.Printf("OK\n") -+} --- -2.33.0 - diff --git a/backport-0029-Backport-net-http-persist-header-stripping-across-re.patch b/backport-0029-Backport-net-http-persist-header-stripping-across-re.patch deleted file mode 100644 index 668ddf9a3612fa8e9904fe53a2ba19b07af4c023..0000000000000000000000000000000000000000 --- a/backport-0029-Backport-net-http-persist-header-stripping-across-re.patch +++ /dev/null @@ -1,412 +0,0 @@ -From a2d38dcd10bfbc340ce27470f350a9db3c7ff2c3 Mon Sep 17 00:00:00 2001 -From: t00884001 -Date: Wed, 22 Jan 2025 16:45:27 +0800 -Subject: [PATCH 1/2] [Backport] net/http: persist header stripping across - repeated redirects - -CVE: CVE-2024-45336 -Reference: https://go-review.googlesource.com/c/go/+/643106 - -When an HTTP redirect changes the host of a request, we drop -sensitive headers such as Authorization from the redirected request. -Fix a bug where a chain of redirects could result in sensitive -headers being sent to the wrong host: - - 1. request to a.tld with Authorization header - 2. a.tld redirects to b.tld - 3. request to b.tld with no Authorization header - 4. b.tld redirects to b.tld - 3. request to b.tld with Authorization header restored - -Thanks to Kyle Seely for reporting this issue. - -Note: The upstream does not submit this change to go1.20.7 according to the rules of MinorReleases. -corego5.x are based on go1.20.7. Therefore, it need to submit the change to corego5.x. - -Edited-by: TangJianfeng t00884001 - -Fixes #70530 -For #71210 -Fixes CVE-2024-45336 - -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1641 -Reviewed-by: Roland Shoemaker -Reviewed-by: Tatiana Bradley -Commit-Queue: Roland Shoemaker -Change-Id: Id7b1e3c90345566b8ee1a51f65dbb179da6eb427 -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1765 -Reviewed-on: https://go-review.googlesource.com/c/go/+/643106 -Reviewed-by: Michael Pratt -LUCI-TryBot-Result: Go LUCI -Auto-Submit: Michael Knyszek -Signed-off-by: TangJianfeng tony.tangjianfeng@huawei.com ---- - src/net/http/client.go | 65 ++++++------ - src/net/http/client_test.go | 111 +++++++++++++++------ - src/net/http/internal/testcert/testcert.go | 84 ++++++++-------- - 3 files changed, 154 insertions(+), 106 deletions(-) - -diff --git a/src/net/http/client.go b/src/net/http/client.go -index 77a701b806..63234489ec 100644 ---- a/src/net/http/client.go -+++ b/src/net/http/client.go -@@ -612,8 +612,9 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) { - reqBodyClosed = false // have we closed the current req.Body? - - // Redirect behavior: -- redirectMethod string -- includeBody bool -+ redirectMethod string -+ includeBody = true -+ stripSensitiveHeaders = false - ) - uerr := func(err error) error { - // the body may have been closed already by c.send() -@@ -680,7 +681,12 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) { - // in case the user set Referer on their first request. - // If they really want to override, they can do it in - // their CheckRedirect func. -- copyHeaders(req) -+ if !stripSensitiveHeaders && reqs[0].URL.Host != req.URL.Host { -+ if !shouldCopyHeaderOnRedirect(reqs[0].URL, req.URL) { -+ stripSensitiveHeaders = true -+ } -+ } -+ copyHeaders(req, stripSensitiveHeaders) - - // Add the Referer header from the most recent - // request URL to the new one, if it's not https->http: -@@ -746,7 +752,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) { - // makeHeadersCopier makes a function that copies headers from the - // initial Request, ireq. For every redirect, this function must be called - // so that it can copy headers into the upcoming Request. --func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) { -+func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensitiveHeaders bool) { - // The headers to copy are from the very initial request. - // We use a closured callback to keep a reference to these original headers. - var ( -@@ -760,8 +766,7 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) { - } - } - -- preq := ireq // The previous request -- return func(req *Request) { -+ return func(req *Request, stripSensitiveHeaders bool) { - // If Jar is present and there was some initial cookies provided - // via the request header, then we may need to alter the initial - // cookies as we follow redirects since each redirect may end up -@@ -798,12 +803,15 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) { - // Copy the initial request's Header values - // (at least the safe ones). - for k, vv := range ireqhdr { -- if shouldCopyHeaderOnRedirect(k, preq.URL, req.URL) { -+ sensitive := false -+ switch CanonicalHeaderKey(k) { -+ case "Authorization", "Www-Authenticate", "Cookie", "Cookie2": -+ sensitive = true -+ } -+ if !(sensitive && stripSensitiveHeaders) { - req.Header[k] = vv - } - } -- -- preq = req // Update previous Request with the current request - } - } - -@@ -982,28 +990,23 @@ func (b *cancelTimerBody) Close() error { - return err - } - --func shouldCopyHeaderOnRedirect(headerKey string, initial, dest *url.URL) bool { -- switch CanonicalHeaderKey(headerKey) { -- case "Authorization", "Www-Authenticate", "Cookie", "Cookie2": -- // Permit sending auth/cookie headers from "foo.com" -- // to "sub.foo.com". -- -- // Note that we don't send all cookies to subdomains -- // automatically. This function is only used for -- // Cookies set explicitly on the initial outgoing -- // client request. Cookies automatically added via the -- // CookieJar mechanism continue to follow each -- // cookie's scope as set by Set-Cookie. But for -- // outgoing requests with the Cookie header set -- // directly, we don't know their scope, so we assume -- // it's for *.domain.com. -- -- ihost := idnaASCIIFromURL(initial) -- dhost := idnaASCIIFromURL(dest) -- return isDomainOrSubdomain(dhost, ihost) -- } -- // All other headers are copied: -- return true -+func shouldCopyHeaderOnRedirect(initial, dest *url.URL) bool { -+ // Permit sending auth/cookie headers from "foo.com" -+ // to "sub.foo.com". -+ -+ // Note that we don't send all cookies to subdomains -+ // automatically. This function is only used for -+ // Cookies set explicitly on the initial outgoing -+ // client request. Cookies automatically added via the -+ // CookieJar mechanism continue to follow each -+ // cookie's scope as set by Set-Cookie. But for -+ // outgoing requests with the Cookie header set -+ // directly, we don't know their scope, so we assume -+ // it's for *.domain.com. -+ -+ ihost := idnaASCIIFromURL(initial) -+ dhost := idnaASCIIFromURL(dest) -+ return isDomainOrSubdomain(dhost, ihost) - } - - // isDomainOrSubdomain reports whether sub is a subdomain (or exact -diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go -index fc1d791612..dba1aa1a66 100644 ---- a/src/net/http/client_test.go -+++ b/src/net/http/client_test.go -@@ -1544,6 +1544,55 @@ func testClientCopyHeadersOnRedirect(t *testing.T, mode testMode) { - } - } - -+// Issue #70530: Once we strip a header on a redirect to a different host, -+// the header should stay stripped across any further redirects. -+func TestClientStripHeadersOnRepeatedRedirect(t *testing.T) { -+ run(t, testClientStripHeadersOnRepeatedRedirect) -+} -+func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) { -+ var proto string -+ ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { -+ if r.Host+r.URL.Path != "a.example.com/" { -+ if h := r.Header.Get("Authorization"); h != "" { -+ t.Errorf("on request to %v%v, Authorization=%q, want no header", r.Host, r.URL.Path, h) -+ } -+ } -+ // Follow a chain of redirects from a to b and back to a. -+ // The Authorization header is stripped on the first redirect to b, -+ // and stays stripped even if we're sent back to a. -+ switch r.Host + r.URL.Path { -+ case "a.example.com/": -+ Redirect(w, r, proto+"://b.example.com/", StatusFound) -+ case "b.example.com/": -+ Redirect(w, r, proto+"://b.example.com/redirect", StatusFound) -+ case "b.example.com/redirect": -+ Redirect(w, r, proto+"://a.example.com/redirect", StatusFound) -+ case "a.example.com/redirect": -+ w.Header().Set("X-Done", "true") -+ default: -+ t.Errorf("unexpected request to %v", r.URL) -+ } -+ })).ts -+ proto, _, _ = strings.Cut(ts.URL, ":") -+ -+ c := ts.Client() -+ c.Transport.(*Transport).Dial = func(_ string, _ string) (net.Conn, error) { -+ return net.Dial("tcp", ts.Listener.Addr().String()) -+ } -+ -+ req, _ := NewRequest("GET", proto+"://a.example.com/", nil) -+ req.Header.Add("Cookie", "foo=bar") -+ req.Header.Add("Authorization", "secretpassword") -+ res, err := c.Do(req) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer res.Body.Close() -+ if res.Header.Get("X-Done") != "true" { -+ t.Fatalf("response missing expected header: X-Done=true") -+ } -+} -+ - // Issue 22233: copy host when Client follows a relative redirect. - func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) } - func testClientCopyHostOnRedirect(t *testing.T, mode testMode) { -@@ -1710,43 +1759,39 @@ func testClientAltersCookiesOnRedirect(t *testing.T, mode testMode) { - // Part of Issue 4800 - func TestShouldCopyHeaderOnRedirect(t *testing.T) { - tests := []struct { -- header string - initialURL string - destURL string - want bool - }{ -- {"User-Agent", "http://foo.com/", "http://bar.com/", true}, -- {"X-Foo", "http://foo.com/", "http://bar.com/", true}, -- - // Sensitive headers: -- {"cookie", "http://foo.com/", "http://bar.com/", false}, -- {"cookie2", "http://foo.com/", "http://bar.com/", false}, -- {"authorization", "http://foo.com/", "http://bar.com/", false}, -- {"authorization", "http://foo.com/", "https://foo.com/", true}, -- {"authorization", "http://foo.com:1234/", "http://foo.com:4321/", true}, -- {"www-authenticate", "http://foo.com/", "http://bar.com/", false}, -- {"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false}, -+ {"http://foo.com/", "http://bar.com/", false}, -+ {"http://foo.com/", "http://bar.com/", false}, -+ {"http://foo.com/", "http://bar.com/", false}, -+ {"http://foo.com/", "https://foo.com/", true}, -+ {"http://foo.com:1234/", "http://foo.com:4321/", true}, -+ {"http://foo.com/", "http://bar.com/", false}, -+ {"http://foo.com/", "http://[::1%25.foo.com]/", false}, - - // But subdomains should work: -- {"www-authenticate", "http://foo.com/", "http://foo.com/", true}, -- {"www-authenticate", "http://foo.com/", "http://sub.foo.com/", true}, -- {"www-authenticate", "http://foo.com/", "http://notfoo.com/", false}, -- {"www-authenticate", "http://foo.com/", "https://foo.com/", true}, -- {"www-authenticate", "http://foo.com:80/", "http://foo.com/", true}, -- {"www-authenticate", "http://foo.com:80/", "http://sub.foo.com/", true}, -- {"www-authenticate", "http://foo.com:443/", "https://foo.com/", true}, -- {"www-authenticate", "http://foo.com:443/", "https://sub.foo.com/", true}, -- {"www-authenticate", "http://foo.com:1234/", "http://foo.com/", true}, -- -- {"authorization", "http://foo.com/", "http://foo.com/", true}, -- {"authorization", "http://foo.com/", "http://sub.foo.com/", true}, -- {"authorization", "http://foo.com/", "http://notfoo.com/", false}, -- {"authorization", "http://foo.com/", "https://foo.com/", true}, -- {"authorization", "http://foo.com:80/", "http://foo.com/", true}, -- {"authorization", "http://foo.com:80/", "http://sub.foo.com/", true}, -- {"authorization", "http://foo.com:443/", "https://foo.com/", true}, -- {"authorization", "http://foo.com:443/", "https://sub.foo.com/", true}, -- {"authorization", "http://foo.com:1234/", "http://foo.com/", true}, -+ {"http://foo.com/", "http://foo.com/", true}, -+ {"http://foo.com/", "http://sub.foo.com/", true}, -+ {"http://foo.com/", "http://notfoo.com/", false}, -+ {"http://foo.com/", "https://foo.com/", true}, -+ {"http://foo.com:80/", "http://foo.com/", true}, -+ {"http://foo.com:80/", "http://sub.foo.com/", true}, -+ {"http://foo.com:443/", "https://foo.com/", true}, -+ {"http://foo.com:443/", "https://sub.foo.com/", true}, -+ {"http://foo.com:1234/", "http://foo.com/", true}, -+ -+ {"http://foo.com/", "http://foo.com/", true}, -+ {"http://foo.com/", "http://sub.foo.com/", true}, -+ {"http://foo.com/", "http://notfoo.com/", false}, -+ {"http://foo.com/", "https://foo.com/", true}, -+ {"http://foo.com:80/", "http://foo.com/", true}, -+ {"http://foo.com:80/", "http://sub.foo.com/", true}, -+ {"http://foo.com:443/", "https://foo.com/", true}, -+ {"http://foo.com:443/", "https://sub.foo.com/", true}, -+ {"http://foo.com:1234/", "http://foo.com/", true}, - } - for i, tt := range tests { - u0, err := url.Parse(tt.initialURL) -@@ -1759,10 +1804,10 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) { - t.Errorf("%d. dest URL %q parse error: %v", i, tt.destURL, err) - continue - } -- got := Export_shouldCopyHeaderOnRedirect(tt.header, u0, u1) -+ got := Export_shouldCopyHeaderOnRedirect(u0, u1) - if got != tt.want { -- t.Errorf("%d. shouldCopyHeaderOnRedirect(%q, %q => %q) = %v; want %v", -- i, tt.header, tt.initialURL, tt.destURL, got, tt.want) -+ t.Errorf("%d. shouldCopyHeaderOnRedirect(%q => %q) = %v; want %v", -+ i, tt.initialURL, tt.destURL, got, tt.want) - } - } - } -diff --git a/src/net/http/internal/testcert/testcert.go b/src/net/http/internal/testcert/testcert.go -index d510e791d6..78ce42e228 100644 ---- a/src/net/http/internal/testcert/testcert.go -+++ b/src/net/http/internal/testcert/testcert.go -@@ -10,56 +10,56 @@ import "strings" - // LocalhostCert is a PEM-encoded TLS cert with SAN IPs - // "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT. - // generated from src/crypto/tls: --// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h -+// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com,*.example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h - var LocalhostCert = []byte(`-----BEGIN CERTIFICATE----- --MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS -+MIIDSDCCAjCgAwIBAgIQEP/md970HysdBTpuzDOf0DANBgkqhkiG9w0BAQsFADAS - MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw - MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A --MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r --bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U --aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P --YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk --POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu --h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE -+MIIBCgKCAQEAxcl69ROJdxjN+MJZnbFrYxyQooADCsJ6VDkuMyNQIix/Hk15Nk/u -+FyBX1Me++aEpGmY3RIY4fUvELqT/srvAHsTXwVVSttMcY8pcAFmXSqo3x4MuUTG/ -+jCX3Vftj0r3EM5M8ImY1rzA/jqTTLJg00rD+DmuDABcqQvoXw/RV8w1yTRi5BPoH -+DFD/AWTt/YgMvk1l2Yq/xI8VbMUIpjBoGXxWsSevQ5i2s1mk9/yZzu0Ysp1tTlzD -+qOPa4ysFjBitdXiwfxjxtv5nXqOCP5rheKO0sWLk0fetMp1OV5JSJMAJw6c2ZMkl -+U2WMqAEpRjdE/vHfIuNg+yGaRRqI07NZRQIDAQABo4GXMIGUMA4GA1UdDwEB/wQE - AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud --DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv --bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI --5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv --cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2 --+tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B --grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK --5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/ --WkBKOclmOV2xlTVuPw== -+DgQWBBQR5QIzmacmw78ZI1C4MXw7Q0wJ1jA9BgNVHREENjA0ggtleGFtcGxlLmNv -+bYINKi5leGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG -+9w0BAQsFAAOCAQEACrRNgiioUDzxQftd0fwOa6iRRcPampZRDtuaF68yNHoNWbOu -+LUwc05eOWxRq3iABGSk2xg+FXM3DDeW4HhAhCFptq7jbVZ+4Jj6HeJG9mYRatAxR -+Y/dEpa0D0EHhDxxVg6UzKOXB355n0IetGE/aWvyTV9SiDs6QsaC57Q9qq1/mitx5 -+2GFBoapol9L5FxCc77bztzK8CpLujkBi25Vk6GAFbl27opLfpyxkM+rX/T6MXCPO -+6/YBacNZ7ff1/57Etg4i5mNA6ubCpuc4Gi9oYqCNNohftr2lkJr7REdDR6OW0lsL -+rF7r4gUnKeC7mYIH1zypY7laskopiLFAfe96Kg== - -----END CERTIFICATE-----`) - - // LocalhostKey is the private key for LocalhostCert. - var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY----- --MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDoZtrm0dXV0Aqi --4Bpc7f95sNRTiu/AJSD8I1onY9PnEsPg3VVxvytsVJbYdcqr4w99V3AgpH/UNzMS --gAZ/8lZBNbsSDOVesJ3euVqMRfYPvd9pYl6QPRRpSDPm+2tNdn3QFAvta9EgJ3sW --URnoU85w+W6aLI2bNSq3AaE771p3VbkGolpEjo9h+i42TBHo1rhPNKPkGupR8/QX --AOLMpInRdeaHyDwb2a3DE5I3dG7VAVzrVfJ6W6Q84YoFX+rpEE2SVM17SAjy6xQy --VjKgLvK2mk0xbtfa+h0B6VK7bmODHZqeP18NVm6HsBcXn7iclLgAC3SfWU1jucZK --x1lqzw9tAgMBAAECggEABWzxS1Y2wckblnXY57Z+sl6YdmLV+gxj2r8Qib7g4ZIk --lIlWR1OJNfw7kU4eryib4fc6nOh6O4AWZyYqAK6tqNQSS/eVG0LQTLTTEldHyVJL --dvBe+MsUQOj4nTndZW+QvFzbcm2D8lY5n2nBSxU5ypVoKZ1EqQzytFcLZpTN7d89 --EPj0qDyrV4NZlWAwL1AygCwnlwhMQjXEalVF1ylXwU3QzyZ/6MgvF6d3SSUlh+sq --XefuyigXw484cQQgbzopv6niMOmGP3of+yV4JQqUSb3IDmmT68XjGd2Dkxl4iPki --6ZwXf3CCi+c+i/zVEcufgZ3SLf8D99kUGE7v7fZ6AQKBgQD1ZX3RAla9hIhxCf+O --3D+I1j2LMrdjAh0ZKKqwMR4JnHX3mjQI6LwqIctPWTU8wYFECSh9klEclSdCa64s --uI/GNpcqPXejd0cAAdqHEEeG5sHMDt0oFSurL4lyud0GtZvwlzLuwEweuDtvT9cJ --Wfvl86uyO36IW8JdvUprYDctrQKBgQDycZ697qutBieZlGkHpnYWUAeImVA878sJ --w44NuXHvMxBPz+lbJGAg8Cn8fcxNAPqHIraK+kx3po8cZGQywKHUWsxi23ozHoxo --+bGqeQb9U661TnfdDspIXia+xilZt3mm5BPzOUuRqlh4Y9SOBpSWRmEhyw76w4ZP --OPxjWYAgwQKBgA/FehSYxeJgRjSdo+MWnK66tjHgDJE8bYpUZsP0JC4R9DL5oiaA --brd2fI6Y+SbyeNBallObt8LSgzdtnEAbjIH8uDJqyOmknNePRvAvR6mP4xyuR+Bv --m+Lgp0DMWTw5J9CKpydZDItc49T/mJ5tPhdFVd+am0NAQnmr1MCZ6nHxAoGABS3Y --LkaC9FdFUUqSU8+Chkd/YbOkuyiENdkvl6t2e52jo5DVc1T7mLiIrRQi4SI8N9bN --/3oJWCT+uaSLX2ouCtNFunblzWHBrhxnZzTeqVq4SLc8aESAnbslKL4i8/+vYZlN --s8xtiNcSvL+lMsOBORSXzpj/4Ot8WwTkn1qyGgECgYBKNTypzAHeLE6yVadFp3nQ --Ckq9yzvP/ib05rvgbvrne00YeOxqJ9gtTrzgh7koqJyX1L4NwdkEza4ilDWpucn0 --xiUZS4SoaJq6ZvcBYS62Yr1t8n09iG47YL8ibgtmH3L+svaotvpVxVK+d7BLevA/ --ZboOWVe3icTy64BT3OQhmg== -+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDFyXr1E4l3GM34 -+wlmdsWtjHJCigAMKwnpUOS4zI1AiLH8eTXk2T+4XIFfUx775oSkaZjdEhjh9S8Qu -+pP+yu8AexNfBVVK20xxjylwAWZdKqjfHgy5RMb+MJfdV+2PSvcQzkzwiZjWvMD+O -+pNMsmDTSsP4Oa4MAFypC+hfD9FXzDXJNGLkE+gcMUP8BZO39iAy+TWXZir/EjxVs -+xQimMGgZfFaxJ69DmLazWaT3/JnO7RiynW1OXMOo49rjKwWMGK11eLB/GPG2/mde -+o4I/muF4o7SxYuTR960ynU5XklIkwAnDpzZkySVTZYyoASlGN0T+8d8i42D7IZpF -+GojTs1lFAgMBAAECggEAIYthUi1lFBDd5gG4Rzlu+BlBIn5JhcqkCqLEBiJIFfOr -+/4yuMRrvS3bNzqWt6xJ9MSAC4ZlN/VobRLnxL/QNymoiGYUKCT3Ww8nvPpPzR9OE -+sE68TUL9tJw/zZJcRMKwgvrGqSLimfq53MxxkE+kLdOc0v9C8YH8Re26mB5ZcWYa -+7YFyZQpKsQYnsmu/05cMbpOQrQWhtmIqRoyn8mG/par2s3NzjtpSE9NINyz26uFc -+k/3ovFJQIHkUmTS7KHD3BgY5vuCqP98HramYnOysJ0WoYgvSDNCWw3037s5CCwJT -+gCKuM+Ow6liFrj83RrdKBpm5QUGjfNpYP31o+QNP4QKBgQDSrUQ2XdgtAnibAV7u -+7kbxOxro0EhIKso0Y/6LbDQgcXgxLqltkmeqZgG8nC3Z793lhlSasz2snhzzooV5 -+5fTy1y8ikXqjhG0nNkInFyOhsI0auE28CFoDowaQd+5cmCatpN4Grqo5PNRXxm1w -+HktfPEgoP11NNCFHvvN5fEKbbQKBgQDwVlOaV20IvW3IPq7cXZyiyabouFF9eTRo -+VJka1Uv+JtyvL2P0NKkjYHOdN8gRblWqxQtJoTNk020rVA4UP1heiXALy50gvj/p -+hMcybPTLYSPOhAGx838KIcvGR5oskP1aUCmFbFQzGELxhJ9diVVjxUtbG2DuwPKd -+tD9TLxT2OQKBgQCcdlHSjp+dzdgERmBa0ludjGfPv9/uuNizUBAbO6D690psPFtY -+JQMYaemgSd1DngEOFVWADt4e9M5Lose+YCoqr+UxpxmNlyv5kzJOFcFAs/4XeglB -+PHKdgNW/NVKxMc6H54l9LPr+x05sYdGlEtqnP/3W5jhEvhJ5Vjc8YiyVgQKBgQCl -+zwjyrGo+42GACy7cPYE5FeIfIDqoVByB9guC5bD98JXEDu/opQQjsgFRcBCJZhOY -+M0UsURiB8ROaFu13rpQq9KrmmF0ZH+g8FSzQbzcbsTLg4VXCDXmR5esOKowFPypr -+Sm667BfTAGP++D5ya7MLmCv6+RKQ5XD8uEQQAaV2kQKBgAD8qeJuWIXZT0VKkQrn -+nIhgtzGERF/6sZdQGW2LxTbUDWG74AfFkkEbeBfwEkCZXY/xmnYqYABhvlSex8jU -+supU6Eea21esIxIub2zv/Np0ojUb6rlqTPS4Ox1E27D787EJ3VOXpriSD10vyNnZ -+jel6uj2FOP9g54s+GzlSVg/T - -----END RSA TESTING KEY-----`)) - - func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } --- -2.33.0 - diff --git a/backport-0030-Backport-crypto-x509-properly-check-for-IPv6-hosts-i.patch b/backport-0030-Backport-crypto-x509-properly-check-for-IPv6-hosts-i.patch deleted file mode 100644 index fb704dc5fb3f970640577fc62a9367d2d52568ef..0000000000000000000000000000000000000000 --- a/backport-0030-Backport-crypto-x509-properly-check-for-IPv6-hosts-i.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 63669d97d675d662d14311268097c6f85e99cae1 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Mon, 9 Dec 2024 11:31:22 -0800 -Subject: [PATCH 2/2] [Backport] crypto/x509: properly check for IPv6 hosts in - URIs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -CVE: CVE-2024-45341 -Reference: https://go-review.googlesource.com/c/go/+/643105 - -When checking URI constraints, use netip.ParseAddr, which understands -zones, unlike net.ParseIP which chokes on them. This prevents zone IDs -from mistakenly satisfying URI constraints. - -Thanks to Juho Forsén of Mattermost for reporting this issue. - -Note: The upstream does not submit this change to go1.22.1 according to the rules of MinorReleases. -Corego6.x are based on go1.22.1. Therefore, it need to submit the change to corego6.x. - -Edited-by: qinlonglong q00508429 - -For #71156 -Fixes #71207 -Fixes CVE-2024-45341 - -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1700 -Reviewed-by: Tatiana Bradley -Reviewed-by: Damien Neil -Change-Id: I1d97723e0f29fcf1404fb868ba0495282da70f6e -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1780 -Reviewed-by: Roland Shoemaker -Reviewed-on: https://go-review.googlesource.com/c/go/+/643105 -TryBot-Bypass: Michael Knyszek -Reviewed-by: Michael Pratt -Auto-Submit: Michael Knyszek -Signed-off-by: QinLongLong qinlonglong@huawei.com ---- - src/crypto/x509/name_constraints_test.go | 18 ++++++++++++++++++ - src/crypto/x509/verify.go | 7 +++++-- - 2 files changed, 23 insertions(+), 2 deletions(-) - -diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go -index 4c22c4cd8e..78263fc0b2 100644 ---- a/src/crypto/x509/name_constraints_test.go -+++ b/src/crypto/x509/name_constraints_test.go -@@ -1599,6 +1599,24 @@ var nameConstraintsTests = []nameConstraintsTest{ - cn: "foo.bar", - }, - }, -+ -+ // #86: URIs with IPv6 addresses with zones and ports are rejected -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:http://[2006:abcd::1%25.example.com]:16/"}, -+ }, -+ expectedError: "URI with IP", -+ }, - } - - func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { -diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go -index 56a1a1725c..1da13d8d55 100644 ---- a/src/crypto/x509/verify.go -+++ b/src/crypto/x509/verify.go -@@ -11,6 +11,7 @@ import ( - "errors" - "fmt" - "net" -+ "net/netip" - "net/url" - "reflect" - "runtime" -@@ -429,8 +430,10 @@ func matchURIConstraint(uri *url.URL, constraint string) (bool, error) { - } - } - -- if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") || -- net.ParseIP(host) != nil { -+ // netip.ParseAddr will reject the URI IPv6 literal form "[...]", so we -+ // check if _either_ the string parses as an IP, or if it is enclosed in -+ // square brackets. -+ if _, err := netip.ParseAddr(host); err == nil || (strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]")) { - return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String()) - } - --- -2.33.0 - diff --git a/backport-0031-CVE-2025-22870.patch b/backport-0031-CVE-2025-22870.patch deleted file mode 100644 index bcfdc8c5473f8393ff31af49f4f7875041f28838..0000000000000000000000000000000000000000 --- a/backport-0031-CVE-2025-22870.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 334de7982f8ec959c74470dd709ceedfd6dbd50a Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Wed, 26 Feb 2025 16:46:43 -0800 -Subject: [PATCH] [release-branch.go1.24] all: updated vendored x/net with - security fix - -6ed00d0 [internal-branch.go1.24-vendor] proxy, http/httpproxy: do not mismatch IPv6 zone ids against hosts - -Fixes CVE-2025-22870 -For #71986 - -Change-Id: I7bda0825f1a9470b0708714d9cc32b5eae212f8b -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2121 -Reviewed-by: Neal Patel -Reviewed-by: Roland Shoemaker -Commit-Queue: Roland Shoemaker -Reviewed-on: https://go-review.googlesource.com/c/go/+/654715 -Reviewed-by: Michael Pratt -LUCI-TryBot-Result: Go LUCI -Auto-Submit: Junyang Shao -Reviewed-by: Damien Neil ---- - src/cmd/internal/moddeps/moddeps_test.go | 1 + - src/vendor/golang.org/x/net/http/httpproxy/proxy.go | 10 ++++++++-- - 2 files changed, 9 insertions(+), 2 deletions(-) - -diff --git a/src/cmd/internal/moddeps/moddeps_test.go b/src/cmd/internal/moddeps/moddeps_test.go -index ae890b6..9dc4741 100644 ---- a/src/cmd/internal/moddeps/moddeps_test.go -+++ b/src/cmd/internal/moddeps/moddeps_test.go -@@ -33,6 +33,7 @@ import ( - // See issues 36852, 41409, and 43687. - // (Also see golang.org/issue/27348.) - func TestAllDependencies(t *testing.T) { -+ t.Skip("TODO(#71986): 1.24.1 contains unreleased changes from vendored modules") - goBin := testenv.GoToolPath(t) - - // Ensure that all packages imported within GOROOT -diff --git a/src/vendor/golang.org/x/net/http/httpproxy/proxy.go b/src/vendor/golang.org/x/net/http/httpproxy/proxy.go -index c3bd9a1..334add3 100644 ---- a/src/vendor/golang.org/x/net/http/httpproxy/proxy.go -+++ b/src/vendor/golang.org/x/net/http/httpproxy/proxy.go -@@ -14,6 +14,7 @@ import ( - "errors" - "fmt" - "net" -+ "net/netip" - "net/url" - "os" - "strings" -@@ -180,8 +181,10 @@ func (cfg *config) useProxy(addr string) bool { - if host == "localhost" { - return false - } -- ip := net.ParseIP(host) -- if ip != nil { -+ nip, err := netip.ParseAddr(host) -+ var ip net.IP -+ if err == nil { -+ ip = net.IP(nip.AsSlice()) - if ip.IsLoopback() { - return false - } -@@ -363,6 +366,9 @@ type domainMatch struct { - } - - func (m domainMatch) match(host, port string, ip net.IP) bool { -+ if ip != nil { -+ return false -+ } - if strings.HasSuffix(host, m.host) || (m.matchHost && host == m.host[1:]) { - return m.port == "" || m.port == port - } --- -2.46.0 - diff --git a/go1.21.4.src.tar.gz b/go1.23.7.src.tar.gz similarity index 71% rename from go1.21.4.src.tar.gz rename to go1.23.7.src.tar.gz index 9b9ceeb53d04f98af4fa203b68ea2ebdb035cdc2..8cda1909dc3ad408cf3f07a72ded4d56e1d519a3 100644 Binary files a/go1.21.4.src.tar.gz and b/go1.23.7.src.tar.gz differ diff --git a/golang.spec b/golang.spec index 0148137cc71b18d7ceb11c8b6ec281c6d048a239..452c0dd7f0d57ec0425268ce825a8fabc33cb7e9 100644 --- a/golang.spec +++ b/golang.spec @@ -2,8 +2,8 @@ %global _binaries_in_noarch_packages_terminate_build 0 %global golibdir %{_libdir}/golang %global goroot /usr/lib/%{name} -%global go_api 1.20 -%global go_version 1.20 +%global go_api 1.23 +%global go_version 1.23 %global __spec_install_post /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot /usr/lib/rpm/brp-compress %global __requires_exclude_from ^(%{_datadir}|/usr/lib)/%{name}/(doc|src)/.*$ %global __strip /bin/true @@ -65,7 +65,7 @@ %endif Name: golang -Version: 1.21.4 +Version: 1.23.7 Release: 32 Summary: The Go Programming Language License: BSD and Public Domain @@ -75,7 +75,7 @@ Source0: https://dl.google.com/go/go%{version}.src.tar.gz %if !%{golang_bootstrap} BuildRequires: gcc-go >= 5 %else -BuildRequires: golang > 1.4 +BuildRequires: golang >= 1.20.6 %endif BuildRequires: hostname # for tests @@ -99,17 +99,20 @@ Recommends: glibc gcc git subversion # Bundled/Vendored provides generated by bundled-deps.sh based on the in tree module data # - in version filed substituted with . per versioning guidelines -Provides: bundled(golang(github.com/google/pprof)) = 0.0.0.20221118152302.e6195bd50e26 -Provides: bundled(golang(github.com/ianlancetaylor/demangle)) = 0.0.0.20220319035150.800ac71e25c2 -Provides: bundled(golang(golang.org/x/arch)) = 0.4.0 -Provides: bundled(golang(golang.org/x/crypto)) = 0.11.1.0.20230711161743.2e82bdd1719d -Provides: bundled(golang(golang.org/x/mod)) = 0.12.0 -Provides: bundled(golang(golang.org/x/net)) = 0.12.1.0.20231027154334.5ca955b1789c -Provides: bundled(golang(golang.org/x/sync)) = 0.3.0 -Provides: bundled(golang(golang.org/x/sys)) = 0.10.0 -Provides: bundled(golang(golang.org/x/term)) = 0.10.0 -Provides: bundled(golang(golang.org/x/text)) = 0.11.0 -Provides: bundled(golang(golang.org/x/tools)) = 0.11.1.0.20230712164437.1ca21856af7b +Provides: bundled(golang(github.com/google/pprof)) = 0.0.0.20240528025155.186aa0362fba +Provides: bundled(golang(github.com/ianlancetaylor/demangle)) = 0.0.0.20240312041847.bd984b5ce465 +Provides: bundled(golang(golang.org/x/arch)) = 0.8.0 +Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20240603162849.5dfbda438323 +Provides: bundled(golang(golang.org/x/crypto)) = 0.23.1.0.20240603234054.0b431c7de36a +Provides: bundled(golang(golang.org/x/mod)) = 0.19.0 +Provides: bundled(golang(golang.org/x/net)) = 0.25.1.0.20240603202750.6249541f2a6c +Provides: bundled(golang(golang.org/x/sync)) = 0.7.0 +Provides: bundled(golang(golang.org/x/sys)) = 0.22.0 +Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20240828213427.40b6b7fe7147 +Provides: bundled(golang(golang.org/x/term)) = 0.20.0 +Provides: bundled(golang(golang.org/x/text)) = 0.16.0 +Provides: bundled(golang(golang.org/x/tools)) = 0.22.1.0.20240618181713.f2d2ebe43e72 +Provides: bundled(golang(rsc.io/markdown)) = 0.0.0.20240306144322.0bf8f97ee8ef Provides: %{name}-bin = %{version}-%{release} Obsoletes: %{name}-bin @@ -120,37 +123,9 @@ Obsoletes: %{name}-vim < 1.4 Obsoletes: emacs-%{name} < 1.4 Requires: %{vendor}-rpm-config -Patch6001: backport-0001-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch -Patch6002: backport-0002-release-branch.go1.21-html-template-escape-additiona.patch -Patch6003: backport-0003-release-branch.go1.21-net-textproto-mime-multipart-a.patch -Patch6004: backport-0004-release-branch.go1.21-net-http-net-http-cookiejar-av.patch -Patch6005: backport-0005-release-branch.go1.21-net-mail-properly-handle-speci.patch -Patch6006: backport-0006-Backport-net-http-update-bundled-golang.org-x-net-ht.patch -Patch6007: backport-0007-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch -Patch6008: backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch -Patch6009: backport-0009-Backport-cmd-go-internal-vcs-error-out-if-the-reques.patch -Patch6010: backport-0010-release-branch.go1.21-net-http-limit-chunked-data-ov.patch -Patch6011: backport-0011-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch -Patch6012: backport-0012-net-http-send-body-or-close-connection-on-expect-100.patch -Patch6013: backport-0013-release-branch.go1.21-net-http-update-bundled-golang.patch -Patch6014: backport-0014-cmd-compile-handle-constant-pointer-offsets-in-dead-.patch -Patch6015: backport-0015-release-branch.go1.21-cmd-compile-ensure-pointer-ari.patch -Patch6016: backport-0016-release-branch.go1.21-internal-poll-add-SPLICE_F_NON.patch -Patch6017: backport-0017-release-branch.go1.21-runtime-call-enableMetadataHug.patch -Patch6018: backport-0018-release-branch.go1.21-cmd-compile-fix-findIndVar-so-.patch -Patch6019: backport-0019-release-branch.go1.21-cmd-compile-fix-escape-analysi.patch -Patch6020: backport-0020-CVE-2024-34155-track-depth-in-nested-element-lists.patch -Patch6021: backport-0021-release-branch.go1.21-runtime-pprof-fix-generics-fun.patch -Patch6022: backport-0022-encoding-gob-cover-missed-cases-when-checking-ignore.patch -Patch6023: backport-0023-go-build-constraint-add-parsing-limits.patch -Patch6024: backport-0024-release-branch.go1.21-runtime-add-the-disablethp-GOD.patch -Patch6025: backport-0025-release-branch.go1.21-runtime-put-ReadMemStats-debug.patch -Patch6026: backport-0026-release-branch.go1.21-runtime-add-race-annotations-i.patch -Patch6027: backport-0027-crypto-tls-fix-Config.Time-in-tests-using-expired-ce.patch -Patch6028: backport-0028-release-branch.go1.21-runtime-allow-update-of-system.patch -Patch6029: backport-0029-Backport-net-http-persist-header-stripping-across-re.patch -Patch6030: backport-0030-Backport-crypto-x509-properly-check-for-IPv6-hosts-i.patch -Patch6031: backport-0031-CVE-2025-22870.patch +Patch1000: 1000-all-implement-plugin-build-mode-for-riscv64.patch +Patch1001: 1001-cmd-link-cmd-internal-add-R_GOT_PCREL_ITYPE_RELOC-fo.patch +Patch1002: 1002-cmd-compile-don-t-merge-symbols-on-riscv64-when-dyna.patch Patch9001: 0001-fix-asan_test-test-case-failure.patch @@ -391,6 +366,10 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Tue Mar 25 2025 Suyun - 1.23.7-32 +- Update to 1.23.7 +- Backport several patches for riscv64 + * Fri Mar 14 2025 changtao - 1.21.4-32 - Type:CVE - CVE:CVE-2025-22870