aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-05-13 00:00:20 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-05-13 14:03:20 -0700
commit66f3efb63b4b352b1dbbaa4216fb3b0dabac3f3e (patch)
tree5a5613dc1f64234b122883ae518ce970e5da8cec /test
parentf32928c50dabde1dee40b7137beef0fe72e89b49 (diff)
downloadzig-66f3efb63b4b352b1dbbaa4216fb3b0dabac3f3e.tar.gz
zig-66f3efb63b4b352b1dbbaa4216fb3b0dabac3f3e.zip
migrate runtime safety tests to the new test harness
* migrate runtime safety tests to the new test harness - this required adding compare output / execution support for stage1 to the test harness. * rename `zig build test-stage2` to `zig build test-cases` since it now does quite a bit of stage1 testing actually. I named it this way since the main directory in the source tree associated with these tests is "test/cases/". * add some documentation for the test manifest format.
Diffstat (limited to 'test')
-rw-r--r--test/cases/README.md61
-rw-r--r--test/cases/safety/@alignCast misaligned.zig21
-rw-r--r--test/cases/safety/@asyncCall with too small a frame.zig19
-rw-r--r--test/cases/safety/@errSetCast error not present in destination.zig18
-rw-r--r--test/cases/safety/@floatToInt cannot fit - negative out of range.zig17
-rw-r--r--test/cases/safety/@floatToInt cannot fit - negative to unsigned.zig17
-rw-r--r--test/cases/safety/@floatToInt cannot fit - positive out of range.zig17
-rw-r--r--test/cases/safety/@intCast to u0.zig19
-rw-r--r--test/cases/safety/@intToEnum - no matching tag value.zig22
-rw-r--r--test/cases/safety/@intToPtr address zero to non-optional byte-aligned pointer.zig15
-rw-r--r--test/cases/safety/@intToPtr address zero to non-optional pointer.zig15
-rw-r--r--test/cases/safety/@tagName on corrupted enum value.zig24
-rw-r--r--test/cases/safety/@tagName on corrupted union value.zig25
-rw-r--r--test/cases/safety/array slice sentinel mismatch.zig18
-rw-r--r--test/cases/safety/awaiting twice.zig28
-rw-r--r--test/cases/safety/bad union field access.zig24
-rw-r--r--test/cases/safety/calling panic.zig15
-rw-r--r--test/cases/safety/cast []u8 to bigger slice of wrong size.zig18
-rw-r--r--test/cases/safety/cast integer to global error and no code matches.zig16
-rw-r--r--test/cases/safety/empty slice with sentinel out of bounds.zig20
-rw-r--r--test/cases/safety/error return trace across suspend points.zig38
-rw-r--r--test/cases/safety/exact division failure - vectors.zig20
-rw-r--r--test/cases/safety/exact division failure.zig18
-rw-r--r--test/cases/safety/intToPtr with misaligned address.zig17
-rw-r--r--test/cases/safety/integer addition overflow.zig22
-rw-r--r--test/cases/safety/integer division by zero - vectors.zig19
-rw-r--r--test/cases/safety/integer division by zero.zig17
-rw-r--r--test/cases/safety/integer multiplication overflow.zig18
-rw-r--r--test/cases/safety/integer negation overflow.zig18
-rw-r--r--test/cases/safety/integer subtraction overflow.zig18
-rw-r--r--test/cases/safety/invalid resume of async function.zig18
-rw-r--r--test/cases/safety/nosuspend function call, callee suspends.zig19
-rw-r--r--test/cases/safety/optional unwrap operator on C pointer.zig15
-rw-r--r--test/cases/safety/optional unwrap operator on null pointer.zig15
-rw-r--r--test/cases/safety/out of bounds slice access.zig18
-rw-r--r--test/cases/safety/pointer casting null to non-optional pointer.zig15
-rw-r--r--test/cases/safety/pointer slice sentinel mismatch.zig20
-rw-r--r--test/cases/safety/resuming a function which is awaiting a call.zig20
-rw-r--r--test/cases/safety/resuming a function which is awaiting a frame.zig21
-rw-r--r--test/cases/safety/resuming a non-suspended function which has been suspended and resumed.zig31
-rw-r--r--test/cases/safety/resuming a non-suspended function which never been suspended.zig26
-rw-r--r--test/cases/safety/shift left by huge amount.zig20
-rw-r--r--test/cases/safety/shift right by huge amount.zig20
-rw-r--r--test/cases/safety/signed integer division overflow - vectors.zig20
-rw-r--r--test/cases/safety/signed integer division overflow.zig18
-rw-r--r--test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig15
-rw-r--r--test/cases/safety/signed integer not fitting in cast to unsigned integer.zig18
-rw-r--r--test/cases/safety/signed shift left overflow.zig18
-rw-r--r--test/cases/safety/signed shift right overflow.zig18
-rw-r--r--test/cases/safety/signed-unsigned vector cast.zig19
-rw-r--r--test/cases/safety/slice sentinel mismatch - floats.zig19
-rw-r--r--test/cases/safety/slice sentinel mismatch - optional pointers.zig19
-rw-r--r--test/cases/safety/slice slice sentinel mismatch.zig18
-rw-r--r--test/cases/safety/slice with sentinel out of bounds.zig20
-rw-r--r--test/cases/safety/slicing null C pointer.zig16
-rw-r--r--test/cases/safety/switch on corrupted enum value.zig25
-rw-r--r--test/cases/safety/switch on corrupted union value.zig25
-rw-r--r--test/cases/safety/truncating vector cast.zig19
-rw-r--r--test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig15
-rw-r--r--test/cases/safety/unsigned shift left overflow.zig18
-rw-r--r--test/cases/safety/unsigned shift right overflow.zig18
-rw-r--r--test/cases/safety/unsigned-signed vector cast.zig19
-rw-r--r--test/cases/safety/unwrap error.zig18
-rw-r--r--test/cases/safety/value does not fit in shortening cast - u0.zig18
-rw-r--r--test/cases/safety/value does not fit in shortening cast.zig18
-rw-r--r--test/cases/safety/vector integer addition overflow.zig19
-rw-r--r--test/cases/safety/vector integer multiplication overflow.zig19
-rw-r--r--test/cases/safety/vector integer negation overflow.zig18
-rw-r--r--test/cases/safety/vector integer subtraction overflow.zig19
-rw-r--r--test/runtime_safety.zig1206
-rw-r--r--test/tests.zig16
71 files changed, 1378 insertions, 1222 deletions
diff --git a/test/cases/README.md b/test/cases/README.md
new file mode 100644
index 0000000000..4c9f401ab6
--- /dev/null
+++ b/test/cases/README.md
@@ -0,0 +1,61 @@
+# Test Case Quick Reference
+
+Use comments at the **end of the file** to indicate metadata about the test
+case. Here are examples of different kinds of tests:
+
+## Compile Error Test
+
+If you want it to be run with `zig test` and match expected error messages:
+
+```zig
+// error
+// is_test=1
+//
+// :4:13: error: 'try' outside function scope
+```
+
+## Execution
+
+This will do `zig run` on the code and expect exit code 0.
+
+```zig
+// run
+```
+
+## Incremental Compilation
+
+Make multiple files that have ".", and then an integer, before the ".zig"
+extension, like this:
+
+```
+hello.0.zig
+hello.1.zig
+hello.2.zig
+```
+
+Each file can be a different kind of test, such as expecting compile errors,
+or expecting to be run and exit(0). The test harness will use these to simulate
+incremental compilation.
+
+At the time of writing there is no way to specify multiple files being changed
+as part of an update.
+
+## Subdirectories
+
+Subdirectories do not have any semantic meaning but they can be used for
+organization since the test harness will recurse into them. The full directory
+path will be prepended as a prefix on the test case name.
+
+## Limiting which Backends and Targets are Tested
+
+```zig
+// run
+// backend=stage2,llvm
+// target=x86_64-linux,x86_64-macos
+```
+
+Possible backends are:
+
+ * `stage1`: equivalent to `-fstage1`.
+ * `stage2`: equivalent to passing `-fno-stage1 -fno-LLVM`.
+ * `llvm`: equivalent to `-fLLVM -fno-stage1`.
diff --git a/test/cases/safety/@alignCast misaligned.zig b/test/cases/safety/@alignCast misaligned.zig
new file mode 100644
index 0000000000..3948cea443
--- /dev/null
+++ b/test/cases/safety/@alignCast misaligned.zig
@@ -0,0 +1,21 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ var array align(4) = [_]u32{0x11111111, 0x11111111};
+ const bytes = std.mem.sliceAsBytes(array[0..]);
+ if (foo(bytes) != 0x11111111) return error.Wrong;
+ return error.TestFailed;
+}
+fn foo(bytes: []u8) u32 {
+ const slice4 = bytes[1..5];
+ const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4));
+ return int_slice[0];
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/@asyncCall with too small a frame.zig b/test/cases/safety/@asyncCall with too small a frame.zig
new file mode 100644
index 0000000000..8ae4d4ee3f
--- /dev/null
+++ b/test/cases/safety/@asyncCall with too small a frame.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var bytes: [1]u8 align(16) = undefined;
+ var ptr = other;
+ var frame = @asyncCall(&bytes, {}, ptr, .{});
+ _ = frame;
+ return error.TestFailed;
+}
+fn other() callconv(.Async) void {
+ suspend {}
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/@errSetCast error not present in destination.zig b/test/cases/safety/@errSetCast error not present in destination.zig
new file mode 100644
index 0000000000..3934307e9e
--- /dev/null
+++ b/test/cases/safety/@errSetCast error not present in destination.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+const Set1 = error{A, B};
+const Set2 = error{A, C};
+pub fn main() !void {
+ foo(Set1.B) catch {};
+ return error.TestFailed;
+}
+fn foo(set1: Set1) Set2 {
+ return @errSetCast(Set2, set1);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/@floatToInt cannot fit - negative out of range.zig b/test/cases/safety/@floatToInt cannot fit - negative out of range.zig
new file mode 100644
index 0000000000..1e7016830e
--- /dev/null
+++ b/test/cases/safety/@floatToInt cannot fit - negative out of range.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ baz(bar(-129.1));
+ return error.TestFailed;
+}
+fn bar(a: f32) i8 {
+ return @floatToInt(i8, a);
+}
+fn baz(_: i8) void { }
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/@floatToInt cannot fit - negative to unsigned.zig b/test/cases/safety/@floatToInt cannot fit - negative to unsigned.zig
new file mode 100644
index 0000000000..fbcc7fc11d
--- /dev/null
+++ b/test/cases/safety/@floatToInt cannot fit - negative to unsigned.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ baz(bar(-1.1));
+ return error.TestFailed;
+}
+fn bar(a: f32) u8 {
+ return @floatToInt(u8, a);
+}
+fn baz(_: u8) void { }
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/@floatToInt cannot fit - positive out of range.zig b/test/cases/safety/@floatToInt cannot fit - positive out of range.zig
new file mode 100644
index 0000000000..1ab83edafa
--- /dev/null
+++ b/test/cases/safety/@floatToInt cannot fit - positive out of range.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ baz(bar(256.2));
+ return error.TestFailed;
+}
+fn bar(a: f32) u8 {
+ return @floatToInt(u8, a);
+}
+fn baz(_: u8) void { }
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/@intCast to u0.zig b/test/cases/safety/@intCast to u0.zig
new file mode 100644
index 0000000000..10c3d22213
--- /dev/null
+++ b/test/cases/safety/@intCast to u0.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ bar(1, 1);
+ return error.TestFailed;
+}
+
+fn bar(one: u1, not_zero: i32) void {
+ var x = one << @intCast(u0, not_zero);
+ _ = x;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/@intToEnum - no matching tag value.zig b/test/cases/safety/@intToEnum - no matching tag value.zig
new file mode 100644
index 0000000000..7f66dc050d
--- /dev/null
+++ b/test/cases/safety/@intToEnum - no matching tag value.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+const Foo = enum {
+ A,
+ B,
+ C,
+};
+pub fn main() !void {
+ baz(bar(3));
+ return error.TestFailed;
+}
+fn bar(a: u2) Foo {
+ return @intToEnum(Foo, a);
+}
+fn baz(_: Foo) void {}
+// run
+// backend=stage1
diff --git a/test/cases/safety/@intToPtr address zero to non-optional byte-aligned pointer.zig b/test/cases/safety/@intToPtr address zero to non-optional byte-aligned pointer.zig
new file mode 100644
index 0000000000..6c44505af9
--- /dev/null
+++ b/test/cases/safety/@intToPtr address zero to non-optional byte-aligned pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var zero: usize = 0;
+ var b = @intToPtr(*u8, zero);
+ _ = b;
+ return error.TestFailed;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/@intToPtr address zero to non-optional pointer.zig b/test/cases/safety/@intToPtr address zero to non-optional pointer.zig
new file mode 100644
index 0000000000..9f61766884
--- /dev/null
+++ b/test/cases/safety/@intToPtr address zero to non-optional pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var zero: usize = 0;
+ var b = @intToPtr(*i32, zero);
+ _ = b;
+ return error.TestFailed;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/@tagName on corrupted enum value.zig b/test/cases/safety/@tagName on corrupted enum value.zig
new file mode 100644
index 0000000000..577ba183d5
--- /dev/null
+++ b/test/cases/safety/@tagName on corrupted enum value.zig
@@ -0,0 +1,24 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "invalid enum value")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+const E = enum(u32) {
+ X = 1,
+};
+
+pub fn main() !void {
+ var e: E = undefined;
+ @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
+ var n = @tagName(e);
+ _ = n;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/@tagName on corrupted union value.zig b/test/cases/safety/@tagName on corrupted union value.zig
new file mode 100644
index 0000000000..6012e86833
--- /dev/null
+++ b/test/cases/safety/@tagName on corrupted union value.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "invalid enum value")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+const U = union(enum(u32)) {
+ X: u8,
+};
+
+pub fn main() !void {
+ var u: U = undefined;
+ @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
+ var t: @typeInfo(U).Union.tag_type.? = u;
+ var n = @tagName(t);
+ _ = n;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/array slice sentinel mismatch.zig b/test/cases/safety/array slice sentinel mismatch.zig
new file mode 100644
index 0000000000..83e8b1f787
--- /dev/null
+++ b/test/cases/safety/array slice sentinel mismatch.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "sentinel mismatch")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var buf: [4]u8 = undefined;
+ const slice = buf[0..3 :0];
+ _ = slice;
+ return error.TestFailed;
+}
+// run
+// backend=stage1
+
diff --git a/test/cases/safety/awaiting twice.zig b/test/cases/safety/awaiting twice.zig
new file mode 100644
index 0000000000..2a64320c07
--- /dev/null
+++ b/test/cases/safety/awaiting twice.zig
@@ -0,0 +1,28 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+var frame: anyframe = undefined;
+
+pub fn main() !void {
+ _ = async amain();
+ resume frame;
+ return error.TestFailed;
+}
+
+fn amain() void {
+ var f = async func();
+ await f;
+ await f;
+}
+
+fn func() void {
+ suspend {
+ frame = @frame();
+ }
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/bad union field access.zig b/test/cases/safety/bad union field access.zig
new file mode 100644
index 0000000000..cc476f57c5
--- /dev/null
+++ b/test/cases/safety/bad union field access.zig
@@ -0,0 +1,24 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+const Foo = union {
+ float: f32,
+ int: u32,
+};
+
+pub fn main() !void {
+ var f = Foo { .int = 42 };
+ bar(&f);
+ return error.TestFailed;
+}
+
+fn bar(f: *Foo) void {
+ f.float = 12.34;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/calling panic.zig b/test/cases/safety/calling panic.zig
new file mode 100644
index 0000000000..e6ff577e7f
--- /dev/null
+++ b/test/cases/safety/calling panic.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "oh no")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ if (true) @panic("oh no");
+ return error.TestFailed;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/cast []u8 to bigger slice of wrong size.zig b/test/cases/safety/cast []u8 to bigger slice of wrong size.zig
new file mode 100644
index 0000000000..5bdee09e52
--- /dev/null
+++ b/test/cases/safety/cast []u8 to bigger slice of wrong size.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = widenSlice(&[_]u8{1, 2, 3, 4, 5});
+ if (x.len == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
+ return std.mem.bytesAsSlice(i32, slice);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/cast integer to global error and no code matches.zig b/test/cases/safety/cast integer to global error and no code matches.zig
new file mode 100644
index 0000000000..57b72aab5d
--- /dev/null
+++ b/test/cases/safety/cast integer to global error and no code matches.zig
@@ -0,0 +1,16 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ bar(9999) catch {};
+ return error.TestFailed;
+}
+fn bar(x: u16) anyerror {
+ return @intToError(x);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/empty slice with sentinel out of bounds.zig b/test/cases/safety/empty slice with sentinel out of bounds.zig
new file mode 100644
index 0000000000..2ea22ed41d
--- /dev/null
+++ b/test/cases/safety/empty slice with sentinel out of bounds.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "index out of bounds")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var buf_zero = [0]u8{};
+ const input: []u8 = &buf_zero;
+ const slice = input[0..0 :0];
+ _ = slice;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/error return trace across suspend points.zig b/test/cases/safety/error return trace across suspend points.zig
new file mode 100644
index 0000000000..b27bc770fb
--- /dev/null
+++ b/test/cases/safety/error return trace across suspend points.zig
@@ -0,0 +1,38 @@
+const std = @import("std");
+
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+var failing_frame: @Frame(failing) = undefined;
+
+pub fn main() !void {
+ const p = nonFailing();
+ resume p;
+ const p2 = async printTrace(p);
+ _ = p2;
+ return error.TestFailed;
+}
+
+fn nonFailing() anyframe->anyerror!void {
+ failing_frame = async failing();
+ return &failing_frame;
+}
+
+fn failing() anyerror!void {
+ suspend {}
+ return second();
+}
+
+fn second() callconv(.Async) anyerror!void {
+ return error.Fail;
+}
+
+fn printTrace(p: anyframe->anyerror!void) void {
+ (await p) catch unreachable;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/exact division failure - vectors.zig b/test/cases/safety/exact division failure - vectors.zig
new file mode 100644
index 0000000000..77dd427683
--- /dev/null
+++ b/test/cases/safety/exact division failure - vectors.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
+ var b: @Vector(4, i32) = [4]i32{111, 222, 333, 441};
+ const x = divExact(a, b);
+ _ = x;
+ return error.TestFailed;
+}
+fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
+ return @divExact(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/exact division failure.zig b/test/cases/safety/exact division failure.zig
new file mode 100644
index 0000000000..c363df94ab
--- /dev/null
+++ b/test/cases/safety/exact division failure.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = divExact(10, 3);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn divExact(a: i32, b: i32) i32 {
+ return @divExact(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/intToPtr with misaligned address.zig b/test/cases/safety/intToPtr with misaligned address.zig
new file mode 100644
index 0000000000..eaca2cb32d
--- /dev/null
+++ b/test/cases/safety/intToPtr with misaligned address.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "incorrect alignment")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var x: usize = 5;
+ var y = @intToPtr([*]align(4) u8, x);
+ _ = y;
+ return error.TestFailed;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/integer addition overflow.zig b/test/cases/safety/integer addition overflow.zig
new file mode 100644
index 0000000000..74fce53890
--- /dev/null
+++ b/test/cases/safety/integer addition overflow.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer overflow")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ const x = add(65530, 10);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+
+fn add(a: u16, b: u16) u16 {
+ return a + b;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/integer division by zero - vectors.zig b/test/cases/safety/integer division by zero - vectors.zig
new file mode 100644
index 0000000000..b3365bfcae
--- /dev/null
+++ b/test/cases/safety/integer division by zero - vectors.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
+ var b: @Vector(4, i32) = [4]i32{111, 0, 333, 444};
+ const x = div0(a, b);
+ _ = x;
+ return error.TestFailed;
+}
+fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
+ return @divTrunc(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/integer division by zero.zig b/test/cases/safety/integer division by zero.zig
new file mode 100644
index 0000000000..b209a69d35
--- /dev/null
+++ b/test/cases/safety/integer division by zero.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ const x = div0(999, 0);
+ _ = x;
+ return error.TestFailed;
+}
+fn div0(a: i32, b: i32) i32 {
+ return @divTrunc(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/integer multiplication overflow.zig b/test/cases/safety/integer multiplication overflow.zig
new file mode 100644
index 0000000000..0eb68fabe0
--- /dev/null
+++ b/test/cases/safety/integer multiplication overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = mul(300, 6000);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn mul(a: u16, b: u16) u16 {
+ return a * b;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/integer negation overflow.zig b/test/cases/safety/integer negation overflow.zig
new file mode 100644
index 0000000000..c9d7e4f919
--- /dev/null
+++ b/test/cases/safety/integer negation overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = neg(-32768);
+ if (x == 32767) return error.Whatever;
+ return error.TestFailed;
+}
+fn neg(a: i16) i16 {
+ return -a;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/integer subtraction overflow.zig b/test/cases/safety/integer subtraction overflow.zig
new file mode 100644
index 0000000000..f1b17020a8
--- /dev/null
+++ b/test/cases/safety/integer subtraction overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = sub(10, 20);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn sub(a: u16, b: u16) u16 {
+ return a - b;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/invalid resume of async function.zig b/test/cases/safety/invalid resume of async function.zig
new file mode 100644
index 0000000000..acde5eed92
--- /dev/null
+++ b/test/cases/safety/invalid resume of async function.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var p = async suspendOnce();
+ resume p; //ok
+ resume p; //bad
+ return error.TestFailed;
+}
+fn suspendOnce() void {
+ suspend {}
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/nosuspend function call, callee suspends.zig b/test/cases/safety/nosuspend function call, callee suspends.zig
new file mode 100644
index 0000000000..fc99174bd0
--- /dev/null
+++ b/test/cases/safety/nosuspend function call, callee suspends.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ _ = nosuspend add(101, 100);
+ return error.TestFailed;
+}
+fn add(a: i32, b: i32) i32 {
+ if (a > 100) {
+ suspend {}
+ }
+ return a + b;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/optional unwrap operator on C pointer.zig b/test/cases/safety/optional unwrap operator on C pointer.zig
new file mode 100644
index 0000000000..4d5fa54d3d
--- /dev/null
+++ b/test/cases/safety/optional unwrap operator on C pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var ptr: [*c]i32 = null;
+ var b = ptr.?;
+ _ = b;
+ return error.TestFailed;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/optional unwrap operator on null pointer.zig b/test/cases/safety/optional unwrap operator on null pointer.zig
new file mode 100644
index 0000000000..eb791be268
--- /dev/null
+++ b/test/cases/safety/optional unwrap operator on null pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var ptr: ?*i32 = null;
+ var b = ptr.?;
+ _ = b;
+ return error.TestFailed;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/out of bounds slice access.zig b/test/cases/safety/out of bounds slice access.zig
new file mode 100644
index 0000000000..e429328b1e
--- /dev/null
+++ b/test/cases/safety/out of bounds slice access.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ const a = [_]i32{1, 2, 3, 4};
+ baz(bar(&a));
+ return error.TestFailed;
+}
+fn bar(a: []const i32) i32 {
+ return a[4];
+}
+fn baz(_: i32) void { }
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/pointer casting null to non-optional pointer.zig b/test/cases/safety/pointer casting null to non-optional pointer.zig
new file mode 100644
index 0000000000..a61ba2fa9b
--- /dev/null
+++ b/test/cases/safety/pointer casting null to non-optional pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var c_ptr: [*c]u8 = 0;
+ var zig_ptr: *u8 = c_ptr;
+ _ = zig_ptr;
+ return error.TestFailed;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/pointer slice sentinel mismatch.zig b/test/cases/safety/pointer slice sentinel mismatch.zig
new file mode 100644
index 0000000000..f796534783
--- /dev/null
+++ b/test/cases/safety/pointer slice sentinel mismatch.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "sentinel mismatch")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var buf: [4]u8 = undefined;
+ const ptr: [*]u8 = &buf;
+ const slice = ptr[0..3 :0];
+ _ = slice;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/resuming a function which is awaiting a call.zig b/test/cases/safety/resuming a function which is awaiting a call.zig
new file mode 100644
index 0000000000..63c4e1ef50
--- /dev/null
+++ b/test/cases/safety/resuming a function which is awaiting a call.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var frame = async first();
+ resume frame;
+ return error.TestFailed;
+}
+fn first() void {
+ other();
+}
+fn other() void {
+ suspend {}
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/resuming a function which is awaiting a frame.zig b/test/cases/safety/resuming a function which is awaiting a frame.zig
new file mode 100644
index 0000000000..0f68be4db8
--- /dev/null
+++ b/test/cases/safety/resuming a function which is awaiting a frame.zig
@@ -0,0 +1,21 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var frame = async first();
+ resume frame;
+ return error.TestFailed;
+}
+fn first() void {
+ var frame = async other();
+ await frame;
+}
+fn other() void {
+ suspend {}
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/resuming a non-suspended function which has been suspended and resumed.zig b/test/cases/safety/resuming a non-suspended function which has been suspended and resumed.zig
new file mode 100644
index 0000000000..3f3a62fe4e
--- /dev/null
+++ b/test/cases/safety/resuming a non-suspended function which has been suspended and resumed.zig
@@ -0,0 +1,31 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+fn foo() void {
+ suspend {
+ global_frame = @frame();
+ }
+ var f = async bar(@frame());
+ _ = f;
+ std.os.exit(1);
+}
+
+fn bar(frame: anyframe) void {
+ suspend {
+ resume frame;
+ }
+ std.os.exit(1);
+}
+
+var global_frame: anyframe = undefined;
+pub fn main() !void {
+ _ = async foo();
+ resume global_frame;
+ std.os.exit(1);
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/resuming a non-suspended function which never been suspended.zig b/test/cases/safety/resuming a non-suspended function which never been suspended.zig
new file mode 100644
index 0000000000..b0dfbc1911
--- /dev/null
+++ b/test/cases/safety/resuming a non-suspended function which never been suspended.zig
@@ -0,0 +1,26 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+fn foo() void {
+ var f = async bar(@frame());
+ _ = f;
+ std.os.exit(1);
+}
+
+fn bar(frame: anyframe) void {
+ suspend {
+ resume frame;
+ }
+ std.os.exit(1);
+}
+
+pub fn main() !void {
+ _ = async foo();
+ return error.TestFailed;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/shift left by huge amount.zig b/test/cases/safety/shift left by huge amount.zig
new file mode 100644
index 0000000000..8cf5ec3752
--- /dev/null
+++ b/test/cases/safety/shift left by huge amount.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var x: u24 = 42;
+ var y: u5 = 24;
+ var z = x >> y;
+ _ = z;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/shift right by huge amount.zig b/test/cases/safety/shift right by huge amount.zig
new file mode 100644
index 0000000000..90a620ddc4
--- /dev/null
+++ b/test/cases/safety/shift right by huge amount.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var x: u24 = 42;
+ var y: u5 = 24;
+ var z = x << y;
+ _ = z;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/signed integer division overflow - vectors.zig b/test/cases/safety/signed integer division overflow - vectors.zig
new file mode 100644
index 0000000000..5ce8fd740e
--- /dev/null
+++ b/test/cases/safety/signed integer division overflow - vectors.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ var a: @Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 };
+ var b: @Vector(4, i16) = [_]i16{ 1, 2, -1, 4 };
+ const x = div(a, b);
+ if (x[2] == 32767) return error.Whatever;
+ return error.TestFailed;
+}
+fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) {
+ return @divTrunc(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/signed integer division overflow.zig b/test/cases/safety/signed integer division overflow.zig
new file mode 100644
index 0000000000..64e1827b45
--- /dev/null
+++ b/test/cases/safety/signed integer division overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = div(-32768, -1);
+ if (x == 32767) return error.Whatever;
+ return error.TestFailed;
+}
+fn div(a: i16, b: i16) i16 {
+ return @divTrunc(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig b/test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig
new file mode 100644
index 0000000000..7c08fcddb2
--- /dev/null
+++ b/test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var value: c_short = -1;
+ var casted = @intCast(u32, value);
+ _ = casted;
+ return error.TestFailed;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/signed integer not fitting in cast to unsigned integer.zig b/test/cases/safety/signed integer not fitting in cast to unsigned integer.zig
new file mode 100644
index 0000000000..6ed4246403
--- /dev/null
+++ b/test/cases/safety/signed integer not fitting in cast to unsigned integer.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = unsigned_cast(-10);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn unsigned_cast(x: i32) u32 {
+ return @intCast(u32, x);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/signed shift left overflow.zig b/test/cases/safety/signed shift left overflow.zig
new file mode 100644
index 0000000000..814d52b1a9
--- /dev/null
+++ b/test/cases/safety/signed shift left overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = shl(-16385, 1);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn shl(a: i16, b: u4) i16 {
+ return @shlExact(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/signed shift right overflow.zig b/test/cases/safety/signed shift right overflow.zig
new file mode 100644
index 0000000000..fc2e00cee3
--- /dev/null
+++ b/test/cases/safety/signed shift right overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = shr(-16385, 1);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn shr(a: i16, b: u4) i16 {
+ return @shrExact(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/signed-unsigned vector cast.zig b/test/cases/safety/signed-unsigned vector cast.zig
new file mode 100644
index 0000000000..4de78e969d
--- /dev/null
+++ b/test/cases/safety/signed-unsigned vector cast.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var x = @splat(4, @as(i32, -2147483647));
+ var y = @intCast(@Vector(4, u32), x);
+ _ = y;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/slice sentinel mismatch - floats.zig b/test/cases/safety/slice sentinel mismatch - floats.zig
new file mode 100644
index 0000000000..df5edc1fdf
--- /dev/null
+++ b/test/cases/safety/slice sentinel mismatch - floats.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "sentinel mismatch")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var buf: [4]f32 = undefined;
+ const slice = buf[0..3 :1.2];
+ _ = slice;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/slice sentinel mismatch - optional pointers.zig b/test/cases/safety/slice sentinel mismatch - optional pointers.zig
new file mode 100644
index 0000000000..8199f3280e
--- /dev/null
+++ b/test/cases/safety/slice sentinel mismatch - optional pointers.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "sentinel mismatch")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var buf: [4]?*i32 = undefined;
+ const slice = buf[0..3 :null];
+ _ = slice;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/slice slice sentinel mismatch.zig b/test/cases/safety/slice slice sentinel mismatch.zig
new file mode 100644
index 0000000000..8303b1a288
--- /dev/null
+++ b/test/cases/safety/slice slice sentinel mismatch.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "sentinel mismatch")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var buf: [4]u8 = undefined;
+ const slice = buf[0..];
+ const slice2 = slice[0..3 :0];
+ _ = slice2;
+ return error.TestFailed;
+}
+// run
+// backend=stage1
diff --git a/test/cases/safety/slice with sentinel out of bounds.zig b/test/cases/safety/slice with sentinel out of bounds.zig
new file mode 100644
index 0000000000..7fc890e144
--- /dev/null
+++ b/test/cases/safety/slice with sentinel out of bounds.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "index out of bounds")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var buf = [4]u8{ 'a', 'b', 'c', 0 };
+ const input: []u8 = &buf;
+ const slice = input[0..4 :0];
+ _ = slice;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/slicing null C pointer.zig b/test/cases/safety/slicing null C pointer.zig
new file mode 100644
index 0000000000..2b678ad9cf
--- /dev/null
+++ b/test/cases/safety/slicing null C pointer.zig
@@ -0,0 +1,16 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ var ptr: [*c]const u32 = null;
+ var slice = ptr[0..3];
+ _ = slice;
+ return error.TestFailed;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/switch on corrupted enum value.zig b/test/cases/safety/switch on corrupted enum value.zig
new file mode 100644
index 0000000000..b574444341
--- /dev/null
+++ b/test/cases/safety/switch on corrupted enum value.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "reached unreachable code")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+const E = enum(u32) {
+ X = 1,
+};
+
+pub fn main() !void {
+ var e: E = undefined;
+ @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
+ switch (e) {
+ .X => @breakpoint(),
+ }
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/switch on corrupted union value.zig b/test/cases/safety/switch on corrupted union value.zig
new file mode 100644
index 0000000000..8ec4fece1b
--- /dev/null
+++ b/test/cases/safety/switch on corrupted union value.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "reached unreachable code")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+const U = union(enum(u32)) {
+ X: u8,
+};
+
+pub fn main() !void {
+ var u: U = undefined;
+ @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
+ switch (u) {
+ .X => @breakpoint(),
+ }
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/truncating vector cast.zig b/test/cases/safety/truncating vector cast.zig
new file mode 100644
index 0000000000..f2795d9c66
--- /dev/null
+++ b/test/cases/safety/truncating vector cast.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer cast truncated bits")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var x = @splat(4, @as(u32, 0xdeadbeef));
+ var y = @intCast(@Vector(4, u16), x);
+ _ = y;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig b/test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig
new file mode 100644
index 0000000000..6118d5a5ea
--- /dev/null
+++ b/test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var value: u8 = 245;
+ var casted = @intCast(i8, value);
+ _ = casted;
+ return error.TestFailed;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/unsigned shift left overflow.zig b/test/cases/safety/unsigned shift left overflow.zig
new file mode 100644
index 0000000000..3fa2658c3f
--- /dev/null
+++ b/test/cases/safety/unsigned shift left overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = shl(0b0010111111111111, 3);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn shl(a: u16, b: u4) u16 {
+ return @shlExact(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/unsigned shift right overflow.zig b/test/cases/safety/unsigned shift right overflow.zig
new file mode 100644
index 0000000000..0953229a67
--- /dev/null
+++ b/test/cases/safety/unsigned shift right overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = shr(0b0010111111111111, 3);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn shr(a: u16, b: u4) u16 {
+ return @shrExact(a, b);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/unsigned-signed vector cast.zig b/test/cases/safety/unsigned-signed vector cast.zig
new file mode 100644
index 0000000000..9c157d8f40
--- /dev/null
+++ b/test/cases/safety/unsigned-signed vector cast.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer cast truncated bits")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ var x = @splat(4, @as(u32, 0x80000000));
+ var y = @intCast(@Vector(4, i32), x);
+ _ = y;
+ return error.TestFailed;
+}
+
+// run
+// backend=stage1
diff --git a/test/cases/safety/unwrap error.zig b/test/cases/safety/unwrap error.zig
new file mode 100644
index 0000000000..451b9b3891
--- /dev/null
+++ b/test/cases/safety/unwrap error.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "attempt to unwrap error: Whatever")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ bar() catch unreachable;
+ return error.TestFailed;
+}
+fn bar() !void {
+ return error.Whatever;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/value does not fit in shortening cast - u0.zig b/test/cases/safety/value does not fit in shortening cast - u0.zig
new file mode 100644
index 0000000000..3bbcaf972f
--- /dev/null
+++ b/test/cases/safety/value does not fit in shortening cast - u0.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = shorten_cast(1);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn shorten_cast(x: u8) u0 {
+ return @intCast(u0, x);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/value does not fit in shortening cast.zig b/test/cases/safety/value does not fit in shortening cast.zig
new file mode 100644
index 0000000000..2c7409d225
--- /dev/null
+++ b/test/cases/safety/value does not fit in shortening cast.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() !void {
+ const x = shorten_cast(200);
+ if (x == 0) return error.Whatever;
+ return error.TestFailed;
+}
+fn shorten_cast(x: i32) i8 {
+ return @intCast(i8, x);
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/vector integer addition overflow.zig b/test/cases/safety/vector integer addition overflow.zig
new file mode 100644
index 0000000000..32b045cd56
--- /dev/null
+++ b/test/cases/safety/vector integer addition overflow.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var a: @Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 };
+ var b: @Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
+ const x = add(a, b);
+ _ = x;
+ return error.TestFailed;
+}
+fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
+ return a + b;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/vector integer multiplication overflow.zig b/test/cases/safety/vector integer multiplication overflow.zig
new file mode 100644
index 0000000000..2c9d48e1fd
--- /dev/null
+++ b/test/cases/safety/vector integer multiplication overflow.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var a: @Vector(4, u8) = [_]u8{ 1, 2, 200, 4 };
+ var b: @Vector(4, u8) = [_]u8{ 5, 6, 2, 8 };
+ const x = mul(b, a);
+ _ = x;
+ return error.TestFailed;
+}
+fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) {
+ return a * b;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/vector integer negation overflow.zig b/test/cases/safety/vector integer negation overflow.zig
new file mode 100644
index 0000000000..81506da41c
--- /dev/null
+++ b/test/cases/safety/vector integer negation overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var a: @Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 };
+ const x = neg(a);
+ _ = x;
+ return error.TestFailed;
+}
+fn neg(a: @Vector(4, i16)) @Vector(4, i16) {
+ return -a;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/cases/safety/vector integer subtraction overflow.zig b/test/cases/safety/vector integer subtraction overflow.zig
new file mode 100644
index 0000000000..c3a21e971c
--- /dev/null
+++ b/test/cases/safety/vector integer subtraction overflow.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+pub fn main() !void {
+ var a: @Vector(4, u32) = [_]u32{ 1, 2, 8, 4 };
+ var b: @Vector(4, u32) = [_]u32{ 5, 6, 7, 8 };
+ const x = sub(b, a);
+ _ = x;
+ return error.TestFailed;
+}
+fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) {
+ return a - b;
+}
+// run
+// backend=stage1 \ No newline at end of file
diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig
deleted file mode 100644
index f73226159a..0000000000
--- a/test/runtime_safety.zig
+++ /dev/null
@@ -1,1206 +0,0 @@
-const tests = @import("tests.zig");
-
-pub fn addCases(cases: *tests.CompareOutputContext) void {
- {
- const check_panic_msg =
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "reached unreachable code")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- ;
-
- cases.addRuntimeSafety("switch on corrupted enum value",
- \\const std = @import("std");
- ++ check_panic_msg ++
- \\const E = enum(u32) {
- \\ X = 1,
- \\};
- \\pub fn main() void {
- \\ var e: E = undefined;
- \\ @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
- \\ switch (e) {
- \\ .X => @breakpoint(),
- \\ }
- \\}
- );
-
- cases.addRuntimeSafety("switch on corrupted union value",
- \\const std = @import("std");
- ++ check_panic_msg ++
- \\const U = union(enum(u32)) {
- \\ X: u8,
- \\};
- \\pub fn main() void {
- \\ var u: U = undefined;
- \\ @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
- \\ switch (u) {
- \\ .X => @breakpoint(),
- \\ }
- \\}
- );
- }
-
- {
- const check_panic_msg =
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "invalid enum value")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- ;
-
- cases.addRuntimeSafety("@tagName on corrupted enum value",
- \\const std = @import("std");
- ++ check_panic_msg ++
- \\const E = enum(u32) {
- \\ X = 1,
- \\};
- \\pub fn main() void {
- \\ var e: E = undefined;
- \\ @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
- \\ var n = @tagName(e);
- \\ _ = n;
- \\}
- );
-
- cases.addRuntimeSafety("@tagName on corrupted union value",
- \\const std = @import("std");
- ++ check_panic_msg ++
- \\const U = union(enum(u32)) {
- \\ X: u8,
- \\};
- \\pub fn main() void {
- \\ var u: U = undefined;
- \\ @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
- \\ var t: @typeInfo(U).Union.tag_type.? = u;
- \\ var n = @tagName(t);
- \\ _ = n;
- \\}
- );
- }
-
- {
- const check_panic_msg =
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "index out of bounds")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- ;
-
- cases.addRuntimeSafety("slice with sentinel out of bounds",
- \\const std = @import("std");
- ++ check_panic_msg ++
- \\pub fn main() void {
- \\ var buf = [4]u8{'a','b','c',0};
- \\ const input: []u8 = &buf;
- \\ const slice = input[0..4 :0];
- \\ _ = slice;
- \\}
- );
- cases.addRuntimeSafety("empty slice with sentinel out of bounds",
- \\const std = @import("std");
- ++ check_panic_msg ++
- \\pub fn main() void {
- \\ var buf_zero = [0]u8{};
- \\ const input: []u8 = &buf_zero;
- \\ const slice = input[0..0 :0];
- \\ _ = slice;
- \\}
- );
- }
-
- cases.addRuntimeSafety("truncating vector cast",
- \\const std = @import("std");
- \\const V = @import("std").meta.Vector;
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "integer cast truncated bits")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var x = @splat(4, @as(u32, 0xdeadbeef));
- \\ var y = @intCast(V(4, u16), x);
- \\ _ = y;
- \\}
- );
-
- cases.addRuntimeSafety("unsigned-signed vector cast",
- \\const std = @import("std");
- \\const V = @import("std").meta.Vector;
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "integer cast truncated bits")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var x = @splat(4, @as(u32, 0x80000000));
- \\ var y = @intCast(V(4, i32), x);
- \\ _ = y;
- \\}
- );
-
- cases.addRuntimeSafety("signed-unsigned vector cast",
- \\const std = @import("std");
- \\const V = @import("std").meta.Vector;
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var x = @splat(4, @as(i32, -2147483647));
- \\ var y = @intCast(V(4, u32), x);
- \\ _ = y;
- \\}
- );
-
- cases.addRuntimeSafety("shift left by huge amount",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var x: u24 = 42;
- \\ var y: u5 = 24;
- \\ var z = x >> y;
- \\ _ = z;
- \\}
- );
-
- cases.addRuntimeSafety("shift right by huge amount",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var x: u24 = 42;
- \\ var y: u5 = 24;
- \\ var z = x << y;
- \\ _ = z;
- \\}
- );
-
- cases.addRuntimeSafety("slice sentinel mismatch - optional pointers",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var buf: [4]?*i32 = undefined;
- \\ const slice = buf[0..3 :null];
- \\ _ = slice;
- \\}
- );
-
- cases.addRuntimeSafety("slice sentinel mismatch - floats",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var buf: [4]f32 = undefined;
- \\ const slice = buf[0..3 :1.2];
- \\ _ = slice;
- \\}
- );
-
- cases.addRuntimeSafety("pointer slice sentinel mismatch",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var buf: [4]u8 = undefined;
- \\ const ptr: [*]u8 = &buf;
- \\ const slice = ptr[0..3 :0];
- \\ _ = slice;
- \\}
- );
-
- cases.addRuntimeSafety("slice slice sentinel mismatch",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var buf: [4]u8 = undefined;
- \\ const slice = buf[0..];
- \\ const slice2 = slice[0..3 :0];
- \\ _ = slice2;
- \\}
- );
-
- cases.addRuntimeSafety("array slice sentinel mismatch",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
- \\ std.process.exit(126); // good
- \\ }
- \\ std.process.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var buf: [4]u8 = undefined;
- \\ const slice = buf[0..3 :0];
- \\ _ = slice;
- \\}
- );
-
- cases.addRuntimeSafety("intToPtr with misaligned address",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "incorrect alignment")) {
- \\ std.os.exit(126); // good
- \\ }
- \\ std.os.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ var x: usize = 5;
- \\ var y = @intToPtr([*]align(4) u8, x);
- \\ _ = y;
- \\}
- );
-
- cases.addRuntimeSafety("resuming a non-suspended function which never been suspended",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\fn foo() void {
- \\ var f = async bar(@frame());
- \\ _ = f;
- \\ std.os.exit(0);
- \\}
- \\
- \\fn bar(frame: anyframe) void {
- \\ suspend {
- \\ resume frame;
- \\ }
- \\ std.os.exit(0);
- \\}
- \\
- \\pub fn main() void {
- \\ _ = async foo();
- \\}
- );
-
- cases.addRuntimeSafety("resuming a non-suspended function which has been suspended and resumed",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\fn foo() void {
- \\ suspend {
- \\ global_frame = @frame();
- \\ }
- \\ var f = async bar(@frame());
- \\ _ = f;
- \\ std.os.exit(0);
- \\}
- \\
- \\fn bar(frame: anyframe) void {
- \\ suspend {
- \\ resume frame;
- \\ }
- \\ std.os.exit(0);
- \\}
- \\
- \\var global_frame: anyframe = undefined;
- \\pub fn main() void {
- \\ _ = async foo();
- \\ resume global_frame;
- \\ std.os.exit(0);
- \\}
- );
-
- cases.addRuntimeSafety("nosuspend function call, callee suspends",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ _ = nosuspend add(101, 100);
- \\}
- \\fn add(a: i32, b: i32) i32 {
- \\ if (a > 100) {
- \\ suspend {}
- \\ }
- \\ return a + b;
- \\}
- );
-
- cases.addRuntimeSafety("awaiting twice",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\var frame: anyframe = undefined;
- \\
- \\pub fn main() void {
- \\ _ = async amain();
- \\ resume frame;
- \\}
- \\
- \\fn amain() void {
- \\ var f = async func();
- \\ await f;
- \\ await f;
- \\}
- \\
- \\fn func() void {
- \\ suspend {
- \\ frame = @frame();
- \\ }
- \\}
- );
-
- cases.addRuntimeSafety("@asyncCall with too small a frame",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var bytes: [1]u8 align(16) = undefined;
- \\ var ptr = other;
- \\ var frame = @asyncCall(&bytes, {}, ptr, .{});
- \\ _ = frame;
- \\}
- \\fn other() callconv(.Async) void {
- \\ suspend {}
- \\}
- );
-
- cases.addRuntimeSafety("resuming a function which is awaiting a frame",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var frame = async first();
- \\ resume frame;
- \\}
- \\fn first() void {
- \\ var frame = async other();
- \\ await frame;
- \\}
- \\fn other() void {
- \\ suspend {}
- \\}
- );
-
- cases.addRuntimeSafety("resuming a function which is awaiting a call",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var frame = async first();
- \\ resume frame;
- \\}
- \\fn first() void {
- \\ other();
- \\}
- \\fn other() void {
- \\ suspend {}
- \\}
- );
-
- cases.addRuntimeSafety("invalid resume of async function",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var p = async suspendOnce();
- \\ resume p; //ok
- \\ resume p; //bad
- \\}
- \\fn suspendOnce() void {
- \\ suspend {}
- \\}
- );
-
- cases.addRuntimeSafety(".? operator on null pointer",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var ptr: ?*i32 = null;
- \\ var b = ptr.?;
- \\ _ = b;
- \\}
- );
-
- cases.addRuntimeSafety(".? operator on C pointer",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var ptr: [*c]i32 = null;
- \\ var b = ptr.?;
- \\ _ = b;
- \\}
- );
-
- cases.addRuntimeSafety("@intToPtr address zero to non-optional pointer",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var zero: usize = 0;
- \\ var b = @intToPtr(*i32, zero);
- \\ _ = b;
- \\}
- );
-
- cases.addRuntimeSafety("@intToPtr address zero to non-optional byte-aligned pointer",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var zero: usize = 0;
- \\ var b = @intToPtr(*u8, zero);
- \\ _ = b;
- \\}
- );
-
- cases.addRuntimeSafety("pointer casting null to non-optional pointer",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var c_ptr: [*c]u8 = 0;
- \\ var zig_ptr: *u8 = c_ptr;
- \\ _ = zig_ptr;
- \\}
- );
-
- cases.addRuntimeSafety("@intToEnum - no matching tag value",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\const Foo = enum {
- \\ A,
- \\ B,
- \\ C,
- \\};
- \\pub fn main() void {
- \\ baz(bar(3));
- \\}
- \\fn bar(a: u2) Foo {
- \\ return @intToEnum(Foo, a);
- \\}
- \\fn baz(_: Foo) void {}
- );
-
- cases.addRuntimeSafety("@floatToInt cannot fit - negative to unsigned",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ baz(bar(-1.1));
- \\}
- \\fn bar(a: f32) u8 {
- \\ return @floatToInt(u8, a);
- \\}
- \\fn baz(_: u8) void { }
- );
-
- cases.addRuntimeSafety("@floatToInt cannot fit - negative out of range",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ baz(bar(-129.1));
- \\}
- \\fn bar(a: f32) i8 {
- \\ return @floatToInt(i8, a);
- \\}
- \\fn baz(_: i8) void { }
- );
-
- cases.addRuntimeSafety("@floatToInt cannot fit - positive out of range",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ baz(bar(256.2));
- \\}
- \\fn bar(a: f32) u8 {
- \\ return @floatToInt(u8, a);
- \\}
- \\fn baz(_: u8) void { }
- );
-
- cases.addRuntimeSafety("calling panic",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ @panic("oh no");
- \\}
- );
-
- cases.addRuntimeSafety("out of bounds slice access",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ const a = [_]i32{1, 2, 3, 4};
- \\ baz(bar(&a));
- \\}
- \\fn bar(a: []const i32) i32 {
- \\ return a[4];
- \\}
- \\fn baz(_: i32) void { }
- );
-
- cases.addRuntimeSafety("integer addition overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = add(65530, 10);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn add(a: u16, b: u16) u16 {
- \\ return a + b;
- \\}
- );
-
- cases.addRuntimeSafety("vector integer addition overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var a: @Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 };
- \\ var b: @Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
- \\ const x = add(a, b);
- \\ _ = x;
- \\}
- \\fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
- \\ return a + b;
- \\}
- );
-
- cases.addRuntimeSafety("vector integer subtraction overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var a: @Vector(4, u32) = [_]u32{ 1, 2, 8, 4 };
- \\ var b: @Vector(4, u32) = [_]u32{ 5, 6, 7, 8 };
- \\ const x = sub(b, a);
- \\ _ = x;
- \\}
- \\fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) {
- \\ return a - b;
- \\}
- );
-
- cases.addRuntimeSafety("vector integer multiplication overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var a: @Vector(4, u8) = [_]u8{ 1, 2, 200, 4 };
- \\ var b: @Vector(4, u8) = [_]u8{ 5, 6, 2, 8 };
- \\ const x = mul(b, a);
- \\ _ = x;
- \\}
- \\fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) {
- \\ return a * b;
- \\}
- );
-
- cases.addRuntimeSafety("vector integer negation overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var a: @Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 };
- \\ const x = neg(a);
- \\ _ = x;
- \\}
- \\fn neg(a: @Vector(4, i16)) @Vector(4, i16) {
- \\ return -a;
- \\}
- );
-
- cases.addRuntimeSafety("integer subtraction overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = sub(10, 20);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn sub(a: u16, b: u16) u16 {
- \\ return a - b;
- \\}
- );
-
- cases.addRuntimeSafety("integer multiplication overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = mul(300, 6000);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn mul(a: u16, b: u16) u16 {
- \\ return a * b;
- \\}
- );
-
- cases.addRuntimeSafety("integer negation overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = neg(-32768);
- \\ if (x == 32767) return error.Whatever;
- \\}
- \\fn neg(a: i16) i16 {
- \\ return -a;
- \\}
- );
-
- cases.addRuntimeSafety("signed integer division overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = div(-32768, -1);
- \\ if (x == 32767) return error.Whatever;
- \\}
- \\fn div(a: i16, b: i16) i16 {
- \\ return @divTrunc(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("signed integer division overflow - vectors",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ var a: @Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 };
- \\ var b: @Vector(4, i16) = [_]i16{ 1, 2, -1, 4 };
- \\ const x = div(a, b);
- \\ if (x[2] == 32767) return error.Whatever;
- \\}
- \\fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) {
- \\ return @divTrunc(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("signed shift left overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = shl(-16385, 1);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn shl(a: i16, b: u4) i16 {
- \\ return @shlExact(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("unsigned shift left overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = shl(0b0010111111111111, 3);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn shl(a: u16, b: u4) u16 {
- \\ return @shlExact(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("signed shift right overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = shr(-16385, 1);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn shr(a: i16, b: u4) i16 {
- \\ return @shrExact(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("unsigned shift right overflow",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = shr(0b0010111111111111, 3);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn shr(a: u16, b: u4) u16 {
- \\ return @shrExact(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("integer division by zero",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ const x = div0(999, 0);
- \\ _ = x;
- \\}
- \\fn div0(a: i32, b: i32) i32 {
- \\ return @divTrunc(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("integer division by zero - vectors",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
- \\ var b: @Vector(4, i32) = [4]i32{111, 0, 333, 444};
- \\ const x = div0(a, b);
- \\ _ = x;
- \\}
- \\fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
- \\ return @divTrunc(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("exact division failure",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = divExact(10, 3);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn divExact(a: i32, b: i32) i32 {
- \\ return @divExact(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("exact division failure - vectors",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
- \\ var b: @Vector(4, i32) = [4]i32{111, 222, 333, 441};
- \\ const x = divExact(a, b);
- \\ _ = x;
- \\}
- \\fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
- \\ return @divExact(a, b);
- \\}
- );
-
- cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = widenSlice(&[_]u8{1, 2, 3, 4, 5});
- \\ if (x.len == 0) return error.Whatever;
- \\}
- \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
- \\ return std.mem.bytesAsSlice(i32, slice);
- \\}
- );
-
- cases.addRuntimeSafety("value does not fit in shortening cast",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = shorten_cast(200);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn shorten_cast(x: i32) i8 {
- \\ return @intCast(i8, x);
- \\}
- );
-
- cases.addRuntimeSafety("value does not fit in shortening cast - u0",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = shorten_cast(1);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn shorten_cast(x: u8) u0 {
- \\ return @intCast(u0, x);
- \\}
- );
-
- cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ const x = unsigned_cast(-10);
- \\ if (x == 0) return error.Whatever;
- \\}
- \\fn unsigned_cast(x: i32) u32 {
- \\ return @intCast(u32, x);
- \\}
- );
-
- cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var value: c_short = -1;
- \\ var casted = @intCast(u32, value);
- \\ _ = casted;
- \\}
- );
-
- cases.addRuntimeSafety("unsigned integer not fitting in cast to signed integer - same bit count",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ var value: u8 = 245;
- \\ var casted = @intCast(i8, value);
- \\ _ = casted;
- \\}
- );
-
- cases.addRuntimeSafety("unwrap error",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = stack_trace;
- \\ if (std.mem.eql(u8, message, "attempt to unwrap error: Whatever")) {
- \\ std.os.exit(126); // good
- \\ }
- \\ std.os.exit(0); // test failed
- \\}
- \\pub fn main() void {
- \\ bar() catch unreachable;
- \\}
- \\fn bar() !void {
- \\ return error.Whatever;
- \\}
- );
-
- cases.addRuntimeSafety("cast integer to global error and no code matches",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() void {
- \\ bar(9999) catch {};
- \\}
- \\fn bar(x: u16) anyerror {
- \\ return @intToError(x);
- \\}
- );
-
- cases.addRuntimeSafety("@errSetCast error not present in destination",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\const Set1 = error{A, B};
- \\const Set2 = error{A, C};
- \\pub fn main() void {
- \\ foo(Set1.B) catch {};
- \\}
- \\fn foo(set1: Set1) Set2 {
- \\ return @errSetCast(Set2, set1);
- \\}
- );
-
- cases.addRuntimeSafety("@alignCast misaligned",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\pub fn main() !void {
- \\ var array align(4) = [_]u32{0x11111111, 0x11111111};
- \\ const bytes = std.mem.sliceAsBytes(array[0..]);
- \\ if (foo(bytes) != 0x11111111) return error.Wrong;
- \\}
- \\fn foo(bytes: []u8) u32 {
- \\ const slice4 = bytes[1..5];
- \\ const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4));
- \\ return int_slice[0];
- \\}
- );
-
- cases.addRuntimeSafety("bad union field access",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\
- \\const Foo = union {
- \\ float: f32,
- \\ int: u32,
- \\};
- \\
- \\pub fn main() void {
- \\ var f = Foo { .int = 42 };
- \\ bar(&f);
- \\}
- \\
- \\fn bar(f: *Foo) void {
- \\ f.float = 12.34;
- \\}
- );
-
- // @intCast a runtime integer to u0 actually results in a comptime-known value,
- // but we still emit a safety check to ensure the integer was 0 and thus
- // did not truncate information.
- cases.addRuntimeSafety("@intCast to u0",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\
- \\pub fn main() void {
- \\ bar(1, 1);
- \\}
- \\
- \\fn bar(one: u1, not_zero: i32) void {
- \\ var x = one << @intCast(u0, not_zero);
- \\ _ = x;
- \\}
- );
-
- // This case makes sure that the code compiles and runs. There is not actually a special
- // runtime safety check having to do specifically with error return traces across suspend points.
- cases.addRuntimeSafety("error return trace across suspend points",
- \\const std = @import("std");
- \\
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\
- \\var failing_frame: @Frame(failing) = undefined;
- \\
- \\pub fn main() void {
- \\ const p = nonFailing();
- \\ resume p;
- \\ const p2 = async printTrace(p);
- \\ _ = p2;
- \\}
- \\
- \\fn nonFailing() anyframe->anyerror!void {
- \\ failing_frame = async failing();
- \\ return &failing_frame;
- \\}
- \\
- \\fn failing() anyerror!void {
- \\ suspend {}
- \\ return second();
- \\}
- \\
- \\fn second() callconv(.Async) anyerror!void {
- \\ return error.Fail;
- \\}
- \\
- \\fn printTrace(p: anyframe->anyerror!void) void {
- \\ (await p) catch unreachable;
- \\}
- );
-
- // Slicing a C pointer returns a non-allowzero slice, thus we need to emit
- // a safety check to ensure the pointer is not null.
- cases.addRuntimeSafety("slicing null C pointer",
- \\const std = @import("std");
- \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
- \\ _ = message;
- \\ _ = stack_trace;
- \\ std.os.exit(126);
- \\}
- \\
- \\pub fn main() void {
- \\ var ptr: [*c]const u32 = null;
- \\ var slice = ptr[0..3];
- \\ _ = slice;
- \\}
- );
-}
diff --git a/test/tests.zig b/test/tests.zig
index 62c437e7f7..e44b190bb4 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -18,7 +18,6 @@ const compare_output = @import("compare_output.zig");
const standalone = @import("standalone.zig");
const stack_traces = @import("stack_traces.zig");
const assemble_and_link = @import("assemble_and_link.zig");
-const runtime_safety = @import("runtime_safety.zig");
const translate_c = @import("translate_c.zig");
const run_translated_c = @import("run_translated_c.zig");
const gen_h = @import("gen_h.zig");
@@ -455,21 +454,6 @@ pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, modes: []
return cases.step;
}
-pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
- const cases = b.allocator.create(CompareOutputContext) catch unreachable;
- cases.* = CompareOutputContext{
- .b = b,
- .step = b.step("test-runtime-safety", "Run the runtime safety tests"),
- .test_index = 0,
- .test_filter = test_filter,
- .modes = modes,
- };
-
- runtime_safety.addCases(cases);
-
- return cases.step;
-}
-
pub fn addStandaloneTests(
b: *build.Builder,
test_filter: ?[]const u8,