Skip to content

Commit

Permalink
asan tester
Browse files Browse the repository at this point in the history
  • Loading branch information
pfgithub committed Feb 5, 2025
1 parent 8521a03 commit a0dbe9e
Showing 1 changed file with 129 additions and 2 deletions.
131 changes: 129 additions & 2 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,137 @@ comptime {
bun.assert(builtin.target.cpu.arch.endian() == .little);
}

const asan_example = struct {
//! By convention, main.zig is where your main function lives in the case that
//! you are building an executable. If you are making a library, the convention
//! is to delete this file and start with root.zig instead.

pub fn main() !void {
const args = try std.process.argsAlloc(std.heap.c_allocator);
defer std.process.argsFree(std.heap.c_allocator, args);
const arg: []const u8 = if (args.len < 2) "" else args[1];
if (std.mem.eql(u8, arg, "ok")) {
try demoOk();
} else if (std.mem.eql(u8, arg, "read-after-free")) {
try demoReadAfterFree();
} else if (std.mem.eql(u8, arg, "write-after-free")) {
try demoWriteAfterFree();
} else if (std.mem.eql(u8, arg, "read-out-of-bounds")) {
try demoReadOutOfBounds();
} else if (std.mem.eql(u8, arg, "write-out-of-bounds")) {
try demoWriteOutOfBounds();
} else if (std.mem.eql(u8, arg, "read-stack-after-return")) {
std.log.info("note: requires execution with `ASAN_OPTIONS=detect_stack_use_after_return=1`", .{});
try demoReadStackAfterReturn();
} else if (std.mem.eql(u8, arg, "write-stack-after-return")) {
std.log.info("note: requires execution with `ASAN_OPTIONS=detect_stack_use_after_return=1`", .{});
try demoWriteStackAfterReturn();
} else if (std.mem.eql(u8, arg, "leak")) {
try demoLeak();
} else if (std.mem.eql(u8, arg, "gpa")) {
try demoGpa();
} else {
std.log.info(
\\Unknown argument: {s}
\\
\\Available arguments:
\\ ok
\\ read-after-free
\\ write-after-free
\\ read-out-of-bounds
\\ write-out-of-bounds
\\ read-stack-after-return
\\ write-stack-after-return
\\ gpa
\\ leak
, .{arg});
}
}

fn demoOk() !void {
const gpa = bun.default_allocator;
const v_nonvolatile: *i32 = try gpa.create(i32);
const v: *volatile i32 = v_nonvolatile;
v.* = 5;
gpa.destroy(v_nonvolatile);
}

fn demoReadAfterFree() !void {
const gpa = bun.default_allocator;
const v_nonvolatile: *i32 = try gpa.create(i32);
const v: *volatile i32 = v_nonvolatile;
v.* = 5;
gpa.destroy(v_nonvolatile);
_ = v.*;
}

fn demoWriteAfterFree() !void {
const gpa = bun.default_allocator;
const v_nonvolatile: *i32 = try gpa.create(i32);
const v: *volatile i32 = v_nonvolatile;
v.* = 5;
gpa.destroy(v_nonvolatile);
v.* = 6;
}

fn demoReadOutOfBounds() !void {
const gpa = bun.default_allocator;
const arr_nonvolatile: []i32 = try gpa.alloc(i32, 1);
const arr: []volatile i32 = arr_nonvolatile;
defer gpa.free(arr_nonvolatile);

_ = arr.ptr[2];
}

fn demoWriteOutOfBounds() !void {
const gpa = bun.default_allocator;
const arr_nonvolatile: []i32 = try gpa.alloc(i32, 1);
const arr: []volatile i32 = arr_nonvolatile;
defer gpa.free(arr_nonvolatile);

arr.ptr[2] = 42;
}

fn getStackPointer() *volatile i32 {
var x: i32 = 42;
return &x;
}

fn demoReadStackAfterReturn() !void {
const ptr = getStackPointer();
_ = ptr.*;
}

fn demoWriteStackAfterReturn() !void {
const ptr = getStackPointer();
ptr.* = 100;
}

fn demoLeak() !void {
// https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer
var ptr: ?*i32 = try bun.default_allocator.create(i32);
ptr = null;
return;
}

fn demoGpa() !void {
// demo showing gpa does not catch the out of bounds write
var gpa_backing = std.heap.GeneralPurposeAllocator(.{}).init;
const gpa = gpa_backing.allocator();
const v = try gpa.alloc(i32, 1);
const arr: []volatile i32 = v;
arr.ptr[2] = 5;
gpa.free(v);
}
};

extern fn bun_warn_avx_missing(url: [*:0]const u8) void;
pub extern "c" var _environ: ?*anyopaque;
pub extern "c" var environ: ?*anyopaque;
pub extern "C" var _environ: ?*anyopaque;
pub extern "C" var environ: ?*anyopaque;
pub fn main() void {
const cond: ?[]const u8 = std.process.getEnvVarOwned(bun.default_allocator, "BUN_ASAN_TEST") catch null;
if (cond != null) return asan_example.main() catch |e| std.log.err("err: {s}", .{@errorName(e)});

bun.crash_handler.init();

if (Environment.isPosix) {
Expand Down

0 comments on commit a0dbe9e

Please sign in to comment.