From ab2053c6c618ce01d7e18a5e3584cfafc6e58ab4 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sat, 30 May 2026 21:43:40 +0300 Subject: test(socketpair): lock in domain-is-not-an-fd invariant (c00) Audit of socketpair(2) found the tracing implementation already correct: KindSocketpair captures the two output fds from the sv[2] buffer (args[3]) at exit and never treats args[0] (the address-family/domain constant) as a file descriptor. Family=Network and UNCLASSIFIED ret are consistent with the socket/accept siblings and the docs. Add regression lock-in tests so a future field-shape or classification change cannot silently regress to recording the domain integer as a bogus fd: - TestClassifySocketpairNotFd: pins the name-based override so socketpair is KindSocketpair, never the generic KindFd path that reads args[0]. - TestHandleSocketpairExitDoesNotTrackDomainAsFd: uses AF_INET6 (10), distinct from the returned fds, and asserts fd 10 is never tracked while sv0/sv1 are. - TestHandleSocketpairExitDropsFdsOnError: on ret!=0 no descriptors are tracked. Co-Authored-By: Claude Opus 4.8 --- internal/generate/classify_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'internal/generate') diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go index 3053615..3be393d 100644 --- a/internal/generate/classify_test.go +++ b/internal/generate/classify_test.go @@ -843,6 +843,25 @@ func TestClassifyExitSocketpair(t *testing.T) { } } +// TestClassifySocketpairNotFd is a regression lock-in for the socketpair(2) +// audit (task c00). socketpair(int domain, int type, int protocol, int sv[2]) +// takes the address-family/domain constant as args[0] (named "family" in the +// tracepoint format), NOT a file descriptor. The created fds are written into +// the OUTPUT array sv[2] (args[3]) and are only valid after the call returns. +// socketpair must therefore be KindSocketpair (read sv[2] at exit), never +// KindFd, which would record the domain integer as a bogus fd. Pin that the +// name-based override wins so a future field-shape change cannot make it fall +// through to the generic KindFd path. +func TestClassifySocketpairNotFd(t *testing.T) { + r := classifyFromData(t, FormatSocketpair) + if r.Kind == KindFd { + t.Fatal("socketpair classified as KindFd: args[0] is the domain constant, not an fd") + } + if r.Kind != KindSocketpair { + t.Errorf("socketpair: got kind %d, want KindSocketpair", r.Kind) + } +} + func TestClassifyPipe(t *testing.T) { r := classifyFromData(t, FormatPipe) if r.Kind != KindPipe { -- cgit v1.2.3