koffi 2.2.2 → 2.2.3-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/src/koffi/build/2.2.3-beta.2/koffi_darwin_arm64.tar.gz +0 -0
  3. package/src/koffi/build/2.2.3-beta.2/koffi_darwin_x64.tar.gz +0 -0
  4. package/src/koffi/build/2.2.3-beta.2/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/src/koffi/build/2.2.3-beta.2/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/src/koffi/build/2.2.3-beta.2/koffi_freebsd_x64.tar.gz +0 -0
  7. package/src/koffi/build/2.2.3-beta.2/koffi_linux_arm32hf.tar.gz +0 -0
  8. package/src/koffi/build/2.2.3-beta.2/koffi_linux_arm64.tar.gz +0 -0
  9. package/src/koffi/build/2.2.3-beta.2/koffi_linux_ia32.tar.gz +0 -0
  10. package/src/koffi/build/2.2.3-beta.2/koffi_linux_riscv64hf64.tar.gz +0 -0
  11. package/src/koffi/build/2.2.3-beta.2/koffi_linux_x64.tar.gz +0 -0
  12. package/src/koffi/build/2.2.3-beta.2/koffi_openbsd_ia32.tar.gz +0 -0
  13. package/src/koffi/build/2.2.3-beta.2/koffi_openbsd_x64.tar.gz +0 -0
  14. package/src/koffi/build/2.2.3-beta.2/koffi_win32_arm64.tar.gz +0 -0
  15. package/src/koffi/build/2.2.3-beta.2/koffi_win32_ia32.tar.gz +0 -0
  16. package/src/koffi/build/2.2.3-beta.2/koffi_win32_x64.tar.gz +0 -0
  17. package/src/koffi/src/abi_x64_win.cc +35 -0
  18. package/src/koffi/src/abi_x86.cc +42 -1
  19. package/src/koffi/src/ffi.cc +73 -4
  20. package/src/koffi/src/ffi.hh +10 -0
  21. package/vendor/miniz/ChangeLog.md +4 -0
  22. package/vendor/miniz/miniz.c +1 -1
  23. package/vendor/miniz/miniz.h +3 -3
  24. package/src/koffi/build/2.2.2/koffi_darwin_arm64.tar.gz +0 -0
  25. package/src/koffi/build/2.2.2/koffi_darwin_x64.tar.gz +0 -0
  26. package/src/koffi/build/2.2.2/koffi_freebsd_arm64.tar.gz +0 -0
  27. package/src/koffi/build/2.2.2/koffi_freebsd_ia32.tar.gz +0 -0
  28. package/src/koffi/build/2.2.2/koffi_freebsd_x64.tar.gz +0 -0
  29. package/src/koffi/build/2.2.2/koffi_linux_arm32hf.tar.gz +0 -0
  30. package/src/koffi/build/2.2.2/koffi_linux_arm64.tar.gz +0 -0
  31. package/src/koffi/build/2.2.2/koffi_linux_ia32.tar.gz +0 -0
  32. package/src/koffi/build/2.2.2/koffi_linux_riscv64hf64.tar.gz +0 -0
  33. package/src/koffi/build/2.2.2/koffi_linux_x64.tar.gz +0 -0
  34. package/src/koffi/build/2.2.2/koffi_openbsd_ia32.tar.gz +0 -0
  35. package/src/koffi/build/2.2.2/koffi_openbsd_x64.tar.gz +0 -0
  36. package/src/koffi/build/2.2.2/koffi_win32_arm64.tar.gz +0 -0
  37. package/src/koffi/build/2.2.2/koffi_win32_ia32.tar.gz +0 -0
  38. package/src/koffi/build/2.2.2/koffi_win32_x64.tar.gz +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.2.2",
3
+ "version": "2.2.3-beta.2",
4
4
  "stable": "2.2.2",
5
5
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
6
  "keywords": [
@@ -40,6 +40,10 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
40
40
 
41
41
  #include "abi_trampolines.inc"
42
42
 
43
+ #define TEB_STACK_BASE(TEB) (*(void **)((uint8_t *)(TEB) + 0x08))
44
+ #define TEB_STACK_LIMIT(TEB) (*(void **)((uint8_t *)(TEB) + 0x10))
45
+ #define TEB_DEALLOCATION_STACK(TEB) (*(void **)((uint8_t *)(TEB) + 0x1478))
46
+
43
47
  bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
44
48
  {
45
49
  func->ret.regular = IsRegularSize(func->ret.type->size, 8);
@@ -216,6 +220,22 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
216
220
 
217
221
  void CallData::Execute(const FunctionInfo *func)
218
222
  {
223
+ void *teb = (void *)__readgsqword(0x30);
224
+
225
+ // Store current stack limits
226
+ RG_DEFER_C(base = TEB_STACK_BASE(teb),
227
+ limit = TEB_STACK_LIMIT(teb),
228
+ dealloc = TEB_DEALLOCATION_STACK(teb)) {
229
+ TEB_STACK_BASE(teb) = base;
230
+ TEB_STACK_LIMIT(teb) = limit;
231
+ TEB_DEALLOCATION_STACK(teb) = dealloc;
232
+ };
233
+
234
+ // Adjust stack limits so SEH works correctly
235
+ TEB_STACK_BASE(teb) = mem->stack0.end();
236
+ TEB_STACK_LIMIT(teb) = mem->stack0.ptr;
237
+ TEB_DEALLOCATION_STACK(teb) = mem->stack0.ptr;
238
+
219
239
  #define PERFORM_CALL(Suffix) \
220
240
  ([&]() { \
221
241
  auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, new_sp, &old_sp) \
@@ -317,6 +337,21 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
317
337
  if (RG_UNLIKELY(env.IsExceptionPending()))
318
338
  return;
319
339
 
340
+ void *teb = (void *)__readgsqword(0x30);
341
+
342
+ RG_DEFER_C(base = TEB_STACK_BASE(teb),
343
+ limit = TEB_STACK_LIMIT(teb),
344
+ dealloc = TEB_DEALLOCATION_STACK(teb)) {
345
+ TEB_STACK_BASE(teb) = base;
346
+ TEB_STACK_LIMIT(teb) = limit;
347
+ TEB_DEALLOCATION_STACK(teb) = dealloc;
348
+ };
349
+
350
+ // Restore real thread stack limits
351
+ TEB_STACK_BASE(teb) = instance->main_stack_max;
352
+ TEB_STACK_LIMIT(teb) = instance->main_stack_min;
353
+ TEB_DEALLOCATION_STACK(teb) = instance->main_stack_min;
354
+
320
355
  const TrampolineInfo &trampoline = shared.trampolines[idx];
321
356
 
322
357
  const FunctionInfo *proto = trampoline.proto;
@@ -46,6 +46,12 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
46
46
 
47
47
  #include "abi_trampolines.inc"
48
48
 
49
+ #ifdef _WIN32
50
+ #define TEB_STACK_BASE(TEB) (*(void **)((uint8_t *)(TEB) + 0x04))
51
+ #define TEB_STACK_LIMIT(TEB) (*(void **)((uint8_t *)(TEB) + 0x08))
52
+ #define TEB_DEALLOCATION_STACK(TEB) (*(void **)((uint8_t *)(TEB) + 0xE0C))
53
+ #endif
54
+
49
55
  bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
50
56
  {
51
57
  if (!func->lib && func->convention != CallConvention::Cdecl &&
@@ -297,6 +303,24 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
297
303
 
298
304
  void CallData::Execute(const FunctionInfo *func)
299
305
  {
306
+ #ifdef _WIN32
307
+ void *teb = (void *)__readfsdword(0x18);
308
+
309
+ // Store current stack limits
310
+ RG_DEFER_C(base = TEB_STACK_BASE(teb),
311
+ limit = TEB_STACK_LIMIT(teb),
312
+ dealloc = TEB_DEALLOCATION_STACK(teb)) {
313
+ TEB_STACK_BASE(teb) = base;
314
+ TEB_STACK_LIMIT(teb) = limit;
315
+ TEB_DEALLOCATION_STACK(teb) = dealloc;
316
+ };
317
+
318
+ // Adjust stack limits so SEH works correctly
319
+ TEB_STACK_BASE(teb) = mem->stack0.end();
320
+ TEB_STACK_LIMIT(teb) = mem->stack0.ptr;
321
+ TEB_DEALLOCATION_STACK(teb) = mem->stack0.ptr;
322
+ #endif
323
+
300
324
  #define PERFORM_CALL(Suffix) \
301
325
  ([&]() { \
302
326
  auto ret = (func->fast ? ForwardCallR ## Suffix(func->func, new_sp, &old_sp) \
@@ -394,11 +418,28 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
394
418
  RG_UNREACHABLE();
395
419
  }
396
420
 
397
- void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async, BackRegisters *out_reg)
421
+ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool async, BackRegisters *out_reg)
398
422
  {
399
423
  if (RG_UNLIKELY(env.IsExceptionPending()))
400
424
  return;
401
425
 
426
+ #ifdef _WIN32
427
+ void *teb = (void *)__readfsdword(0x18);
428
+
429
+ RG_DEFER_C(base = TEB_STACK_BASE(teb),
430
+ limit = TEB_STACK_LIMIT(teb),
431
+ dealloc = TEB_DEALLOCATION_STACK(teb)) {
432
+ TEB_STACK_BASE(teb) = base;
433
+ TEB_STACK_LIMIT(teb) = limit;
434
+ TEB_DEALLOCATION_STACK(teb) = dealloc;
435
+ };
436
+
437
+ // Restore real thread stack limits
438
+ TEB_STACK_BASE(teb) = instance->main_stack_max;
439
+ TEB_STACK_LIMIT(teb) = instance->main_stack_min;
440
+ TEB_DEALLOCATION_STACK(teb) = instance->main_stack_min;
441
+ #endif
442
+
402
443
  const TrampolineInfo &trampoline = shared.trampolines[idx];
403
444
 
404
445
  const FunctionInfo *proto = trampoline.proto;
@@ -1014,13 +1014,66 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
1014
1014
  return nullptr;
1015
1015
 
1016
1016
  InstanceMemory *mem = new InstanceMemory();
1017
+ RG_DEFER_N(mem_guard) { delete mem; };
1017
1018
 
1018
- mem->stack.len = stack_size;
1019
1019
  #if defined(_WIN32)
1020
- mem->stack.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->stack.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
1020
+ {
1021
+ struct FiberContext {
1022
+ InstanceMemory *mem;
1023
+ void *self;
1024
+ bool was_fiber;
1025
+ };
1026
+
1027
+ FiberContext ctx;
1028
+ bool is_fiber = IsThreadAFiber();
1029
+
1030
+ ctx.mem = mem;
1031
+ ctx.self = is_fiber ? GetCurrentFiber() : ConvertThreadToFiber(nullptr);
1032
+ if (!ctx.self) {
1033
+ LogError("Failed to make initial fiber: %1", GetWin32ErrorString());
1034
+ return nullptr;
1035
+ }
1036
+ RG_DEFER {
1037
+ if (!is_fiber) {
1038
+ ConvertFiberToThread();
1039
+ }
1040
+ };
1041
+
1042
+ // Work around issue with CreateFiber() API and stack size
1043
+ // See here: https://github.com/google/marl/issues/12
1044
+ mem->fiber = CreateFiberEx(stack_size - 1, stack_size,
1045
+ FIBER_FLAG_FLOAT_SWITCH, [](void *udata) {
1046
+ FiberContext *ctx = (FiberContext *)udata;
1047
+
1048
+ // Handle initial call just below
1049
+ #if defined(__aarch64__) || defined(_M_ARM64)
1050
+ NT_TIB *tib = (NT_TIB *)__getReg(18);
1051
+ #elif defined(__x86_64__) || defined(_M_AMD64)
1052
+ NT_TIB *tib = (NT_TIB *)__readgsqword(0x30);
1053
+ #else
1054
+ NT_TIB *tib = (NT_TIB *)__readfsdword(0x18);
1055
+ #endif
1056
+
1057
+ ctx->mem->stack.ptr = (uint8_t *)tib->StackLimit;
1058
+ ctx->mem->stack.len = (uint8_t *)tib->StackBase - ctx->mem->stack.ptr;
1059
+
1060
+ SwitchToFiber(ctx->self);
1061
+ }, &ctx);
1062
+
1063
+ if (!mem->fiber) {
1064
+ LogError("Failed to create Win32 fiber: %1", GetWin32ErrorString());
1065
+ return nullptr;
1066
+ }
1067
+
1068
+ SwitchToFiber(mem->fiber);
1069
+ }
1070
+
1071
+ RG_ASSERT(mem->stack.ptr);
1021
1072
  #elif defined(__APPLE__)
1073
+ mem->stack.len = stack_size;
1022
1074
  mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1023
1075
  #else
1076
+ mem->stack.len = stack_size;
1024
1077
  mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
1025
1078
  #endif
1026
1079
  RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
@@ -1030,6 +1083,9 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
1030
1083
  mem->stack.len -= 16;
1031
1084
  #endif
1032
1085
 
1086
+ // Keep real stack limits intact, in case we need them
1087
+ mem->stack0 = mem->stack;
1088
+
1033
1089
  mem->heap.len = heap_size;
1034
1090
  #ifdef _WIN32
1035
1091
  mem->heap.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->heap.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
@@ -1048,6 +1104,7 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
1048
1104
  mem->temporary = true;
1049
1105
  }
1050
1106
 
1107
+ mem_guard.Disable();
1051
1108
  return mem;
1052
1109
  }
1053
1110
 
@@ -1688,8 +1745,8 @@ void FunctionInfo::Unref() const
1688
1745
  InstanceMemory::~InstanceMemory()
1689
1746
  {
1690
1747
  #ifdef _WIN32
1691
- if (stack.ptr) {
1692
- VirtualFree(stack.ptr, 0, MEM_RELEASE);
1748
+ if (fiber) {
1749
+ DeleteFiber(fiber);
1693
1750
  }
1694
1751
  if (heap.ptr) {
1695
1752
  VirtualFree(heap.ptr, 0, MEM_RELEASE);
@@ -1929,6 +1986,18 @@ static InstanceData *CreateInstance(Napi::Env env)
1929
1986
  }
1930
1987
  napi_unref_threadsafe_function(env, instance->broker);
1931
1988
 
1989
+ #if defined(_WIN32) && (defined(__x86_64__) || defined(_M_AMD64))
1990
+ void *teb = (void *)__readgsqword(0x30);
1991
+
1992
+ instance->main_stack_max = *(void **)((uint8_t *)teb + 0x08); // StackBase
1993
+ instance->main_stack_min = *(void **)((uint8_t *)teb + 0x1478); // DeallocationStack
1994
+ #elif defined(_WIN32) && (defined(__i386__) || defined(_M_IX86))
1995
+ void *teb = (void *)__readfsdword(0x18);
1996
+
1997
+ instance->main_stack_max = *(void **)((uint8_t *)teb + 0x04); // StackBase
1998
+ instance->main_stack_min = *(void **)((uint8_t *)teb + 0xE0C); // DeallocationStack
1999
+ #endif
2000
+
1932
2001
  err_guard.Disable();
1933
2002
  return instance;
1934
2003
  }
@@ -225,12 +225,17 @@ struct InstanceMemory {
225
225
  ~InstanceMemory();
226
226
 
227
227
  Span<uint8_t> stack;
228
+ Span<uint8_t> stack0;
228
229
  Span<uint8_t> heap;
229
230
 
230
231
  uint16_t generation; // Can wrap without risk
231
232
 
232
233
  int16_t depth;
233
234
  bool temporary;
235
+
236
+ #ifdef _WIN32
237
+ void *fiber;
238
+ #endif
234
239
  };
235
240
 
236
241
  struct InstanceData {
@@ -254,6 +259,11 @@ struct InstanceData {
254
259
  std::thread::id main_thread_id;
255
260
  napi_threadsafe_function broker = nullptr;
256
261
 
262
+ #ifdef _WIN32
263
+ void *main_stack_max;
264
+ void *main_stack_min;
265
+ #endif
266
+
257
267
  HashMap<void *, int16_t> trampolines_map;
258
268
 
259
269
  BlockAllocator str_alloc;
@@ -1,5 +1,9 @@
1
1
  ## Changelog
2
2
 
3
+ ### 3.0.2
4
+
5
+ - Fix buffer overrun in mz_utf8z_to_widechar on Windows
6
+
3
7
  ### 3.0.1
4
8
 
5
9
  - Fix compilation error with MINIZ_USE_UNALIGNED_LOADS_AND_STORES=1
@@ -3068,7 +3068,7 @@ static WCHAR* mz_utf8z_to_widechar(const char* str)
3068
3068
  {
3069
3069
  int reqChars = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
3070
3070
  WCHAR* wStr = (WCHAR*)malloc(reqChars * sizeof(WCHAR));
3071
- MultiByteToWideChar(CP_UTF8, 0, str, -1, wStr, sizeof(WCHAR) * reqChars);
3071
+ MultiByteToWideChar(CP_UTF8, 0, str, -1, wStr, reqChars);
3072
3072
  return wStr;
3073
3073
  }
3074
3074
 
@@ -275,10 +275,10 @@ enum
275
275
  MZ_DEFAULT_COMPRESSION = -1
276
276
  };
277
277
 
278
- #define MZ_VERSION "11.0.1"
279
- #define MZ_VERNUM 0xB001
278
+ #define MZ_VERSION "11.0.2"
279
+ #define MZ_VERNUM 0xB002
280
280
  #define MZ_VER_MAJOR 11
281
- #define MZ_VER_MINOR 1
281
+ #define MZ_VER_MINOR 2
282
282
  #define MZ_VER_REVISION 0
283
283
  #define MZ_VER_SUBREVISION 0
284
284