From d7bcd641302408f3c2c765c7e676a4f1437d61bb Mon Sep 17 00:00:00 2001 From: DcruBro Date: Sun, 16 Aug 2026 23:15:57 +0200 Subject: [PATCH] Fix analyzer conflicts --- src/main.c | 11 ++++++++--- src/tcpd/tcpserver.c | 13 +++++++++++++ src/udpd/udpnode.c | 11 +++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index 5020097..1ec0ec1 100644 --- a/src/main.c +++ b/src/main.c @@ -1390,9 +1390,14 @@ int main(int argc, char* argv[]) { uint64_t nextReq = start; const int maxInFlight = MAX_PARALLEL_FETCHES; - uint64_t requestedHeights[64]; - int retryCount[64]; - uint64_t sentAtMs[64]; + // Zeroed so a slot is never read before it is written. Slots below + // inFlight are always initialized by the fill loop, but that is a + // loop invariant -fanalyzer cannot prove, and an explicit + // initializer is cheaper than teaching it (one memset per sync + // command) and survives future changes to the fill logic. + uint64_t requestedHeights[64] = {0}; + int retryCount[64] = {0}; + uint64_t sentAtMs[64] = {0}; int inFlight = 0; if (maxInFlight > (int)(sizeof(requestedHeights)/sizeof(requestedHeights[0]))) { diff --git a/src/tcpd/tcpserver.c b/src/tcpd/tcpserver.c index e614a4c..8645c3a 100644 --- a/src/tcpd/tcpserver.c +++ b/src/tcpd/tcpserver.c @@ -238,6 +238,16 @@ void TcpServer_Destroy(tcp_server_t* ptr) { free(ptr); } +// Both sockets are handed to the caller through ptr->sockFd / ptr->sockFdV4 and +// closed by TcpServer_Stop, so neither leaks. -fanalyzer loses track of the +// first store across the second socket's branches and reports it anyway; the +// report is positional, not semantic — swapping the IPv6 and IPv4 blocks moves +// the warning from fd6 to fd4, and deleting the unrelated second block silences +// it entirely. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-fd-leak" +#endif void TcpServer_Init(tcp_server_t* ptr, unsigned short port, const char* addr) { if (!ptr || !addr) { return; @@ -285,6 +295,9 @@ void TcpServer_Init(tcp_server_t* ptr, unsigned short port, const char* addr) { } } } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif // Same borrowed-fd false positive as TcpServer_threadprocess: listen() teaches // -fanalyzer that ptr->sockFd / ptr->sockFdV4 are open passive sockets, so it diff --git a/src/udpd/udpnode.c b/src/udpd/udpnode.c index 37fd8ed..45e632f 100644 --- a/src/udpd/udpnode.c +++ b/src/udpd/udpnode.c @@ -181,6 +181,14 @@ static void* UdpNode_RetryThreadProc(void* arg) { return NULL; } +// Same borrowed/escaped-fd false positive as TcpServer_Init: both sockets are +// handed to the caller through node->sockFd / node->sockFdV4 and closed by +// UdpNode_Stop. -fanalyzer loses the first store across the second socket's +// branches and reports it as a leak. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-fd-leak" +#endif int UdpNode_Init(udp_node_t* node, uint16_t port) { if (!node) { return -1; @@ -237,6 +245,9 @@ int UdpNode_Init(udp_node_t* node, uint16_t port) { pthread_mutex_init(&node->pingsMutex, NULL); return 0; } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif void UdpNode_SetCallbacks(udp_node_t* node, void (*on_pong)(udp_node_t*, const struct sockaddr_storage*, uint64_t, int, uint64_t, void*),