fix incorrect error about bare cr/lf when sending a message over smtp

we weren't properly tracking the cr's and lf's when being strict about message
lines when sending data.

we are reading buffered data from a Reader. if that chunk happens to start with
a newline, we weren't looking at the previously written data, which could be a
cr. instead, in that case, we would always claim the cr/lf wasn't correct.

the new test case triggered the behaviour before having the fix.

should solve issue #129 by x8x, thanks for the report!
This commit is contained in:
Mechiel Lukkien 2024-02-16 20:14:31 +01:00
parent fd359d5973
commit 37de8de1c5
No known key found for this signature in database
2 changed files with 28 additions and 2 deletions

View file

@ -40,8 +40,10 @@ func DataWrite(w io.Writer, r io.Reader) error {
c := p[n] c := p[n]
if c == '\n' { if c == '\n' {
if firstcr < 0 { if firstcr < 0 {
// Bare newline. if n > 0 || last != '\r' {
return ErrCRLF // Bare newline.
return ErrCRLF
}
} else if firstcr != n-1 { } else if firstcr != n-1 {
// Bare carriage return. // Bare carriage return.
return ErrCRLF return ErrCRLF

View file

@ -129,3 +129,27 @@ func TestDataReader(t *testing.T) {
t.Fatalf("got err %v, expected io.ErrUnexpectedEOF", err) t.Fatalf("got err %v, expected io.ErrUnexpectedEOF", err)
} }
} }
func TestDataWriteLineBoundaries(t *testing.T) {
const valid = "Subject: test\r\n\r\nbody\r\n"
if err := DataWrite(io.Discard, &oneReader{[]byte(valid)}); err != nil {
t.Fatalf("data write: %v", err)
}
}
// oneReader returns data one byte at a time.
type oneReader struct {
buf []byte
}
func (r *oneReader) Read(buf []byte) (int, error) {
if len(r.buf) == 0 {
return 0, io.EOF
}
if len(buf) == 0 {
return 0, nil
}
buf[0] = r.buf[0]
r.buf = r.buf[1:]
return 1, nil
}