Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,13 @@ $TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/datetime.cpp -o $OUTPUT/lib/$BUIL
$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/regex.cpp -o $OUTPUT/lib/$BUILD/$MM/regex.o
$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/thread.cpp -o $OUTPUT/lib/$BUILD/$MM/thread.o
$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/http_linux.cpp -o $OUTPUT/lib/$BUILD/$MM/http_linux.o
$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/memory.cpp -o $OUTPUT/lib/$BUILD/$MM/memory.o

$BIN_PATH/$TOOL_NAME $DBG_OPTS $MM_OPT --emit=obj --export=none --nowarn --no-default-lib $SRC/src/lib.linux.ts $PIC -o $OUTPUT/lib/$BUILD/$MM/lib.linux.o

# Build Lib
$BIN_PATH/$TOOL_NAME $DBG_OPTS $MM_OPT --emit=obj --export=none --nowarn --no-default-lib $SRC/src/lib.ts $PIC -o $OUTPUT/lib/$BUILD/$MM/lib.o
$ARC rcs $OUTPUT/lib/$BUILD/$MM/libTypeScriptDefaultLibCore.a $OUTPUT/lib/$BUILD/$MM/lib.o $OUTPUT/lib/$BUILD/$MM/lib.linux.o $OUTPUT/lib/$BUILD/$MM/io.o $OUTPUT/lib/$BUILD/$MM/datetime.o $OUTPUT/lib/$BUILD/$MM/regex.o $OUTPUT/lib/$BUILD/$MM/thread.o $OUTPUT/lib/$BUILD/$MM/http_linux.o
$ARC rcs $OUTPUT/lib/$BUILD/$MM/libTypeScriptDefaultLibCore.a $OUTPUT/lib/$BUILD/$MM/lib.o $OUTPUT/lib/$BUILD/$MM/lib.linux.o $OUTPUT/lib/$BUILD/$MM/io.o $OUTPUT/lib/$BUILD/$MM/datetime.o $OUTPUT/lib/$BUILD/$MM/regex.o $OUTPUT/lib/$BUILD/$MM/thread.o $OUTPUT/lib/$BUILD/$MM/http_linux.o $OUTPUT/lib/$BUILD/$MM/memory.o

# A static archive cannot record its own dependencies on ELF (there is no ld.bfd equivalent of
# the `#pragma comment(lib, ...)` http.cpp uses on Windows), so programs linking
Expand All @@ -93,7 +94,7 @@ EOF
# undefined on purpose: they must bind to the one collector already in the process
# (libTypeScriptRuntime.so under the JIT, libgc.a in an exe); linking libgc.a in here would
# give the library a second, separate heap.
g++ -shared $DBG_GCC $OUTPUT/lib/$BUILD/$MM/lib.o $OUTPUT/lib/$BUILD/$MM/lib.linux.o $OUTPUT/lib/$BUILD/$MM/io.o $OUTPUT/lib/$BUILD/$MM/datetime.o $OUTPUT/lib/$BUILD/$MM/regex.o $OUTPUT/lib/$BUILD/$MM/thread.o $OUTPUT/lib/$BUILD/$MM/http_linux.o -lcurl -lm -o $OUTPUT/dll/$BUILD/$MM/libTypeScriptDefaultLib.so
g++ -shared $DBG_GCC $OUTPUT/lib/$BUILD/$MM/lib.o $OUTPUT/lib/$BUILD/$MM/lib.linux.o $OUTPUT/lib/$BUILD/$MM/io.o $OUTPUT/lib/$BUILD/$MM/datetime.o $OUTPUT/lib/$BUILD/$MM/regex.o $OUTPUT/lib/$BUILD/$MM/thread.o $OUTPUT/lib/$BUILD/$MM/http_linux.o $OUTPUT/lib/$BUILD/$MM/memory.o -lcurl -lm -o $OUTPUT/dll/$BUILD/$MM/libTypeScriptDefaultLib.so

# Copy
# Stage into a single shared defaultlib tree with per-build subfolders under dll/ and lib/,
Expand Down
4 changes: 2 additions & 2 deletions scripts/build_android.bat
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ if exist "%OBJ%" rd /s /q "%OBJ%"
if exist "%LIB_OUT%" rd /s /q "%LIB_OUT%"
md "%OBJ%" "%LIB_OUT%"

for %%w in (io datetime regex thread http_stub) do (
for %%w in (io datetime regex thread http_stub memory) do (
%CXX% -c "%ROOT%\src\wrappers\%%w.cpp" -o "%OBJ%\%%w.o" || exit /b 1
)

%TSC% "%ROOT%\src\lib.linux.ts" -o "%OBJ%\lib.linux.o" || exit /b 1
%TSC% "%ROOT%\src\lib.ts" -o "%OBJ%\lib.o" || exit /b 1

set OBJS="%OBJ%\lib.o" "%OBJ%\lib.linux.o" "%OBJ%\io.o" "%OBJ%\datetime.o" "%OBJ%\regex.o" "%OBJ%\thread.o" "%OBJ%\http_stub.o"
set OBJS="%OBJ%\lib.o" "%OBJ%\lib.linux.o" "%OBJ%\io.o" "%OBJ%\datetime.o" "%OBJ%\regex.o" "%OBJ%\thread.o" "%OBJ%\http_stub.o" "%OBJ%\memory.o"
%AR% rcs "%LIB_OUT%\libTypeScriptDefaultLib.a" %OBJS% || exit /b 1

rd /s /q "%OBJ%"
Expand Down
6 changes: 4 additions & 2 deletions scripts/build_core.bat
Original file line number Diff line number Diff line change
Expand Up @@ -205,22 +205,23 @@ rem Build native wrappers for C++ code
%TSLANG_CC% %DBG_CL% /EHsc /Wall /c /Fo%OUTPUT%\%LIB_OUT%\ %SRC%\src\wrappers\regex.cpp
%TSLANG_CC% %DBG_CL% /EHsc /Wall /c /Fo%OUTPUT%\%LIB_OUT%\ %SRC%\src\wrappers\thread.cpp
%TSLANG_CC% %DBG_CL% /EHsc /Wall /c /Fo%OUTPUT%\%LIB_OUT%\ %SRC%\src\wrappers\http.cpp
%TSLANG_CC% %DBG_CL% /EHsc /Wall /c /Fo%OUTPUT%\%LIB_OUT%\ %SRC%\src\wrappers\memory.cpp

rem Build OS-specific Lib
echo Build OS-specific Lib
%TOOL_PATH%\%TOOL_NAME%.exe %TRIPLE_OPT% %DBG% %MM_OPT% --emit=obj --export=none --nowarn --no-default-lib %SRC%\src\lib.win32.ts -o %OUTPUT%\%LIB_OUT%\lib.win32.obj

rem Build DLL
echo Build DLL
%TOOL_PATH%\%TOOL_NAME%.exe %TRIPLE_OPT% %DBG% %MM_OPT% --emit=dll --gc-lib-path=%GC_SHARED_LIB_PATH% %TSLANG_RUNTIME_OPT% --embed-declarations=false --nowarn --no-default-lib %SRC%\src\lib.ts --obj=%OUTPUT%\%LIB_OUT%\lib.win32.obj --obj=%OUTPUT%\%LIB_OUT%\io.obj --obj=%OUTPUT%\%LIB_OUT%\datetime.obj --obj=%OUTPUT%\%LIB_OUT%\regex.obj --obj=%OUTPUT%\%LIB_OUT%\thread.obj --obj=%OUTPUT%\%LIB_OUT%\http.obj -o %OUTPUT%\%DLL_OUT%\TypeScriptDefaultLib.dll
%TOOL_PATH%\%TOOL_NAME%.exe %TRIPLE_OPT% %DBG% %MM_OPT% --emit=dll --gc-lib-path=%GC_SHARED_LIB_PATH% %TSLANG_RUNTIME_OPT% --embed-declarations=false --nowarn --no-default-lib %SRC%\src\lib.ts --obj=%OUTPUT%\%LIB_OUT%\lib.win32.obj --obj=%OUTPUT%\%LIB_OUT%\io.obj --obj=%OUTPUT%\%LIB_OUT%\datetime.obj --obj=%OUTPUT%\%LIB_OUT%\regex.obj --obj=%OUTPUT%\%LIB_OUT%\thread.obj --obj=%OUTPUT%\%LIB_OUT%\http.obj --obj=%OUTPUT%\%LIB_OUT%\memory.obj -o %OUTPUT%\%DLL_OUT%\TypeScriptDefaultLib.dll

rem Build Lib
echo Build Lib
%TOOL_PATH%\%TOOL_NAME%.exe %TRIPLE_OPT% %DBG% %MM_OPT% --emit=obj --export=none --nowarn --no-default-lib %SRC%\src\lib.ts -o %OUTPUT%\%LIB_OUT%\lib.obj
rem %TOOL_PATH%\%TOOL_NAME%.exe %TRIPLE_OPT% %DBG% %MM_OPT% --emit=llvm --export=none %SRC%\src\lib.ts -o %OUTPUT%\%LIB_OUT%\lib.ll
rem %TOOL_PATH%\%TOOL_NAME%.exe %TRIPLE_OPT% %DBG% %MM_OPT% --emit=mlir --export=none %SRC%\src\lib.ts 2> %OUTPUT%\%LIB_OUT%\lib.mlir

%TSLANG_AR% /out:%OUTPUT%\%LIB_OUT%\TypeScriptDefaultLib.lib %OUTPUT%\%LIB_OUT%\lib.obj %OUTPUT%\%LIB_OUT%\lib.win32.obj %OUTPUT%\%LIB_OUT%\io.obj %OUTPUT%\%LIB_OUT%\datetime.obj %OUTPUT%\%LIB_OUT%\regex.obj %OUTPUT%\%LIB_OUT%\thread.obj %OUTPUT%\%LIB_OUT%\http.obj
%TSLANG_AR% /out:%OUTPUT%\%LIB_OUT%\TypeScriptDefaultLib.lib %OUTPUT%\%LIB_OUT%\lib.obj %OUTPUT%\%LIB_OUT%\lib.win32.obj %OUTPUT%\%LIB_OUT%\io.obj %OUTPUT%\%LIB_OUT%\datetime.obj %OUTPUT%\%LIB_OUT%\regex.obj %OUTPUT%\%LIB_OUT%\thread.obj %OUTPUT%\%LIB_OUT%\http.obj %OUTPUT%\%LIB_OUT%\memory.obj

del %OUTPUT%\%LIB_OUT%\lib.obj
del %OUTPUT%\%LIB_OUT%\lib.win32.obj
Expand All @@ -229,6 +230,7 @@ del %OUTPUT%\%LIB_OUT%\datetime.obj
del %OUTPUT%\%LIB_OUT%\regex.obj
del %OUTPUT%\%LIB_OUT%\thread.obj
del %OUTPUT%\%LIB_OUT%\http.obj
del %OUTPUT%\%LIB_OUT%\memory.obj

rem Stage into a single shared defaultlib tree with per-build subfolders under
rem dll\ and lib\. Only the current build's subfolders are refreshed so the
Expand Down
14 changes: 7 additions & 7 deletions src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ export class RegExp
// get formatted replacement
const len = r.length;
let result = "".clone().resize(len);
memcpy(Ref(result[0]), r, len);
boundedCopy(Ref(result[0]), len, r, len);

regexp_free_string(r);
regexp_free(cmatch);
Expand All @@ -592,7 +592,7 @@ export class RegExp
const r = regexp_replace(this.source, this.flags, s, replacement);
const len = r.length;
let result = "".clone().resize(len);
memcpy(Ref(result[0]), r, len);
boundedCopy(Ref(result[0]), len, r, len);
regexp_free_string(r);
return result;
}
Expand Down Expand Up @@ -655,7 +655,7 @@ namespace __String {
const newString = this.clone().resize(count);
let index = this.length;
for (const item of other) {
memcpy(Ref(newString[index]), Ref(item[0]), sizeof<char>() * item.length);
boundedCopy(Ref(newString[index]), sizeof<char>() * (count - index), Ref(item[0]), sizeof<char>() * item.length);
index += item.length;
}

Expand All @@ -670,7 +670,7 @@ namespace __String {
const newString = "".clone().resize(count);
let index = 0;
for (const item of parts) {
memcpy(Ref(newString[index]), Ref(item[0]), sizeof<char>() * item.length);
boundedCopy(Ref(newString[index]), sizeof<char>() * (count - index), Ref(item[0]), sizeof<char>() * item.length);
index += item.length;
}

Expand Down Expand Up @@ -881,7 +881,7 @@ namespace __String {
// the clone holds the first copy already: count - 1 more fill the string, and one more
// wrote past its end
for (let i = 1; i < count; i++) {
memcpy(Ref(newString[index]), this, byteSize);
boundedCopy(Ref(newString[index]), sizeof<char>() * (newSize - index), this, byteSize);
index += this.length;
}

Expand Down Expand Up @@ -980,7 +980,7 @@ namespace __String {

const count = indexEnd - indexStart;
const newString = "".clone().resize(count);
memcpy(Ref(newString[0]), Ref(this[indexStart]), sizeof<char>() * count);
boundedCopy(Ref(newString[0]), sizeof<char>() * count, Ref(this[indexStart]), sizeof<char>() * count);
return newString;
}

Expand Down Expand Up @@ -1075,7 +1075,7 @@ namespace __String {

const count = indexEnd - indexStart;
const newString = "".clone().resize(count);
memcpy(Ref(newString[0]), Ref(this[indexStart]), sizeof<char>() * count);
boundedCopy(Ref(newString[0]), sizeof<char>() * count, Ref(this[indexStart]), sizeof<char>() * count);
return newString;
}

Expand Down
3 changes: 3 additions & 0 deletions src/native/lib.native.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ declare function trunc(x: number): number;
// memory
declare function memcpy(dest: Opaque, src: Opaque, bytes: index): Opaque;
declare function memmove(dest: Opaque, src: Opaque, bytes: index): Opaque;
// wrappers/memory.cpp: memcpy_s on Windows, __memcpy_chk elsewhere - ends the process rather
// than copy more than `destSize` bytes
declare function boundedCopy(dest: Opaque, destSize: index, src: Opaque, count: index): void;
declare function memcmp(dest: Opaque, src: Opaque, bytes: index): int;

// gc weak references
Expand Down
22 changes: 22 additions & 0 deletions src/wrappers/memory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <cstddef>
#include <cstring>

#include "tslang_export.h"

// A copy of `count` bytes into `dest`, which has `destSize` bytes left, that ends the process
// rather than write past them. Windows has the CRT's memcpy_s: its invalid parameter handler ends
// the process. glibc and Bionic have no memcpy_s, but have the fortified copy _FORTIFY_SOURCE
// uses, which aborts with "buffer overflow detected"; the builtin calls it, or a plain memcpy
// where the compiler can prove the copy fits.
//
// In C++, not in lib.win32.ts / lib.linux.ts: the compiler emits memcpy_s / __memcpy_chk for
// copies of its own, and a TypeScript declaration of the same function in a module that makes such
// a copy before the declaration is lowered is a second definition of the symbol.
extern "C" TSLANG_EXPORT void boundedCopy(void *dest, size_t destSize, const void *src, size_t count)
{
#ifdef _WIN32
memcpy_s(dest, destSize, src, count);
#else
__builtin___memcpy_chk(dest, src, count, destSize);
#endif
}
8 changes: 8 additions & 0 deletions src/wrappers/regex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ extern "C" TSLANG_EXPORT char* regexp_match_results_format(std::cmatch *cm, cons
std::allocator<char> alloc;
char* buffer = alloc.allocate(len + 1);

#ifdef _WIN32
memcpy_s(buffer, len + 1, result.c_str(), len);
#else
std::memcpy(buffer, result.c_str(), len);
#endif

buffer[len] = 0;

Expand Down Expand Up @@ -114,7 +118,11 @@ extern "C" TSLANG_EXPORT char* regexp_replace(const char *expr, const char *flag
std::allocator<char> alloc;
char* buffer = alloc.allocate(len + 1);

#ifdef _WIN32
memcpy_s(buffer, len + 1, result.c_str(), len);
#else
std::memcpy(buffer, result.c_str(), len);
#endif

buffer[len] = 0;

Expand Down