dashboard / erock/pico / fix(send): sftp memory leak #94 rss

open · opened on 2025-12-16T04:36:12Z by erock
Help
checkout latest patchset:
ssh pr.pico.sh print pr-94 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print ps-X | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 94
add review to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add --review 94
accept PR:
ssh pr.pico.sh pr accept 94
close PR:
ssh pr.pico.sh pr close 94

Logs

erock created pr with ps-171 on 2025-12-16T04:36:12Z

Patchsets

ps-171 by erock on 2025-12-16T04:36:12Z

Patchset ps-171

fix(send): sftp memory leak

Eric Bower
2025-12-16T04:32:44Z
Back to top
The SFTP Fileread method returned a ReadAndReaderAtCloser (backed by storage objects) without ever closing it, leaking connections/file descriptors on every SFTP download.

The fix reads the content into memory and immediately closes the underlying reader via defer.
+15 -1 pkg/send/protocols/sftp/handler.go link
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
diff --git a/pkg/send/protocols/sftp/handler.go b/pkg/send/protocols/sftp/handler.go
index 7425cd7..2f654ed 100644
--- a/pkg/send/protocols/sftp/handler.go
+++ b/pkg/send/protocols/sftp/handler.go
@@ -138,8 +138,22 @@ func (f *handler) Fileread(r *sftp.Request) (io.ReaderAt, error) {
 
 	fileEntry := toFileEntry(r)
 	_, reader, err := f.writeHandler.Read(f.session, fileEntry)
+	if err != nil {
+		return nil, err
+	}
+
+	defer func() {
+		if c, ok := reader.(io.Closer); ok {
+			_ = c.Close()
+		}
+	}()
+
+	buf, err := io.ReadAll(reader)
+	if err != nil {
+		return nil, err
+	}
 
-	return reader, err
+	return bytes.NewReader(buf), nil
 }
 
 type handlererr struct {