[go] mime/multipart: properly remove temp files in case of error

390 views
Skip to first unread message

Gerrit Bot (Gerrit)

unread,
May 14, 2018, 7:33:09 AM5/14/18
to Ian Lance Taylor, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Gerrit Bot has uploaded this change for review.

View Change

mime/multipart: properly remove temp files in case of error

The new implementation properly uses the err variable defined in the
return values, instead of declaring a new local-scoped err variable.

Updates #20253

Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
GitHub-Last-Rev: 00f14107e6895bd21760671f2f967092a97f02df
GitHub-Pull-Request: golang/go#25381
---
M src/mime/multipart/formdata.go
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
index 22e2c8d..ef5f083 100644
--- a/src/mime/multipart/formdata.go
+++ b/src/mime/multipart/formdata.go
@@ -42,7 +42,8 @@
// Reserve an additional 10 MB for non-file parts.
maxValueBytes := maxMemory + int64(10<<20)
for {
- p, err := r.NextPart()
+ var p *Part
+ p, err = r.NextPart()
if err == io.EOF {
break
}
@@ -60,7 +61,8 @@

if !p.hasFileName() {
// value, store as string in memory
- n, err := io.CopyN(&b, p, maxValueBytes+1)
+ var n int64
+ n, err = io.CopyN(&b, p, maxValueBytes+1)
if err != nil && err != io.EOF {
return nil, err
}
@@ -77,17 +79,20 @@
Filename: filename,
Header: p.Header,
}
- n, err := io.CopyN(&b, p, maxMemory+1)
+ var n int64
+ n, err = io.CopyN(&b, p, maxMemory+1)
if err != nil && err != io.EOF {
return nil, err
}
if n > maxMemory {
// too big, write to disk and flush buffer
- file, err := ioutil.TempFile("", "multipart-")
+ var file *os.File
+ file, err = ioutil.TempFile("", "multipart-")
if err != nil {
return nil, err
}
- size, err := io.Copy(file, io.MultiReader(&b, p))
+ var size int64
+ size, err = io.Copy(file, io.MultiReader(&b, p))
if cerr := file.Close(); err == nil {
err = cerr
}

To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
Gerrit-Change-Number: 113055
Gerrit-PatchSet: 1
Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
Gerrit-MessageType: newchange

Gobot Gobot (Gerrit)

unread,
May 14, 2018, 7:33:25 AM5/14/18
to Gerrit Bot, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Congratulations on opening your first change. Thank you for your contribution!

Next steps:
Within the next week or so, a maintainer will review your change and provide
feedback. See https://golang.org/doc/contribute.html#review for more info and
tips to get your patch through code review.

Most changes in the Go project go through a few rounds of revision. This can be
surprising to people new to the project. The careful, iterative review process
is our way of helping mentor contributors and ensuring that their contributions
have a lasting impact.

During May-July and Nov-Jan the Go project is in a code freeze, during which
little code gets reviewed or merged. If a reviewer responds with a comment like
R=go1.11, it means that this CL will be reviewed as part of the next development
cycle. See https://golang.org/s/release for more details.

View Change

    To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
    Gerrit-Change-Number: 113055
    Gerrit-PatchSet: 1
    Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
    Gerrit-CC: Gobot Gobot <go...@golang.org>
    Gerrit-Comment-Date: Mon, 14 May 2018 11:33:21 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Brad Fitzpatrick (Gerrit)

    unread,
    May 14, 2018, 7:40:14 AM5/14/18
    to Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

    View Change

    1 comment:

    • File src/mime/multipart/formdata.go:

      • Patch Set #1, Line 34:

        err error) {
        form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
        defer func() {
        if err

        how about just renaming these two "err" to "reterr" and leaving the rest unchanged?

        That seems less likely to break in the future, which is especially important as this change doesn't add any new test coverage either (and we didn't have tests before).

    To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
    Gerrit-Change-Number: 113055
    Gerrit-PatchSet: 1
    Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
    Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-CC: Gobot Gobot <go...@golang.org>
    Gerrit-Comment-Date: Mon, 14 May 2018 11:40:11 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Brad Fitzpatrick (Gerrit)

    unread,
    May 14, 2018, 4:32:20 PM5/14/18
    to Peter Goetz, Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

    View Change

    1 comment:

      • Patch Set #1, Line 34:

        err error) {
        form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
        defer func() {
        if err

      • > how about just renaming these two "err" to "reterr" and leaving the rest unchanged? […]

        You do know that reterr is assigned by return statements, right?

        https://play.golang.org/p/8mwPnr0_vn-

    To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
    Gerrit-Change-Number: 113055
    Gerrit-PatchSet: 1
    Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
    Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-CC: Gobot Gobot <go...@golang.org>
    Gerrit-CC: Peter Goetz <pete...@gmail.com>
    Gerrit-Comment-Date: Mon, 14 May 2018 20:32:18 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Peter Goetz <pete...@gmail.com>
    Comment-In-Reply-To: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-MessageType: comment

    Peter Goetz (Gerrit)

    unread,
    May 14, 2018, 5:34:44 PM5/14/18
    to Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

    View Change

    1 comment:

      • Patch Set #1, Line 34:

        err error) {
        form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
        defer func() {
        if err

      • You do know that reterr is assigned by return statements, right? […]

        Ha! I did indeed *not* know this. Will update the PR according to your recommendation.

    To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
    Gerrit-Change-Number: 113055
    Gerrit-PatchSet: 1
    Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
    Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-CC: Gobot Gobot <go...@golang.org>
    Gerrit-CC: Peter Goetz <pete...@gmail.com>
    Gerrit-Comment-Date: Mon, 14 May 2018 20:38:03 +0000

    Peter Goetz (Gerrit)

    unread,
    May 14, 2018, 5:34:44 PM5/14/18
    to Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

    View Change

    1 comment:

      • Patch Set #1, Line 34:

        err error) {
        form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
        defer func() {
        if err

      • Ha! I did indeed *not* know this. Will update the PR according to your recommendation.

        Wait, in that case the code should work as is. My PR is not necessary. I will close it. It only makes me wonder why I get so many undeleted multipart temp files when I see "multipart: NextPart: bufio: buffer full" error messages. But it seems to be a different issue.

    To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
    Gerrit-Change-Number: 113055
    Gerrit-PatchSet: 1
    Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
    Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-CC: Gobot Gobot <go...@golang.org>
    Gerrit-CC: Peter Goetz <pete...@gmail.com>
    Gerrit-Comment-Date: Mon, 14 May 2018 21:27:47 +0000

    Peter Goetz (Gerrit)

    unread,
    May 14, 2018, 5:34:44 PM5/14/18
    to Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

    View Change

    1 comment:

      • Patch Set #1, Line 34:

        err error) {
        form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
        defer func() {
        if err

      • how about just renaming these two "err" to "reterr" and leaving the rest unchanged?

        I think this will not work. The remaining code will still set "err" to a value, and the defer block will see a reterr == nil and not do the cleanup.

        Agree that we'd like to cover this fix with tests. I tried adding a test, but the code is hard to test, because the cleanup cannot easily be mocked without bigger changes. I could trigger the problematic error situation though with:

        	body := `
        --MyBoundary
        [longline]
        --MyBoundary[longboundary]
        bla
        --MyBoundary--
        `
        body = strings.Replace(body, "[longboundary]", "MyBoundary"+strings.Repeat("B", (1<<15)), -1)
        body = strings.Replace(body, "[longline]", strings.Repeat("X", (1<<15)), -1)
        reader := NewReader(strings.NewReader(body), "MyBoundary"+strings.Repeat("B", (1<<15)))
        reader.ReadForm(0)

        So unless we want these bigger changes to make the code testable, I don't see how we can add a test.

    To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
    Gerrit-Change-Number: 113055
    Gerrit-PatchSet: 1
    Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
    Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-CC: Gobot Gobot <go...@golang.org>
    Gerrit-CC: Peter Goetz <pete...@gmail.com>
    Gerrit-Comment-Date: Mon, 14 May 2018 20:28:59 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No

    Brad Fitzpatrick (Gerrit)

    unread,
    May 14, 2018, 5:43:36 PM5/14/18
    to Peter Goetz, Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

    No, the issue is still that (the inner err variables are shadowing the other one), but there's an additional issue I discovered when I went to also write a test for this.

    View Change

      To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
      Gerrit-Change-Number: 113055
      Gerrit-PatchSet: 1
      Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
      Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-CC: Gobot Gobot <go...@golang.org>
      Gerrit-CC: Peter Goetz <pete...@gmail.com>
      Gerrit-Comment-Date: Mon, 14 May 2018 21:43:33 +0000

      Peter Goetz (Gerrit)

      unread,
      May 14, 2018, 5:57:01 PM5/14/18
      to Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

      Patch Set 1:

      No, the issue is still that (the inner err variables are shadowing the other one), but there's an additional issue I discovered when I went to also write a test for this.

      Not sure I understand. Since all returns do something along the lines of "return nil, err", the inner err variable will be assigned to the return err variable (even though it shadowed that before) and the defer statement is happy, no? I slightly changed your example https://play.golang.org/p/GSpnvsFB9F7 and it shows this.

      Would you mind giving another example?

      View Change

        To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: go
        Gerrit-Branch: master
        Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
        Gerrit-Change-Number: 113055
        Gerrit-PatchSet: 1
        Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
        Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
        Gerrit-CC: Gobot Gobot <go...@golang.org>
        Gerrit-CC: Peter Goetz <pete...@gmail.com>
        Gerrit-Comment-Date: Mon, 14 May 2018 21:56:57 +0000

        Brad Fitzpatrick (Gerrit)

        unread,
        May 14, 2018, 10:50:22 PM5/14/18
        to Peter Goetz, Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

        Patch Set 1:

        Patch Set 1:

        No, the issue is still that (the inner err variables are shadowing the other one), but there's an additional issue I discovered when I went to also write a test for this.

        Not sure I understand. Since all returns do something along the lines of "return nil, err", the inner err variable will be assigned to the return err variable (even though it shadowed that before) and the defer statement is happy, no? I slightly changed your example https://play.golang.org/p/GSpnvsFB9F7 and it shows this.

        Would you mind giving another example?

        Sorry, I thought I remembered a naked return in this code. Yes, if there's no naked return, the change to name the return value reterr should be sufficient.

        Time to write a test to demonstrate the problem you're seeing?

        View Change

          To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: go
          Gerrit-Branch: master
          Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
          Gerrit-Change-Number: 113055
          Gerrit-PatchSet: 1
          Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
          Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
          Gerrit-CC: Gobot Gobot <go...@golang.org>
          Gerrit-CC: Peter Goetz <pete...@gmail.com>
          Gerrit-Comment-Date: Tue, 15 May 2018 02:50:19 +0000

          Peter Goetz (Gerrit)

          unread,
          May 16, 2018, 9:46:38 AM5/16/18
          to Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

          Time to write a test to demonstrate the problem you're seeing?

          The problem I was seeing was triggered by something completely different: the reason the temp files weren't deleted was that the request that did the ParseMultipartForm() was a different one than the one that the server in server.go tries to garbage collect by calling finishRequest(). Why was it a different one? Because modifying request contexts while passing them along handler chains creates request *copies*. So the lesson learnt here is probably that parsing and garbage collecting multipart-forms should be a symmetric process.

          Will close the PR as there is no problem there.

          View Change

            To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
            Gerrit-Change-Number: 113055
            Gerrit-PatchSet: 1
            Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
            Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
            Gerrit-CC: Gobot Gobot <go...@golang.org>
            Gerrit-CC: Peter Goetz <pete...@gmail.com>
            Gerrit-Comment-Date: Wed, 16 May 2018 13:46:35 +0000

            Ian Lance Taylor (Gerrit)

            unread,
            Jun 26, 2018, 6:45:36 PM6/26/18
            to Peter Goetz, Gerrit Bot, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, golang-co...@googlegroups.com

            Ian Lance Taylor abandoned this change.

            View Change

            Abandoned Seems to be abandoned per final comment.

            To view, visit change 113055. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: Ie6b9780028b12f7ea0836c13dafce869d1dd835d
            Gerrit-Change-Number: 113055
            Gerrit-PatchSet: 1
            Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
            Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
            Gerrit-CC: Gobot Gobot <go...@golang.org>
            Gerrit-CC: Peter Goetz <pete...@gmail.com>
            Gerrit-MessageType: abandon
            Reply all
            Reply to author
            Forward
            0 new messages