From 2ed84ed38b1ade4ab84b704fa94b075fcfbb109e Mon Sep 17 00:00:00 2001 From: James Dansereau <106631954+jkdansereau@users.noreply.github.com> Date: Fri, 25 Sep 2026 22:30:48 -0400 Subject: [PATCH] Q7 audit fixes: missing returns in front.c menus, getenv prototype, dram.c shift UB - front.c: constructor_menu07_missionsel / constructor_menu0D_missioncomplete fall off the end while the caller uses the Gfx* result; return DL under AVOID_UB (porting-notes D6). Old/new objects disassemble identically at -O2, so no behaviour change on this compiler; clang/arm64 no longer rely on luck. - libultra/audio/event.c: include under PORT so getenv() is not an implicit int-returning declaration (D324 class). - dram.c: DRAM_SIZE >> 32 on a 32-bit unsigned long (Win64) was UB. Golden gate 3/3. --- docs/porting-notes.md | 6 ++++++ port/src/dram.c | 2 +- src/game/front.c | 14 ++++++++++++++ src/libultra/audio/event.c | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/porting-notes.md b/docs/porting-notes.md index d02db552..1ae928c1 100644 --- a/docs/porting-notes.md +++ b/docs/porting-notes.md @@ -1089,6 +1089,12 @@ silently disappears. upstream. This class isn't limited to display-list cursors; audit any `-O2`-only "quietly broken but not crashing" symptom for the same shape. Fix: `return` under `#ifdef AVOID_UB` (`#else` keeps the N64 body). +- Instances (latent, 2026-09-25 Q7 warning audit): `constructor_menu07_missionsel()` and + `constructor_menu0D_missioncomplete()` (`src/game/front.c`), both `DL = f(DL)` at the + caller. Currently harmless: old/new objects disassemble identically at `-O2` (GCC + keeps `frontDrawCursor()`'s result in `rax`), but a clang/arm64 build is not bound + by that. `return DL;` under `#ifdef AVOID_UB`. A `-Wreturn-type` sweep lists the + remaining candidates; the other 7 current hits have callers that ignore the value. - The one flagged in-source with an explicit comment is `grep -rn "missing a \"return\"" src/` (`gunfire.c`). Others (like D77's) exist without the banner; suspect this class whenever an `-O2` build diff --git a/port/src/dram.c b/port/src/dram.c index fef2b6cd..f0a5f4f4 100644 --- a/port/src/dram.c +++ b/port/src/dram.c @@ -71,7 +71,7 @@ void *dramReserve(void) sa.bInheritHandle = FALSE; HANDLE hSec = CreateFileMappingW(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, - (DWORD)(DRAM_SIZE >> 32), + (DWORD)((unsigned long long)DRAM_SIZE >> 32), (DWORD)(DRAM_SIZE & 0xFFFFFFFF), NULL); if (!hSec) { sysFatalError("dram: CreateFileMapping failed (%lu)", GetLastError()); diff --git a/src/game/front.c b/src/game/front.c index ffb62ab6..e76fcd92 100644 --- a/src/game/front.c +++ b/src/game/front.c @@ -3464,6 +3464,13 @@ Gfx *constructor_menu07_missionsel(Gfx *DL) DL = frontAddPreviousTabText(DL); DL = frontDrawCursor(DL); +#ifdef AVOID_UB + /* porting-notes D6: the decomp falls off the end of this Gfx*-returning + * function and the caller uses the result; N64 and x86-64 GCC -O2 return + * frontDrawCursor()'s result by accident of the return register (verified: + * identical machine code with and without this line). */ + return DL; +#endif } @@ -7503,6 +7510,13 @@ Gfx *constructor_menu0D_missioncomplete(Gfx *DL) DL = frontAddNextTabText(DL); DL = frontAddPreviousTabText(DL); DL = frontDrawCursor(DL); +#ifdef AVOID_UB + /* porting-notes D6: the decomp falls off the end of this Gfx*-returning + * function and the caller uses the result; N64 and x86-64 GCC -O2 return + * frontDrawCursor()'s result by accident of the return register (verified: + * identical machine code with and without this line). */ + return DL; +#endif } diff --git a/src/libultra/audio/event.c b/src/libultra/audio/event.c index ddec4090..3dbb1f70 100644 --- a/src/libultra/audio/event.c +++ b/src/libultra/audio/event.c @@ -22,6 +22,7 @@ #include #include #ifdef PORT +#include /* getenv() prototype (D324 class: no implicit int decl) */ #include "audiotrace.h" /* D202/M-71: evtq drop probe */ #endif