Skip to content

Commit

Permalink
net/http: ignore directory path when parsing multipart forms
Browse files Browse the repository at this point in the history
Fixes #45789

Change-Id: Id588f5dbbecf5fbfb54e957c53903aaa900171f2
Reviewed-on: https://go-review.googlesource.com/c/go/+/313809
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
  • Loading branch information
katiehockman committed May 5, 2021
1 parent 95dde3f commit 784ef4c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
14 changes: 11 additions & 3 deletions src/mime/multipart/multipart.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"mime"
"mime/quotedprintable"
"net/textproto"
"path/filepath"
"strings"
)

Expand Down Expand Up @@ -67,13 +68,20 @@ func (p *Part) FormName() string {
return p.dispositionParams["name"]
}

// FileName returns the filename parameter of the Part's
// Content-Disposition header.
// FileName returns the filename parameter of the Part's Content-Disposition
// header. If not empty, the filename is passed through filepath.Base (which is
// platform dependent) before being returned.
func (p *Part) FileName() string {
if p.dispositionParams == nil {
p.parseContentDisposition()
}
return p.dispositionParams["filename"]
filename := p.dispositionParams["filename"]
if filename == "" {
return ""
}
// RFC 7578, Section 4.2 requires that if a filename is provided, the
// directory path information must not be used.
return filepath.Base(filename)
}

func (p *Part) parseContentDisposition() {
Expand Down
23 changes: 23 additions & 0 deletions src/net/http/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,29 @@ func TestParseMultipartForm(t *testing.T) {
}
}

// Issue 45789: multipart form should not include directory path in filename
func TestParseMultipartFormFilename(t *testing.T) {
postData :=
`--xxx
Content-Disposition: form-data; name="file"; filename="../usr/foobar.txt/"
Content-Type: text/plain
--xxx--
`
req := &Request{
Method: "POST",
Header: Header{"Content-Type": {`multipart/form-data; boundary=xxx`}},
Body: io.NopCloser(strings.NewReader(postData)),
}
_, hdr, err := req.FormFile("file")
if err != nil {
t.Fatal(err)
}
if hdr.Filename != "foobar.txt" {
t.Errorf("expected only the last element of the path, got %q", hdr.Filename)
}
}

// Issue #40430: Test that if maxMemory for ParseMultipartForm when combined with
// the payload size and the internal leeway buffer size of 10MiB overflows, that we
// correctly return an error.
Expand Down

0 comments on commit 784ef4c

Please sign in to comment.