]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: test that ParseMultipartForm catches overflows
authorEmmanuel T Odeke <emmanuel@orijtech.com>
Tue, 20 Oct 2020 11:11:12 +0000 (04:11 -0700)
committerEmmanuel Odeke <emm.odeke@gmail.com>
Wed, 21 Oct 2020 23:05:41 +0000 (23:05 +0000)
Tests that if the combination of:
* HTTP multipart file payload size
* ParseMultipartForm's maxMemory parameter
* the internal leeway buffer size of 10MiB

overflows, then we'll report an overflow instead of silently
passing.

Reapplies and fixes CL 254977, which was reverted in CL 263658.

The prior test lacked a res.Body.Close(), so fixed that and
added a leaked Transport check to verify correctness.

Updates 40430.

Change-Id: I3c0f7ef43d621f6eb00f07755f04f9f36c51f98f
Reviewed-on: https://go-review.googlesource.com/c/go/+/263817
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Trust: Damien Neil <dneil@google.com>

src/net/http/request_test.go

index b4ef472e71229d7a88fbb401fc96fcf7b1b1214a..19526b9ad791adf1260d61e44f09e0dcbdd21531 100644 (file)
@@ -13,6 +13,7 @@ import (
        "fmt"
        "io"
        "io/ioutil"
+       "math"
        "mime/multipart"
        . "net/http"
        "net/http/httptest"
@@ -245,6 +246,50 @@ func TestParseMultipartForm(t *testing.T) {
        }
 }
 
+// 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.
+func TestMaxInt64ForMultipartFormMaxMemoryOverflow(t *testing.T) {
+       defer afterTest(t)
+
+       payloadSize := 1 << 10
+       cst := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+               // The combination of:
+               //      MaxInt64 + payloadSize + (internal spare of 10MiB)
+               // triggers the overflow. See issue https://golang.org/issue/40430/
+               if err := req.ParseMultipartForm(math.MaxInt64); err != nil {
+                       Error(rw, err.Error(), StatusBadRequest)
+                       return
+               }
+       }))
+       defer cst.Close()
+       fBuf := new(bytes.Buffer)
+       mw := multipart.NewWriter(fBuf)
+       mf, err := mw.CreateFormFile("file", "myfile.txt")
+       if err != nil {
+               t.Fatal(err)
+       }
+       if _, err := mf.Write(bytes.Repeat([]byte("abc"), payloadSize)); err != nil {
+               t.Fatal(err)
+       }
+       if err := mw.Close(); err != nil {
+               t.Fatal(err)
+       }
+       req, err := NewRequest("POST", cst.URL, fBuf)
+       if err != nil {
+               t.Fatal(err)
+       }
+       req.Header.Set("Content-Type", mw.FormDataContentType())
+       res, err := cst.Client().Do(req)
+       if err != nil {
+               t.Fatal(err)
+       }
+       res.Body.Close()
+       if g, w := res.StatusCode, StatusBadRequest; g != w {
+               t.Fatalf("Status code mismatch: got %d, want %d", g, w)
+       }
+}
+
 func TestRedirect_h1(t *testing.T) { testRedirect(t, h1Mode) }
 func TestRedirect_h2(t *testing.T) { testRedirect(t, h2Mode) }
 func testRedirect(t *testing.T, h2 bool) {