Skip to content

Bounded copies (memcpy_s / __memcpy_chk) and strtoll/strtod parsing - #525

Merged
ASDAlexander77 merged 2 commits into
mainfrom
parse-strtol-strtod
Oct 6, 2026
Merged

ASDAlexander77 merged 2 commits into
mainfrom
parse-strtol-strtod

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Summary

Two commits:

  1. parseInt / parseFloat use strtoll / strtod, not atoi / atof. atoi and atof leave a value out of range undefined. MSVC saturated, while glibc wrapped: parseInt("3000000000") was -1294967296 on Linux. parseInt with a radix called strtol, whose long is 64 bits on Linux and was read there as a 32-bit result. Every parse now goes through strtoll (base 10 unless one is given), and a 32-bit result is clamped to the i32 range, so every target gives the same answer. The strto* functions have no _s variants in the MSVC CRT; they are its recommended replacement for ato*.

  2. Copies sized at run time are bounded. String concatenation, string copies and array slices go through LLVMCodeHelperBase::MemoryCopy(dest, destSize, src, count), which ends the process rather than write past the destination:

    • Windows target: the CRT's memcpy_s, whose invalid parameter handler fails fast (0xC0000409)
    • Linux, Android, Darwin: they have no memcpy_s, so they get the fortified __memcpy_chk ("buffer overflow detected"). LLVM turns it back into a plain memcpy where it can prove the copy fits.
    • wasm: llvm.memcpy, as before

    The JIT binds memcpy_s to tslang's own CRT, as it does memcpy. The manifest resource for a Windows executable is copied with memcpy_s on a Windows host.

The DefaultLib side (its own string copies, through a C++ boundedCopy) is ASDAlexander77/TypeScriptCompilerDefaultLib, branch memcpy-s-win32. Merge this one first, or both together.

Test plan

  • New 00parse_number_range.ts (compile, JIT, and the rc/none corpus): saturation at both ends, radix, strtod overflow and underflow, casts to i32, i64 and f32. Before the fix, the four out-of-range cases failed on Linux (WSL) and passed on Windows.
  • --emit=llvm per target: Windows has 35 memcpy_s calls, Linux and Android have 35 __memcpy_chk calls, wasm has llvm.memcpy
  • Windows Release ctest -C Release: 3904/3904
  • CI: Linux, where __memcpy_chk is exercised end to end

🤖 Generated with Claude Code

ASDAlexander77 and others added 2 commits October 6, 2026 08:31
atoi and atof leave a value out of range undefined: MSVC saturated, glibc
wrapped ("3000000000" parsed as -1294967296 on Linux). parseInt with a
radix called strtol, which returns a `long` - 64 bits on Linux, read as a
32-bit result there.

Every parse now goes through strtoll (base 10 unless one is given), whose
`long long` is 64 bits on every target, and a 32-bit result is clamped to
the i32 range, so the result is the same on every target. parseFloat and a
cast from a string to a float use strtod. The strto* functions have no _s
variants in the MSVC CRT; they are its recommended replacement for ato*.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hk elsewhere

String concatenation, string copies and array slices copied with
llvm.memcpy, trusting the count. They now go through
LLVMCodeHelperBase::MemoryCopy(dest, destSize, src, count), which ends the
process rather than write past the destination:

- a Windows target calls the CRT's memcpy_s (its invalid parameter handler
  fails fast)
- Linux, Android and Darwin, which have no memcpy_s, call the fortified
  __memcpy_chk ("buffer overflow detected"); LLVM turns it back into a
  plain memcpy where it can prove the copy fits
- wasm has neither and keeps llvm.memcpy

The JIT binds memcpy_s to tslang's own CRT, as it does memcpy. The
manifest resource tslang writes for a Windows executable is copied with
memcpy_s on a Windows host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 0a72b81 into main Oct 6, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the parse-strtol-strtod branch October 6, 2026 07:56
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.

1 participant