Don't use mimalloc with ASAN

This commit is contained in:
Kai Tamkun
2025-08-06 14:16:21 -07:00
parent 86aac268c2
commit 658406129a
11 changed files with 92 additions and 37 deletions

View File

@@ -12,12 +12,6 @@ pub fn load() void {
boring.SSL_load_error_strings();
boring.ERR_load_BIO_strings();
boring.OpenSSL_add_all_algorithms();
if (!builtin.is_test) {
std.mem.doNotOptimizeAway(&OPENSSL_memory_alloc);
std.mem.doNotOptimizeAway(&OPENSSL_memory_get_size);
std.mem.doNotOptimizeAway(&OPENSSL_memory_free);
}
}
var ctx_store: ?*boring.SSL_CTX = null;
@@ -58,19 +52,29 @@ pub fn initClient() *boring.SSL {
// into the process, including pthreads locks. Failing to meet these constraints
// may result in deadlocks, crashes, or memory corruption.
export fn OPENSSL_memory_alloc(size: usize) ?*anyopaque {
return bun.mimalloc.mi_malloc(size);
}
comptime {
if (bun.use_mimalloc) {
@export(&struct {
pub fn alloc(size: usize) callconv(.C) ?*anyopaque {
return bun.mimalloc.mi_malloc(size);
}
}.alloc, .{ .name = "OPENSSL_memory_alloc" });
// BoringSSL always expects memory to be zero'd
export fn OPENSSL_memory_free(ptr: *anyopaque) void {
const len = bun.mimalloc.mi_usable_size(ptr);
@memset(@as([*]u8, @ptrCast(ptr))[0..len], 0);
bun.mimalloc.mi_free(ptr);
}
// BoringSSL always expects memory to be zero'd
@export(&struct {
pub fn free(ptr: *anyopaque) callconv(.C) void {
const len = bun.mimalloc.mi_usable_size(ptr);
@memset(@as([*]u8, @ptrCast(ptr))[0..len], 0);
bun.mimalloc.mi_free(ptr);
}
}.free, .{ .name = "OPENSSL_memory_free" });
export fn OPENSSL_memory_get_size(ptr: ?*const anyopaque) usize {
return bun.mimalloc.mi_usable_size(ptr);
@export(&struct {
pub fn get_size(ptr: ?*const anyopaque) callconv(.C) usize {
return bun.mimalloc.mi_usable_size(ptr);
}
}.get_size, .{ .name = "OPENSSL_memory_get_size" });
}
}
const INET6_ADDRSTRLEN = if (bun.Environment.isWindows) 65 else 46;

View File

@@ -19,7 +19,11 @@ pub const BrotliAllocator = struct {
return;
}
mimalloc.mi_free(data);
if (comptime bun.use_mimalloc) {
mimalloc.mi_free(data);
} else {
std.c.free(data);
}
}
};

View File

@@ -1468,8 +1468,11 @@ pub const JSZlib = struct {
reader.deinit();
}
export fn global_deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
comptime assert(bun.use_mimalloc);
bun.mimalloc.mi_free(ctx);
if (bun.use_mimalloc) {
bun.mimalloc.mi_free(ctx);
} else {
std.c.free(ctx);
}
}
export fn compressor_deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
var compressor: *zlib.ZlibCompressorArrayList = bun.cast(*zlib.ZlibCompressorArrayList, ctx.?);
@@ -1752,11 +1755,6 @@ pub const JSZlib = struct {
};
pub const JSZstd = struct {
export fn deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
comptime assert(bun.use_mimalloc);
bun.mimalloc.mi_free(ctx);
}
inline fn getOptions(globalThis: *JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!struct { jsc.Node.StringOrBuffer, ?JSValue } {
const arguments = callframe.arguments();
const buffer_value: JSValue = if (arguments.len > 0) arguments[0] else .js_undefined;

View File

@@ -440,7 +440,11 @@ pub const MatchedRoute = struct {
}
if (this.needs_deinit) {
if (this.route.pathname.len > 0 and bun.mimalloc.mi_is_in_heap_region(this.route.pathname.ptr)) {
bun.mimalloc.mi_free(@constCast(this.route.pathname.ptr));
if (comptime bun.use_mimalloc) {
bun.mimalloc.mi_free(@constCast(this.route.pathname.ptr));
} else {
std.c.free(@constCast(this.route.pathname.ptr));
}
}
this.params_list_holder.deinit(bun.default_allocator);

View File

@@ -714,7 +714,12 @@ extern "C" BunString BunString__createExternalGloballyAllocatedLatin1(
{
ASSERT(length > 0);
Ref<WTF::ExternalStringImpl> impl = WTF::ExternalStringImpl::create({ bytes, length }, nullptr, [](void*, void* ptr, size_t) {
#if __has_feature(address_sanitizer)
// mimalloc is disabled in ASAN builds
free(ptr);
#else
mi_free(ptr);
#endif
});
return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } };
}
@@ -725,7 +730,12 @@ extern "C" BunString BunString__createExternalGloballyAllocatedUTF16(
{
ASSERT(length > 0);
Ref<WTF::ExternalStringImpl> impl = WTF::ExternalStringImpl::create({ bytes, length }, nullptr, [](void*, void* ptr, size_t) {
#if __has_feature(address_sanitizer)
// mimalloc is disabled in ASAN builds
free(ptr);
#else
mi_free(ptr);
#endif
});
return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } };
}

View File

@@ -12,7 +12,12 @@ extern "C" JSC::EncodedJSValue JSUint8Array__fromDefaultAllocator(JSC::JSGlobalO
if (length > 0) [[likely]] {
auto buffer = ArrayBuffer::createFromBytes({ ptr, length }, createSharedTask<void(void*)>([](void* p) {
#if __has_feature(address_sanitizer)
// mimalloc is disabled in ASAN builds
free(p);
#else
mi_free(p);
#endif
}));
uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructureWithTypedArrayType<JSC::TypeUint8>(), WTFMove(buffer), 0, length);
@@ -30,7 +35,12 @@ extern "C" JSC::EncodedJSValue JSArrayBuffer__fromDefaultAllocator(JSC::JSGlobal
if (length > 0) [[likely]] {
buffer = ArrayBuffer::createFromBytes({ ptr, length }, createSharedTask<void(void*)>([](void* p) {
#if __has_feature(address_sanitizer)
// mimalloc is disabled in ASAN builds
free(p);
#else
mi_free(p);
#endif
}));
} else {
buffer = ArrayBuffer::create(0, 1);

View File

@@ -94,7 +94,12 @@ Ref<SourceProvider> SourceProvider::create(
const auto getProvider = [&]() -> Ref<SourceProvider> {
if (resolvedSource.bytecode_cache != nullptr) {
const auto destructorPtr = [](const void* ptr) {
#if __has_feature(address_sanitizer)
// mimalloc is disabled in ASAN builds
free(const_cast<void*>(ptr));
#else
mi_free(const_cast<void*>(ptr));
#endif
};
const auto destructorNoOp = [](const void* ptr) {
// no-op, for bun build --compile.

View File

@@ -743,7 +743,7 @@ pub const ZigString = extern struct {
}
inline fn assertGlobal(this: *const ZigString) void {
if (comptime bun.Environment.allow_assert) {
if (comptime bun.Environment.allow_assert and bun.use_mimalloc) {
bun.assert(this.len == 0 or
bun.mimalloc.mi_is_in_heap_region(untagged(this._unsafe_ptr_do_not_use)) or
bun.mimalloc.mi_check_owned(untagged(this._unsafe_ptr_do_not_use)));
@@ -852,7 +852,7 @@ pub const StringPointer = struct {
export fn ZigString__free(raw: [*]const u8, len: usize, allocator_: ?*anyopaque) void {
var allocator: std.mem.Allocator = @as(*std.mem.Allocator, @ptrCast(@alignCast(allocator_ orelse return))).*;
var ptr = ZigString.init(raw[0..len]).slice().ptr;
if (comptime Environment.allow_assert) {
if (comptime Environment.allow_assert and bun.use_mimalloc) {
bun.assert(Mimalloc.mi_is_in_heap_region(ptr));
}
const str = ptr[0..len];
@@ -862,11 +862,15 @@ export fn ZigString__free(raw: [*]const u8, len: usize, allocator_: ?*anyopaque)
export fn ZigString__freeGlobal(ptr: [*]const u8, len: usize) void {
const untagged = @as(*anyopaque, @ptrFromInt(@intFromPtr(ZigString.init(ptr[0..len]).slice().ptr)));
if (comptime Environment.allow_assert) {
bun.assert(Mimalloc.mi_is_in_heap_region(ptr));
if (comptime bun.use_mimalloc) {
if (comptime Environment.allow_assert) {
bun.assert(Mimalloc.mi_is_in_heap_region(ptr));
}
// we must untag the string pointer
Mimalloc.mi_free(untagged);
} else {
std.c.free(untagged);
}
// we must untag the string pointer
Mimalloc.mi_free(untagged);
}
const string = []const u8;

View File

@@ -628,7 +628,11 @@ pub export fn MarkedArrayBuffer_deallocator(bytes_: *anyopaque, _: *anyopaque) v
// mimalloc.mi_heap_check_owned(jsc.VirtualMachine.get().arena.heap.?, bytes_));
// }
mimalloc.mi_free(bytes_);
if (comptime bun.use_mimalloc) {
mimalloc.mi_free(bytes_);
} else {
std.c.free(bytes_);
}
}
pub export fn BlobArrayBuffer_deallocator(_: *anyopaque, blob: *anyopaque) void {

View File

@@ -8,7 +8,7 @@ const bun = @This();
pub const Environment = @import("./env.zig");
pub const use_mimalloc = true;
pub const use_mimalloc = !Environment.enable_asan;
pub const default_allocator: std.mem.Allocator = if (use_mimalloc)
allocators.c_allocator

View File

@@ -136,7 +136,11 @@ pub fn NewZlibReader(comptime Writer: type, comptime buffer_size: usize) type {
}
pub fn free(_: *anyopaque, data: *anyopaque) callconv(.C) void {
mimalloc.mi_free(data);
if (comptime bun.use_mimalloc) {
mimalloc.mi_free(data);
} else {
std.c.free(data);
}
}
pub fn deinit(this: *ZlibReader) void {
@@ -310,7 +314,11 @@ const ZlibAllocator = struct {
return;
}
mimalloc.mi_free(data);
if (comptime bun.use_mimalloc) {
mimalloc.mi_free(data);
} else {
std.c.free(data);
}
}
};
@@ -757,7 +765,11 @@ pub const ZlibCompressorArrayList = struct {
}
pub fn free(_: *anyopaque, data: *anyopaque) callconv(.C) void {
mimalloc.mi_free(data);
if (comptime bun.use_mimalloc) {
mimalloc.mi_free(data);
} else {
std.c.free(data);
}
}
pub fn deinit(this: *ZlibCompressor) void {