mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-17 14:37:02 +00:00
Go 1.18 supports fuzzing natively, so this patch migrates our fuzzing tests to make use of it.
97 lines
1.8 KiB
Go
97 lines
1.8 KiB
Go
// Fuzz testing for package smtpsrv. Based on server_test.
|
|
package smtpsrv
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net"
|
|
"net/textproto"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func fuzzConnection(t *testing.T, modeI int, data []byte) {
|
|
var mode SocketMode
|
|
addr := ""
|
|
switch modeI {
|
|
case 0:
|
|
mode = ModeSMTP
|
|
addr = smtpAddr
|
|
case 1:
|
|
mode = ModeSubmission
|
|
addr = submissionAddr
|
|
case 2:
|
|
mode = ModeSubmissionTLS
|
|
addr = submissionTLSAddr
|
|
default:
|
|
mode = ModeSMTP
|
|
addr = smtpAddr
|
|
}
|
|
|
|
var err error
|
|
var conn net.Conn
|
|
if mode.TLS {
|
|
conn, err = tls.Dial("tcp", addr, tlsConfig)
|
|
} else {
|
|
conn, err = net.Dial("tcp", addr)
|
|
}
|
|
if err != nil {
|
|
panic(fmt.Errorf("failed to dial: %v", err))
|
|
}
|
|
defer conn.Close()
|
|
|
|
tconn := textproto.NewConn(conn)
|
|
defer tconn.Close()
|
|
|
|
scanner := bufio.NewScanner(bytes.NewBuffer(data))
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
cmd := strings.TrimSpace(strings.ToUpper(line))
|
|
|
|
// Skip STARTTLS if it happens on a non-TLS connection - the jump is
|
|
// not going to happen via fuzzer, it will just cause a timeout (which
|
|
// is considered a crash).
|
|
if cmd == "STARTTLS" && !mode.TLS {
|
|
continue
|
|
}
|
|
|
|
if err = tconn.PrintfLine(line); err != nil {
|
|
break
|
|
}
|
|
|
|
if _, _, err = tconn.ReadResponse(-1); err != nil {
|
|
break
|
|
}
|
|
|
|
if cmd == "DATA" {
|
|
// We just sent DATA and got a response; send the contents.
|
|
err = exchangeData(scanner, tconn)
|
|
if err != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func FuzzConnection(f *testing.F) {
|
|
f.Fuzz(fuzzConnection)
|
|
}
|
|
|
|
func exchangeData(scanner *bufio.Scanner, tconn *textproto.Conn) error {
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if err := tconn.PrintfLine(line); err != nil {
|
|
return err
|
|
}
|
|
if line == "." {
|
|
break
|
|
}
|
|
}
|
|
|
|
// Read the "." response.
|
|
_, _, err := tconn.ReadResponse(-1)
|
|
return err
|
|
}
|