]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: ignore directory path when parsing multipart forms
authorKatie Hockman <katie@golang.org>
Mon, 26 Apr 2021 22:46:22 +0000 (18:46 -0400)
committerKatie Hockman <katie@golang.org>
Wed, 5 May 2021 18:14:49 +0000 (18:14 +0000)
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>
src/mime/multipart/multipart.go
src/net/http/request_test.go

index cb8bf393383cdd3e13eec778edb7ca21343bfe91..81bf722d4ee5fd79df3986c0ab1136e8491b7396 100644 (file)
@@ -20,6 +20,7 @@ import (
        "mime"
        "mime/quotedprintable"
        "net/textproto"
+       "path/filepath"
        "strings"
 )
 
@@ -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() {
index 07b3d6a1c76daf0988d2a9a156a86687e53e6abe..952828b395e0df66ecf4366cf8d56a31360a458d 100644 (file)
@@ -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.