Skip to content

fix: Windows bsdsocket bugs and consolidate platform-independent code#1793

Merged
midwan merged 2 commits intoBlitterStudio:masterfrom
tbdye:fix/windows-bsdsocket-shared-refactor
Feb 18, 2026
Merged

fix: Windows bsdsocket bugs and consolidate platform-independent code#1793
midwan merged 2 commits intoBlitterStudio:masterfrom
tbdye:fix/windows-bsdsocket-shared-refactor

Conversation

@tbdye
Copy link
Contributor

@tbdye tbdye commented Feb 17, 2026

Summary

PRs #1787-#1792 fixed 24 bugs in the POSIX bsdsocket emulation path. Three of those bugs also exist in the Windows #ifdef _WIN32 code path, which shares a common WinUAE heritage but has diverged over time. This PR fixes the Windows copies of those bugs and addresses the root cause of the divergence: six functions that were duplicated identically between the Windows and POSIX sections are consolidated into shared platform-independent code in bsdsocket.cpp.

The duplication is what allowed these bugs to drift between platforms in the first place. getservbyport byte order and gethostname write-back were fixed in the POSIX path (PR #1791) but the Windows copies remained broken. By moving platform-independent logic to shared code, future fixes apply to both platforms automatically.

These issues were identified by cross-referencing the fixes from PRs #1787-#1792 against the Windows code path using bsdsocktest, a conformance test suite for Amiga bsdsocket.library.

Bug A: getservbyport byte order (Windows)

The problem

The Amiga passes the port number in network byte order (big-endian) via register D0. The host getservbyport() expects its port argument in network byte order, but on a little-endian host, the raw 32-bit register value has the wrong byte order. For example, port 21 (0x0015) arrives as 0x00150000, so getservbyport() looks up port 5376 instead.

This was fixed in the POSIX path in PR #1791 (test 94) but the Windows copy at line 2304 was not updated.

The fix

Add htons((unsigned short)nameport) to convert the register value to the host's network byte order, matching the POSIX fix.

Bug B: Dup2Socket out-of-bounds memory access (Windows)

The problem

Two sub-bugs in the Windows host_dup2socket():

  1. Missing return after bounds check: When fd2 exceeds dtablesize, the function sets errno to EBADF but execution falls through to setsd() with the out-of-range descriptor, corrupting memory beyond the descriptor table.

  2. Unchecked getsd() return: When fd2 == -1 (allocate new slot), getsd() returns -1 if the descriptor table is full. The unchecked return passes -1 to setsd(ctx, sb, -1, s1), which accesses dtable[-2] -- an out-of-bounds write.

These were fixed in the POSIX path in PR #1791 (test 116). The Windows version additionally lacks a proper dup() equivalent -- two descriptor table entries alias the same SOCKET handle, so closing one invalidates the other. The correct Windows fix requires WSADuplicateSocket() + WSASocket(), but this is a pre-existing WinUAE design choice and out of scope for this change (documented with a TODO).

The fix

Add return -1 after the bounds-check errno, and add a fd2 == -1 guard after getsd(). This prevents the crashes while preserving the existing handle-aliasing behavior.

Refactor: consolidate platform-independent functions

The problem

Six functions existed as near-identical copies in both the #ifdef _WIN32 and #else sections of bsdsocket_host.cpp. This duplication meant that bug fixes applied to one platform didn't automatically reach the other, which is exactly how Bugs A and B (and the gethostname write-back bug below) persisted in the Windows path after the POSIX fixes landed.

What moved

Function Notes
host_Inet_LnaOf Pure classful IP arithmetic on uae_u32. Byte-for-byte identical across platforms.
host_Inet_NetOf Same -- no system calls, no platform types.
host_Inet_MakeAddr Same.
host_inet_addr Calls inet_addr() (available via <winsock2.h> on Windows, <arpa/inet.h> on POSIX). Windows version's BSDTRACE call preserved.
host_Inet_NtoA Merged from both versions: uses trap_get_areg(ctx, 6) (modern trap-safe API from Windows version) and bsdsocklib_seterrno(ctx, sb, 22) instead of the platform-specific SETERRNO macro.
host_gethostname Uses the correct POSIX implementation that calls gethostname() then writes the result back to Amiga memory via trap_put_string(). This simultaneously fixes the Windows bug where the function read FROM Amiga memory but never wrote the hostname back (PR #1791 test 98 fix, Windows copy not updated).

All six functions now live in bsdsocket.cpp inside the existing #ifdef BSDSOCKET block. A #ifndef _WIN32 / #include <arpa/inet.h> / #endif guard provides the necessary prototypes on POSIX; Windows gets them via <winsock2.h>.

The #include <arpa/inet.h> transitively pulls in <sys/socket.h> on Linux, which defines MSG_EOR and MSG_TRUNC with different values than the Amiga equivalents. Added #undef for both before the Amiga #defines to prevent redefinition warnings.

Cleanup

Removed the dead host_inet_network declaration from bsdsocket.h. This function was declared but never implemented in either platform section. The dispatch in bsdsocket.cpp calls host_inet_addr() instead.

Pre-existing issues documented

Added TODO comments to four additional unchecked getsd() call sites (2 Windows, 2 POSIX) that have the same out-of-bounds access pattern as Bug B. These exist in host_socket() and host_accept() on both platforms and should be addressed in a follow-up.

Validation

Linux (Debian 13, kernel 6.12, x86_64):

  • Build: clean, zero warnings
  • bsdsocktest 0.2.3 regression (142 tests, with host helper): 139 passed, 0 failed, 0 known, 3 skipped -- identical to the post-PR fix: close event monitor race in bsdsocket emulation #1792 baseline
  • The 3 skips are environmental (test 34: host send buffer >1MB; tests 101/102: no /etc/networks database)

Windows:

  • Not tested locally (no Windows build environment). The bug fixes and shared function moves affect code paths that are either Windows-only (#ifdef _WIN32) or shared. CI will verify compilation. For runtime validation, bsdsocktest 0.2.3 can be used to exercise the affected test cases (particularly tests 94, 98, 115-116).

Files changed

  • src/bsdsocket.cpp -- 109 insertions (include guard, 6 shared functions)
  • src/include/bsdsocket.h -- 1 deletion (dead host_inet_network declaration)
  • src/osdep/bsdsocket_host.cpp -- 22 insertions, 182 deletions (2 bug fixes, 6 function removals from both sections, 4 TODO comments)

Three bugs in the Windows bsdsocket emulation path and one dead
declaration are fixed, and six functions duplicated identically
between the Windows and POSIX sections are consolidated into shared
platform-independent code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tbdye tbdye requested a review from midwan as a code owner February 17, 2026 00:16
@tbdye tbdye changed the title fix: fix Windows bsdsocket bugs and consolidate platform-independent code fix: Windows bsdsocket bugs and consolidate platform-independent code Feb 17, 2026
@midwan midwan enabled auto-merge (squash) February 17, 2026 06:29
@tbdye
Copy link
Contributor Author

tbdye commented Feb 18, 2026

@midwan it looks like the MacOS cert issue is now blocking, or this needs your help to complete.

@midwan midwan disabled auto-merge February 18, 2026 03:43
@midwan midwan merged commit 30af676 into BlitterStudio:master Feb 18, 2026
14 checks passed
@tbdye tbdye deleted the fix/windows-bsdsocket-shared-refactor branch February 18, 2026 04:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants