aports/testing/maddy/fix-autobuffer-function.patch
2020-11-27 20:14:40 +00:00

69 lines
2.7 KiB
Diff

From 925b758e094335807f1928b59d1ceffac82b8a7a Mon Sep 17 00:00:00 2001
From: "fox.cpp" <fox.cpp@disroot.org>
Date: Fri, 27 Nov 2020 21:04:17 +0300
Subject: [PATCH] endpoint/smtp: Actually fix autobuffer function
Regressed in 1c42a705334b3d34b4b3ddff74c654773a4c0ef5.
It truncates messages to I/O buffer size (4096 bytes).
If first 4096 bytes cover head then it causes "unexpected EOF" (see
#300), otherwise it silently breaks the message.
---
internal/endpoint/smtp/session.go | 4 ++--
internal/endpoint/smtp/smtp.go | 12 ++++++++----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/internal/endpoint/smtp/session.go b/internal/endpoint/smtp/session.go
index ef32290..d27330e 100644
--- a/internal/endpoint/smtp/session.go
+++ b/internal/endpoint/smtp/session.go
@@ -336,7 +336,7 @@ func (s *Session) prepareBody(ctx context.Context, r io.Reader) (textproto.Heade
bufr := bufio.NewReader(r)
header, err := textproto.ReadHeader(bufr)
if err != nil {
- return textproto.Header{}, nil, err
+ return textproto.Header{}, nil, fmt.Errorf("I/O error while parsing header: %w", err)
}
if s.endp.submission {
@@ -348,7 +348,7 @@ func (s *Session) prepareBody(ctx context.Context, r io.Reader) (textproto.Heade
buf, err := s.endp.buffer(bufr)
if err != nil {
- return textproto.Header{}, nil, err
+ return textproto.Header{}, nil, fmt.Errorf("I/O error while writing buffer: %w", err)
}
return header, buf, nil
diff --git a/internal/endpoint/smtp/smtp.go b/internal/endpoint/smtp/smtp.go
index 1d57f9f..ebed9b0 100644
--- a/internal/endpoint/smtp/smtp.go
+++ b/internal/endpoint/smtp/smtp.go
@@ -149,19 +149,23 @@ func autoBufferMode(maxSize int, dir string) func(io.Reader) (buffer.Buffer, err
return func(r io.Reader) (buffer.Buffer, error) {
// First try to read up to N bytes.
initial := make([]byte, maxSize)
- actualSize, err := r.Read(initial)
+ actualSize, err := io.ReadFull(r, initial)
if err != nil {
- if err == io.EOF {
- log.Debugln("autobuffer: keeping the message in RAM")
+ if err == io.ErrUnexpectedEOF {
+ log.Debugln("autobuffer: keeping the message in RAM (read", actualSize, "bytes, got EOF)")
return buffer.MemoryBuffer{Slice: initial[:actualSize]}, nil
}
+ if err == io.EOF {
+ // Special case: message with empty body.
+ return buffer.MemoryBuffer{}, nil
+ }
// Some I/O error happened, bail out.
return nil, err
}
if actualSize < maxSize {
// Ok, the message is smaller than N. Make a MemoryBuffer and
// handle it in RAM.
- log.Debugln("autobuffer: keeping the message in RAM")
+ log.Debugln("autobuffer: keeping the message in RAM (read", actualSize, "bytes, got short read)")
return buffer.MemoryBuffer{Slice: initial[:actualSize]}, nil
}