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 75102100de9..73312cdbbba 100644 --- a/docs/WORKLOG/2026-09-DIARY.md +++ b/docs/WORKLOG/2026-09-DIARY.md @@ -10,6 +10,13 @@ - This addresses the misleading wording only; it does not explain or suppress the reported frame-zero divergence. The original replay and, if applicable, its custom map are still needed to investigate that. - Compiled both affected Recorder.cpp objects with the native macOS configuration and checked the diff for whitespace errors. No installed game or user settings were changed. +### 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: