Skip to content

TSLANG_ISSUES 6: a string returned by C is copied - #575

Merged
ASDAlexander77 merged 1 commit into
mainfrom
copy-c-strings
Oct 13, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
copy-c-strings

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

TSLANG_ISSUES.md 6: a string returned by C was C's char* itself.

It was worse than stale text:

  • a buffer C reuses changed under the program: a = strerror(2); b = strerror(13) printed the second text twice;
  • under -mm=rc the reference count lives in the 8 bytes before a string, so retaining C's pointer wrote into memory that isn't the program's. Storing strchr(base, 'k') turned abcdefghijklmnop1 into abddefghijklmnop1, then abedefghijklmnop1; a release reaching zero would free C's pointer.

Change: the result of a call into C, meaning a top-level declare function that nothing in the program defines or a @cpp method (ts.cpp_call), goes through ts.StringCopy. Null stays null, and the copy is owned like any fresh string (markFreshBlockOwned). Declaring the result Opaque gives the raw pointer, for pointer arithmetic or for a string the caller must free. A function in a declare namespace or declare class, as DefaultLib's lib.d.ts declares its methods, is TypeScript and isn't copied.

Merge order: DefaultLib must merge first: ASDAlexander77/TypeScriptCompilerDefaultLib#33. It declares strstr, setlocale, regexp_* and the C time functions Opaque (int for the two that return errno_t). DefaultLib built from older sources with this compiler would break indexOf and RegExp.replace.

Verified:

  • test 00c_string_copy.ts fails on alpha100 under gc and rc, and passes under gc, rc, own and none;
  • --verify-ownership is silent under rc and own;
  • 9M copies in a loop stay flat at ~500 KB private memory under rc and own;
  • DefaultLib built with this compiler: gc 163/163, rc 162/163 (1 gc-only skip);
  • full Release suite 4080/4080.

Known extra cost: DefaultLib's own TypeScript helpers declared top-level in core.os.d.ts (convertNumber, time_*) are in a separately compiled object, so lib.ts copies their results once more (toFixed, Date strings).

Follow-ups, not in this PR:

  • string parameters of @cpp methods that C++ calls (the method has ts.cpp_method): copying needs a release at function exit under rc;
  • string fields of C structs can't be told apart from TypeScript tuples.

Docs: docs/c-cpp-header-import.md and docs/cpp-classes.md; TSLANG_ISSUES.md row and section 6.

🤖 Generated with Claude Code

A `string` result of a C function (a top-level `declare function` with no
definition in the program) or of a @cpp method was C's `char*` itself:
a buffer C may reuse (`strerror(2)` read the next call's text) or the
middle of another string (`strstr`). Under -mm=rc the reference count
lives in the 8 bytes before a string, so retaining it wrote into memory
that isn't the program's: storing `strchr(base, 'k')` rewrote two
characters of `base`, and a release reaching zero would free C's pointer.

The call's result now goes through ts.StringCopy (null stays null), owned
like any fresh string. `Opaque` is the way to get the pointer itself. A
function in a `declare namespace` or `declare class` (the default
library's lib.d.ts) is TypeScript and isn't copied.

TSLANG_ISSUES.md 6. Needs TypeScriptCompilerDefaultLib#33, which declares strstr,
setlocale, regexp_* and the C time functions `Opaque` (or `int`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit d784e54 into main Oct 13, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the copy-c-strings branch October 13, 2026 18:36
ASDAlexander77 added a commit that referenced this pull request Oct 17, 2026
All 19 issues are fixed on main; the section of fixes after pre-alpha97
is no longer headed "Open".

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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