8 Star 6 Fork 97

src-openEuler/golang
关闭

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0091-release-branch.go1.19-mime-multipart-avoid-excessive.patch 4.17 KB
一键复制 编辑 原始数据 按行查看 历史
From 8e1dde80529cc33f8ecef533778ba068e723dbae Mon Sep 17 00:00:00 2001
From: Damien Neil <dneil@google.com>
Date: Thu, 16 Mar 2023 14:18:04 -0700
Subject: [PATCH 4/6] [release-branch.go1.19] mime/multipart: avoid excessive
copy buffer allocations in ReadForm
When copying form data to disk with io.Copy,
allocate only one copy buffer and reuse it rather than
creating two buffers per file (one from io.multiReader.WriteTo,
and a second one from os.File.ReadFrom).
Thanks to Jakob Ackermann (@das7pad) for reporting this issue.
For CVE-2023-24536
For #59153
For #59269
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802453
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802395
Run-TryBot: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Change-Id: Ie405470c92abffed3356913b37d813e982c96c8b
Reviewed-on: https://go-review.googlesource.com/c/go/+/481983
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
---
src/mime/multipart/formdata.go | 15 +++++++--
src/mime/multipart/formdata_test.go | 49 +++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
index 5c3d794977b..b7e90a329b8 100644
--- a/src/mime/multipart/formdata.go
+++ b/src/mime/multipart/formdata.go
@@ -85,6 +85,7 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
maxMemoryBytes = math.MaxInt64
}
}
+ var copyBuf []byte
for {
p, err := r.nextPart(false, maxMemoryBytes)
if err == io.EOF {
@@ -148,14 +149,22 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
}
}
numDiskFiles++
- size, err := io.Copy(file, io.MultiReader(&b, p))
+ if _, err := file.Write(b.Bytes()); err != nil {
+ return nil, err
+ }
+ if copyBuf == nil {
+ copyBuf = make([]byte, 32*1024) // same buffer size as io.Copy uses
+ }
+ // os.File.ReadFrom will allocate its own copy buffer if we let io.Copy use it.
+ type writerOnly struct{ io.Writer }
+ remainingSize, err := io.CopyBuffer(writerOnly{file}, p, copyBuf)
if err != nil {
return nil, err
}
fh.tmpfile = file.Name()
- fh.Size = size
+ fh.Size = int64(b.Len()) + remainingSize
fh.tmpoff = fileOff
- fileOff += size
+ fileOff += fh.Size
if !combineFiles {
if err := file.Close(); err != nil {
return nil, err
diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
index ae54267f1b6..a91f741e63e 100644
--- a/src/mime/multipart/formdata_test.go
+++ b/src/mime/multipart/formdata_test.go
@@ -354,3 +354,52 @@ func testReadFormManyFiles(t *testing.T, distinct bool) {
t.Fatalf("temp dir contains %v files; want 0", len(names))
}
}
+
+func BenchmarkReadForm(b *testing.B) {
+ for _, test := range []struct {
+ name string
+ form func(fw *Writer, count int)
+ }{{
+ name: "fields",
+ form: func(fw *Writer, count int) {
+ for i := 0; i < count; i++ {
+ w, _ := fw.CreateFormField(fmt.Sprintf("field%v", i))
+ fmt.Fprintf(w, "value %v", i)
+ }
+ },
+ }, {
+ name: "files",
+ form: func(fw *Writer, count int) {
+ for i := 0; i < count; i++ {
+ w, _ := fw.CreateFormFile(fmt.Sprintf("field%v", i), fmt.Sprintf("file%v", i))
+ fmt.Fprintf(w, "value %v", i)
+ }
+ },
+ }} {
+ b.Run(test.name, func(b *testing.B) {
+ for _, maxMemory := range []int64{
+ 0,
+ 1 << 20,
+ } {
+ var buf bytes.Buffer
+ fw := NewWriter(&buf)
+ test.form(fw, 10)
+ if err := fw.Close(); err != nil {
+ b.Fatal(err)
+ }
+ b.Run(fmt.Sprintf("maxMemory=%v", maxMemory), func(b *testing.B) {
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ fr := NewReader(bytes.NewReader(buf.Bytes()), fw.Boundary())
+ form, err := fr.ReadForm(maxMemory)
+ if err != nil {
+ b.Fatal(err)
+ }
+ form.RemoveAll()
+ }
+
+ })
+ }
+ })
+ }
+}
--
2.33.0
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/src-openeuler/golang.git
git@gitee.com:src-openeuler/golang.git
src-openeuler
golang
golang
openEuler-20.03-LTS-SP3

搜索帮助