Version 1.2.1 - Bug Fixes

Critical (4)

C1 — udp_client.hpp / udp_client.cpp: Moved mStartReceive() out of the constructor into start(), after the socket is opened.
C2 — client/main.cpp:187: || → && in the main loop condition, so it exits when the connection drops instead of spinning forever.
C3 — tcp_connection.hpp: Added mConnectionAESKey{}, mConnectionSessionID(0), and mConnectionPublicKey{} to the constructor initializer list.
C4 — tcp_server.hpp / tcp_server.cpp: Added std::mutex mClientsMutex and locked it at all three mClients access sites (insert, erase callback, stop snapshot).
High (5)

H1 — tcp_connection.cpp:284: Replaced hardcoded htonl(0x0A0A0001) with htonl(baseIP + 1).
H2 — session_registry.hpp / session_registry.cpp / udp_server.cpp: Changed get() and getByIP() to return shared_ptr<SessionState> (non-const); removed all four const_cast usages.
H3 — session_registry.cpp:90: Guarded against mask == 0 || mask >= 32 (shift UB) and hostCount < 3 (unsigned underflow).
H4 — virtual_interface.cpp: Added runCommandWin32() using CreateProcess (no shell); replaced both system() calls in resetIP().
H5 — virtual_interface.cpp: Added close(mFd); mFd = -1; before both throw sites in the macOS constructor (ioctl failure and connect failure).
Medium (4)

M1 — tcp_connection.cpp:241: Added explicit find() + end-iterator check for NETWORK and SUBNET_MASK before dereferencing.
M2 — tcp_message_handler.cpp: Added an 8 KB (MAX_MSG_BODY = 8192) cap on incoming message body length; oversized messages close the connection.
M3 — tcp_connection.cpp:232: Capped the session ID generation loop at 16 attempts before disconnecting.
M4 — session_registry.cpp:8: put() now evicts the old IP→session mapping before replacing an entry, preventing stale mIPSessions entries.
This commit is contained in:
2026-06-14 20:02:50 +02:00
parent 05febee79e
commit 1d9e1e6165
13 changed files with 109 additions and 37 deletions

View File

@@ -40,7 +40,7 @@ namespace ColumnLynx::Net::UDP {
std::vector<uint8_t> encryptedPayload(it, mRecvBuffer.begin() + bytes);
// Get associated session state
std::shared_ptr<const SessionState> session = SessionRegistry::getInstance().get(sessionID);
std::shared_ptr<SessionState> session = SessionRegistry::getInstance().get(sessionID);
if (!session) {
Utils::warn("UDP: Unknown or invalid session from " + mRemoteEndpoint.address().to_string());
@@ -60,9 +60,9 @@ namespace ColumnLynx::Net::UDP {
Utils::debug("Passed decryption");
const_cast<SessionState*>(session.get())->setUDPEndpoint(mRemoteEndpoint); // Update endpoint after confirming decryption
session->setUDPEndpoint(mRemoteEndpoint); // Update endpoint after confirming decryption
// Update recv counter
const_cast<SessionState*>(session.get())->recv_ctr.fetch_add(1, std::memory_order_relaxed);
session->recv_ctr.fetch_add(1, std::memory_order_relaxed);
// For now, just log the decrypted payload
std::string payloadStr(plaintext.begin(), plaintext.end());
@@ -79,7 +79,7 @@ namespace ColumnLynx::Net::UDP {
void UDPServer::sendData(uint32_t sessionID, const std::string& data) {
// Find the IPv4/IPv6 endpoint for the session
std::shared_ptr<const SessionState> session = SessionRegistry::getInstance().get(sessionID);
std::shared_ptr<SessionState> session = SessionRegistry::getInstance().get(sessionID);
if (!session) {
Utils::warn("UDP: Cannot send data, unknown session ID " + std::to_string(sessionID));
return;
@@ -98,14 +98,13 @@ namespace ColumnLynx::Net::UDP {
// Increment send counter with overflow protection
uint64_t sendCount = 0;
{
auto ptr = const_cast<SessionState*>(session.get());
uint64_t old = ptr->send_ctr.load(std::memory_order_relaxed);
uint64_t old = session->send_ctr.load(std::memory_order_relaxed);
for (;;) {
if (old == std::numeric_limits<uint64_t>::max()) {
Utils::error("UDP: send counter overflow for session " + std::to_string(sessionID));
return;
}
if (ptr->send_ctr.compare_exchange_weak(old, old + 1, std::memory_order_relaxed)) {
if (session->send_ctr.compare_exchange_weak(old, old + 1, std::memory_order_relaxed)) {
sendCount = old;
break;
}