Add fuzz tests, rename fuzz tests and fix panic found by fuzzing (#72)

* begin adding better fuzz test

* finish adding working fuzzer

* implement mutateipv4

* fuzzer finds a panic in ICMP client on receive empty payload

* rename fuzz tests to reflect fuzz methodology
This commit is contained in:
Pat Whittingslow
2026-04-11 11:09:51 -03:00
committed by GitHub
parent 68461b4416
commit 66a1aec593
226 changed files with 835 additions and 20 deletions
+60 -5
View File
@@ -1,7 +1,9 @@
package udp
import (
"errors"
"net"
"net/netip"
"os"
"sync"
"time"
@@ -55,29 +57,39 @@ func (conn *Conn) Configure(cfg ConnConfig) error {
func (conn *Conn) Abort() {
conn.mu.Lock()
defer conn.mu.Unlock()
conn.h.Abort()
conn.abort()
}
func (conn *Conn) abort() {
conn.h.Abort()
conn.rdead = time.Time{}
conn.wdead = time.Time{}
conn.remoteAddr = conn.remoteAddr[:0]
}
var errStillOpen = errors.New("close udp conn before opening")
// Open sets the local port and remote address for the connection.
func (conn *Conn) Open(localPort, remotePort uint16, remoteAddr []byte) error {
func (conn *Conn) Open(localPort uint16, remoteAddr netip.AddrPort) error {
conn.mu.Lock()
defer conn.mu.Unlock()
conn.abort()
err := conn.h.SetPorts(localPort, remotePort)
if conn.h.IsOpen() {
return errStillOpen
}
err := conn.h.SetPorts(localPort, remoteAddr.Port())
if err != nil {
return err
}
conn.remoteAddr = append(conn.remoteAddr[:0], remoteAddr...)
conn.remoteAddr = append(conn.remoteAddr[:0], remoteAddr.Addr().AsSlice()...)
return nil
}
func (conn *Conn) IsOpen() bool {
conn.mu.Lock()
defer conn.mu.Unlock()
return conn.h.IsOpen()
}
// LocalPort returns the local port set by [Conn.Open].
func (conn *Conn) LocalPort() uint16 {
conn.mu.Lock()
@@ -229,3 +241,46 @@ func (conn *Conn) deadlineExceeded(deadline *time.Time) bool {
defer conn.mu.Unlock()
return !deadline.IsZero() && time.Since(*deadline) > 0
}
// BufferedInput returns the number of unread bytes in the receive buffer.
func (conn *Conn) BufferedInput() int {
conn.mu.Lock()
defer conn.mu.Unlock()
return conn.h.BufferedInput()
}
// BufferedUnsent returns the number of written but unsent bytes in the transmit buffer.
func (conn *Conn) BufferedOutput() int {
conn.mu.Lock()
defer conn.mu.Unlock()
return conn.h.BufferedOutput()
}
// SizeInput returns the total size of the receive ring buffer.
func (conn *Conn) SizeInput() int {
conn.mu.Lock()
defer conn.mu.Unlock()
return conn.h.SizeInput()
}
// SizeOutput returns the total size of the transmit ring buffer.
func (conn *Conn) SizeOutput() int {
conn.mu.Lock()
defer conn.mu.Unlock()
return conn.h.SizeOutput()
}
// FreeOutput returns the number of free bytes in the transmit buffer.
// This tells the user how many bytes can be written with Write method before write failing.
func (conn *Conn) FreeOutput() int {
conn.mu.Lock()
defer conn.mu.Unlock()
return conn.h.FreeOutput()
}
// FreeInput returns the number of free bytes in the receive buffer.
func (conn *Conn) FreeInput() int {
conn.mu.Lock()
defer conn.mu.Unlock()
return conn.h.FreeInput()
}
+2 -1
View File
@@ -2,6 +2,7 @@ package udp
import (
"encoding/binary"
"net/netip"
"testing"
"github.com/soypat/lneto/internal"
@@ -29,7 +30,7 @@ func newTestConn(t *testing.T) *Conn {
if err != nil {
t.Fatal(err)
}
err = conn.Open(1234, 8080, []byte{10, 0, 0, 1})
err = conn.Open(1234, netip.AddrPortFrom(netip.AddrFrom4([4]byte{10, 0, 0, 1}), 8080))
if err != nil {
t.Fatal(err)
}
+16
View File
@@ -164,6 +164,11 @@ func (h *Handler) Read(b []byte) (int, error) {
return n, nil
}
// IsOpen returns true if the handler can send/receive data.
func (h *Handler) IsOpen() bool {
return !h.closeCalled && h.lport > 0
}
// Close closes the connection. Calls to [Handler.Send] and [Handler.Recv] will
// return [net.ErrClosed] after Close is called.
func (h *Handler) Close() {
@@ -212,3 +217,14 @@ func (h *Handler) SizeInput() int {
func (h *Handler) SizeOutput() int {
return h.txRing.Size()
}
// FreeOutput returns the number of free bytes in the transmit buffer.
// This tells the user how many bytes can be written with Write method before write failing.
func (h *Handler) FreeOutput() int {
return h.txRing.Free()
}
// FreeInput returns the number of free bytes in the receive buffer.
func (h *Handler) FreeInput() int {
return h.rxRing.Free()
}