Fix potential resource leaks from defer calls in for loop

This moves file operations inside the `for` loop into an anonymous func,
so the `defer` calls don't wait until the end of the handler call to
actually execute.

Ref T609
This commit is contained in:
Matt Baer 2020-01-09 12:36:58 -05:00
parent 6860c0a3ff
commit 03eeca179e
1 changed files with 34 additions and 25 deletions

View File

@ -82,36 +82,45 @@ func handleImport(app *App, u *User, w http.ResponseWriter, r *http.Request) err
filesSubmitted := len(files) filesSubmitted := len(files)
var filesImported int var filesImported int
for _, formFile := range files { for _, formFile := range files {
file, err := formFile.Open() fname := ""
if err != nil { ok := func() bool {
fileErrs = append(fileErrs, fmt.Errorf("failed to open form file: %s", formFile.Filename)) file, err := formFile.Open()
log.Error("import textfile: open from form: %v", err) if err != nil {
continue fileErrs = append(fileErrs, fmt.Errorf("failed to open form file: %s", formFile.Filename))
} log.Error("import textfile: open from form: %v", err)
defer file.Close() return false
}
defer file.Close()
tempFile, err := ioutil.TempFile("", "post-upload-*.txt") tempFile, err := ioutil.TempFile("", "post-upload-*.txt")
if err != nil { if err != nil {
fileErrs = append(fileErrs, fmt.Errorf("failed to create temporary file for: %s", formFile.Filename)) fileErrs = append(fileErrs, fmt.Errorf("failed to create temporary file for: %s", formFile.Filename))
log.Error("import textfile: create temp file: %v", err) log.Error("import textfile: create temp file: %v", err)
continue return false
} }
defer tempFile.Close() defer tempFile.Close()
_, err = io.Copy(tempFile, file) _, err = io.Copy(tempFile, file)
if err != nil { if err != nil {
fileErrs = append(fileErrs, fmt.Errorf("failed to copy file into temporary location: %s", formFile.Filename)) fileErrs = append(fileErrs, fmt.Errorf("failed to copy file into temporary location: %s", formFile.Filename))
log.Error("import textfile: copy to temp: %v", err) log.Error("import textfile: copy to temp: %v", err)
return false
}
info, err := tempFile.Stat()
if err != nil {
fileErrs = append(fileErrs, fmt.Errorf("failed to get file info of: %s", formFile.Filename))
log.Error("import textfile: stat temp file: %v", err)
return false
}
fname = info.Name()
return true
}()
if !ok {
continue continue
} }
info, err := tempFile.Stat() post, err := wfimport.FromFile(filepath.Join(os.TempDir(), fname))
if err != nil {
fileErrs = append(fileErrs, fmt.Errorf("failed to get file info of: %s", formFile.Filename))
log.Error("import textfile: stat temp file: %v", err)
continue
}
post, err := wfimport.FromFile(filepath.Join(os.TempDir(), info.Name()))
if err == wfimport.ErrEmptyFile { if err == wfimport.ErrEmptyFile {
// not a real error so don't log // not a real error so don't log
_ = addSessionFlash(app, w, r, fmt.Sprintf("%s was empty, import skipped", formFile.Filename), nil) _ = addSessionFlash(app, w, r, fmt.Sprintf("%s was empty, import skipped", formFile.Filename), nil)