Repository navigation
Bounded copies (memcpy_s / __memcpy_chk) and strtoll/strtod parsing - #525
Merged
Merged
Conversation
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>
3 of 4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two commits:
parseInt/parseFloatusestrtoll/strtod, notatoi/atof.atoiandatofleave a value out of range undefined. MSVC saturated, while glibc wrapped:parseInt("3000000000")was -1294967296 on Linux.parseIntwith a radix calledstrtol, whoselongis 64 bits on Linux and was read there as a 32-bit result. Every parse now goes throughstrtoll(base 10 unless one is given), and a 32-bit result is clamped to the i32 range, so every target gives the same answer. Thestrto*functions have no_svariants in the MSVC CRT; they are its recommended replacement forato*.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:memcpy_s, whose invalid parameter handler fails fast (0xC0000409)memcpy_s, so they get the fortified__memcpy_chk("buffer overflow detected"). LLVM turns it back into a plainmemcpywhere it can prove the copy fits.llvm.memcpy, as beforeThe JIT binds
memcpy_sto tslang's own CRT, as it doesmemcpy. The manifest resource for a Windows executable is copied withmemcpy_son a Windows host.The DefaultLib side (its own string copies, through a C++
boundedCopy) is ASDAlexander77/TypeScriptCompilerDefaultLib, branchmemcpy-s-win32. Merge this one first, or both together.Test plan
00parse_number_range.ts(compile, JIT, and the rc/none corpus): saturation at both ends, radix,strtodoverflow 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=llvmper target: Windows has 35memcpy_scalls, Linux and Android have 35__memcpy_chkcalls, wasm hasllvm.memcpyctest -C Release: 3904/3904__memcpy_chkis exercised end to end🤖 Generated with Claude Code