Skip to content

fix(libc): return 64-bit values from _Stoul on Windows - #2442

Closed
SurajKhanna wants to merge 1 commit into
boykopovar:mainfrom
SurajKhanna:fix/libc-stoul-windows-truncation
Closed

SurajKhanna wants to merge 1 commit into
boykopovar:mainfrom
SurajKhanna:fix/libc-stoul-windows-truncation

Conversation

@SurajKhanna

Copy link
Copy Markdown

What

_Stoul_nid_postfix in RuntimeSupport.cpp was declared returning unsigned long and delegating to std::strtoul. On the PS5 (LP64), unsigned long is 64-bit, but on Windows (LLP64), unsigned long and std::strtoul are 32-bit. On Windows host builds, inputs exceeding UINT32_MAX (4294967295) were clamped to UINT32_MAX and set errno to ERANGE (34), which causes guest std::stoul calls to throw std::out_of_range on values the console accepts.

Fixes this by:

  • Updating _Stoul_nid_postfix return type to std::uint64_t and delegating to std::strtoull (matching strtoul_nid_postfix in Strings.cpp).
  • Adding regression test cases in GuestMath.cpp verifying parsing of 64-bit values (4294967296 and 18446744073709551615) without truncation or setting ERANGE.

Fixes #2424.

Tested

Windows 11, GCC 16.2.0 (UCRT64):

  • Direct probe verifying _Stoul_nid_postfix parses 64-bit values up to UINT64_MAX without setting ERANGE.
  • Unit test suite (guest_math_tests).

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

_Stoul_nid_postfix was declared returning unsigned long and calling
std::strtoul. On the PS5 (LP64), unsigned long is 64-bit, whereas on
Windows (LLP64), both the return type and std::strtoul are 32-bit.
On Windows builds, values exceeding UINT32_MAX were clamped to 32 bits
with errno set to ERANGE (34), causing guest std::stoul to throw
std::out_of_range on inputs accepted on the console.

Declare _Stoul_nid_postfix returning std::uint64_t and call
std::strtoull, matching strtoul_nid_postfix in Strings.cpp. Add
regression tests in GuestMath.cpp.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@github-actions github-actions Bot added the intake paused Closed while PR intake is limited to authors with at least 10 PRs merged into main label Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Thank you for your interest in the project! We are sorry, but we cannot accept more PRs while we work through the existing backlog. This PR has been automatically closed and labeled "intake paused". This is not a judgment of the quality of your changes.

@github-actions github-actions Bot closed this Oct 9, 2026
nauroth pushed a commit to nauroth/AnyPS5 that referenced this pull request Oct 9, 2026
The guest's unsigned long is 64 bits. _Stoul was declared with the
host's unsigned long and returned std::strtoul, which are 32 bits on
Windows (LLP64): "4294967296" clamped to 4294967295 with ERANGE and
"-1" gave 0xffffffff, so a guest std::stoul threw out_of_range on values
the console accepts. It now returns std::uint64_t from std::strtoull,
as strtoul_nid_postfix and _Stoull already do; on Linux nothing changes.
The binary-prefix check stays in front of the host call.

Reported in boykopovar#2424 by AchrafReyani; the same change was proposed in boykopovar#2442
by SurajKhanna, whose two guest_math cases are taken here, with the "-1"
case from boykopovar#1579 by ewraj. Folded in at MarcZX100's suggestion on boykopovar#1459.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
nauroth pushed a commit to nauroth/AnyPS5 that referenced this pull request Oct 9, 2026
The guest's unsigned long is 64 bits. _Stoul was declared with the
host's unsigned long and returned std::strtoul, which are 32 bits on
Windows (LLP64): "4294967296" clamped to 4294967295 with ERANGE and
"-1" gave 0xffffffff, so a guest std::stoul threw out_of_range on values
the console accepts. It now returns std::uint64_t from std::strtoull,
as strtoul_nid_postfix and _Stoull already do; on Linux nothing changes.
The binary-prefix check stays in front of the host call.

Reported in boykopovar#2424 by AchrafReyani; the same change was proposed in boykopovar#2442
by SurajKhanna, whose two guest_math cases are taken here. Folded in at
MarcZX100's suggestion on boykopovar#1459.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@nauroth

nauroth commented Oct 9, 2026

Copy link
Copy Markdown

Thanks @SurajKhanna, the fix was right and the intake pause was just unlucky timing. Rather than let it sit, I've carried it into #1459, which already changes the same function: same std::uint64_t + std::strtoull, and your two guest_math cases exactly as you wrote them, with you credited in the commit message. Thanks also to @MarcZX100 for pointing me to it and @AchrafReyani for the report in #2424.

SleglJan pushed a commit to SleglJan/AnyPS5 that referenced this pull request Oct 10, 2026
The guest's unsigned long is 64 bits. _Stoul was declared with the
host's unsigned long and returned std::strtoul, which are 32 bits on
Windows (LLP64): "4294967296" clamped to 4294967295 with ERANGE and
"-1" gave 0xffffffff, so a guest std::stoul threw out_of_range on values
the console accepts. It now returns std::uint64_t from std::strtoull,
as strtoul_nid_postfix and _Stoull already do; on Linux nothing changes.
The binary-prefix check stays in front of the host call.

Reported in boykopovar#2424 by AchrafReyani; the same change was proposed in boykopovar#2442
by SurajKhanna, whose two guest_math cases are taken here. Folded in at
MarcZX100's suggestion on boykopovar#1459.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

intake paused Closed while PR intake is limited to authors with at least 10 PRs merged into main

Projects

None yet

Development

Successfully merging this pull request may close these issues.

_Stoul truncates to 32 bits on Windows (unsigned long is 32-bit there)

2 participants