Skip to content

String copies are bounded: memcpy_s on Windows, __memcpy_chk on Linux and Android - #29

Merged
ASDAlexander77 merged 1 commit into
mainfrom
memcpy-s-win32
Oct 6, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
memcpy-s-win32

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Summary

lib.ts copied string bytes with memcpy, trusting each count. Every copy (concat, join, repeat, slice, substring, RegExp.replace, replaceAll) now goes through boundedCopy(dest, destSize, src, count), which ends the process rather than write past the destination:

  • Windows: the CRT's memcpy_s. Its invalid parameter handler fails fast (0xC0000409).
  • Linux and Android: glibc's and Bionic's fortified __memcpy_chk ("buffer overflow detected"), through __builtin___memcpy_chk. The compiler turns it back into a plain memcpy where it can prove the copy fits.

boundedCopy is a C++ wrapper (src/wrappers/memory.cpp, platform chosen by #ifdef), declared in lib.native.d.ts. It is not TypeScript in lib.win32.ts / lib.linux.ts: with ASDAlexander77/TypeScriptCompiler#525 the compiler emits memcpy_s / __memcpy_chk for copies of its own. Under -mm=rc, lib.win32.ts made such a copy before a TypeScript declare function memcpy_s further down was lowered, and the module failed with "redefinition of symbol named 'memcpy_s'".

memory.cpp is added to build_core.bat, build.sh and build_android.bat. The two copies in regex.cpp use memcpy_s on Windows too.

Works with the current compiler, but merge after ASDAlexander77/TypeScriptCompiler#525 (or together) so the compiler's own copies are bounded as well.

Test plan

  • Windows release, compiled and JIT: gc 162/162; rc and none 161/162 (one gc-only skip)
  • Windows: boundedCopy with a count one byte too large exits 0xC0000409; a copy that fits succeeds
  • WSL: memory.cpp built with g++ links __memcpy_chk; one byte too many aborts with "buffer overflow detected"
  • Linux build.sh and Android build_android.bat: only checked by reading them, not run. This repo has no PR CI; they first run in the release workflow.

🤖 Generated with Claude Code

… and Android

lib.ts copied string bytes with memcpy, trusting each count. Every copy now
goes through boundedCopy(dest, destSize, src, count), which ends the process
rather than write past the destination:

- Windows: the CRT's memcpy_s (its invalid parameter handler fails fast,
  0xC0000409)
- Linux and Android: glibc's and Bionic's fortified __memcpy_chk ("buffer
  overflow detected"), through __builtin___memcpy_chk, which the compiler
  turns back into a plain memcpy where it can prove the copy fits

boundedCopy is a C++ wrapper (src/wrappers/memory.cpp, chosen by #ifdef),
not TypeScript in lib.win32.ts / lib.linux.ts. The compiler now emits
memcpy_s / __memcpy_chk for string copies of its own. Under -mm=rc,
lib.win32.ts made such a copy before a TypeScript declaration of memcpy_s
further down was lowered, and the module failed with "redefinition of
symbol named 'memcpy_s'". memory.cpp is added to build_core.bat, build.sh
and build_android.bat.

regex.cpp's two copies out of std::string use memcpy_s on Windows too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit d7866bb into main Oct 6, 2026
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