Files
chasquid/internal/smtpsrv/fuzz_test.go
Alberto Bertogli 5c2566c9b1 Fix non-constant format string in calls to Printf-like functions
In a few places, we call Printf-like functions, but for the format we
use either non-format messages (which is not tidy, but okay), or
variable messages (which can be problematic if they contain %-format
directives).

The patch fixes the calls by either moving to Print-like functions, or
using `Printf("%s", message)` instead.

These were found by a combination of `go vet` (which complains about
"non-constant format string in call"), and manual inspection.
2025-10-24 12:34:58 +01:00

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("%s", 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("%s", line); err != nil {
return err
}
if line == "." {
break
}
}
// Read the "." response.
_, _, err := tconn.ReadResponse(-1)
return err
}