From 9d2cb1188a8dc9b567dd11a47705c8c146b8a50b Mon Sep 17 00:00:00 2001 From: Amir Date: Sun, 20 Sep 2026 20:13:14 -0500 Subject: [PATCH] fix(ini): retain nested parse error details Preserve existing INI exceptions through outer parsing handlers and log numeric conversion failures without changing accepted values or recovery. Related to #297 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Core/GameEngine/Source/Common/INI/INI.cpp | 16 ++++++++++++++++ docs/WORKLOG/2026-09-DIARY.md | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp index a016d6e5bc2..5113b0fde68 100644 --- a/Core/GameEngine/Source/Common/INI/INI.cpp +++ b/Core/GameEngine/Source/Common/INI/INI.cpp @@ -442,6 +442,9 @@ UnsignedInt INI::load( AsciiString filename, INILoadType loadType, Xfer *pXfer ) try { (*parse)( this ); + // GeneralsX @bugfix Copilot 20/09/2026 Preserve the innermost INI field diagnostic. + } catch (const INIException&) { + throw; } catch (...) { DEBUG_CRASH(("Error parsing block '%s' in INI file '%s'", token, m_filename.str()) ); char buff[1024]; @@ -1585,6 +1588,9 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList (*parse)( this, what, (char *)what + offset + parseTableList.getNthExtraOffset(ptIdx), userData ); + // GeneralsX @bugfix Copilot 20/09/2026 Do not replace nested field errors with an enclosing module. + } catch (const INIException&) { + throw; } catch (...) { DEBUG_CRASH( ("[LINE: %d - FILE: '%s'] Error reading field '%s' of block '%s'", INI::getLineNum(), INI::getFilename().str(), field, m_curBlockStart) ); @@ -1683,6 +1689,11 @@ Type scanType(std::string_view token) if (ec != std::errc{}) { + // GeneralsX @bugfix Copilot 20/09/2026 Keep numeric conversion failures visible in release builds. + fprintf(stderr, "[INI] Cannot parse numeric token '%.*s': %s\n", + static_cast(token.size()), token.data(), + ec == std::errc::result_out_of_range ? "out of range" : "invalid number"); + fflush(stderr); throw INI_INVALID_DATA; } @@ -1696,6 +1707,11 @@ Type scanType(std::string_view token) if (ec != std::errc{}) { + // GeneralsX @bugfix Copilot 20/09/2026 Identify overflowing mod values without changing their interpretation. + fprintf(stderr, "[INI] Cannot parse numeric token '%.*s': %s\n", + static_cast(token.size()), token.data(), + ec == std::errc::result_out_of_range ? "out of range" : "invalid number"); + fflush(stderr); throw INI_INVALID_DATA; } diff --git a/docs/WORKLOG/2026-09-DIARY.md b/docs/WORKLOG/2026-09-DIARY.md index 422ce4cabe7..e4459ee3b42 100644 --- a/docs/WORKLOG/2026-09-DIARY.md +++ b/docs/WORKLOG/2026-09-DIARY.md @@ -3,6 +3,14 @@ > [!NOTE] > **AI-Generated Content Disclosure**: This worklog is automatically generated and maintained by AI coding agents to document daily progress, debugging sessions, and technical decisions. +## 20/09/2026 +### Preserve Nested INI Error Details (#297) +- Kept an existing `INIException` intact when it passes through nested module and outer-block handlers, rather than replacing the useful field/file/line details with an enclosing `Object` header. +- Added release-visible numeric conversion diagnostics for `std::from_chars` failures, including the token and whether it is invalid or out of range. Parsing rules and failure behavior are unchanged. +- The supplied Shockwave INIs contain delay values beyond the signed 64-bit intermediate used by the Linux unsigned-number parser. These are concrete rejection points, not proof of the first failure in the reporter's complete mod installation; this is a diagnostics fix, not a compatibility fix. +- Exercised parser-function extracts with both game variants' exception headers, both numeric parsing paths, and address/undefined-behavior sanitizers. The baseline lost nested context; the patch retained it without changing valid/sentinel/suffix handling or cleanup. +- Syntax-checked the actual patched INI.cpp with each game's generated native macOS compiler configuration. No full mod run or installed-game changes were made. + ## 19/09/2026 ### Fix NGMP Statistics Synchronization & Session Token Expiry Handling - **Context**: Welcome screen (`WOLWelcomeMenu`) statistics ("Players online", Daily Stats "Wins/Losses 0% (0/0)", and personal player stats) were not reflecting real-time game activity or active matches. Investigation traced three root causes: