2017-04-19 11:41:59 -07:00
|
|
|
const tests = @import("tests.zig");
|
|
|
|
|
2018-01-25 01:10:11 -08:00
|
|
|
pub fn addCases(cases: &tests.CompareOutputContext) void {
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("calling panic",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-02-08 00:02:41 -08:00
|
|
|
\\pub fn main() void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ @panic("oh no");
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("out of bounds slice access",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-02-08 00:02:41 -08:00
|
|
|
\\pub fn main() void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const a = []i32{1, 2, 3, 4};
|
|
|
|
\\ baz(bar(a));
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn bar(a: []const i32) i32 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return a[4];
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn baz(a: i32) void { }
|
2017-04-19 11:41:59 -07:00
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("integer addition overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = add(65530, 10);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn add(a: u16, b: u16) u16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return a + b;
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("integer subtraction overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = sub(10, 20);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn sub(a: u16, b: u16) u16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return a - b;
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("integer multiplication overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = mul(300, 6000);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn mul(a: u16, b: u16) u16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return a * b;
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("integer negation overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = neg(-32768);
|
|
|
|
\\ if (x == 32767) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn neg(a: i16) i16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return -a;
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("signed integer division overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = div(-32768, -1);
|
|
|
|
\\ if (x == 32767) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn div(a: i16, b: i16) i16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return @divTrunc(a, b);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("signed shift left overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = shl(-16385, 1);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn shl(a: i16, b: u4) i16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return @shlExact(a, b);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("unsigned shift left overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = shl(0b0010111111111111, 3);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn shl(a: u16, b: u4) u16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return @shlExact(a, b);
|
2017-08-09 07:09:38 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("signed shift right overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-08-09 07:09:38 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-08-09 07:09:38 -07:00
|
|
|
\\ const x = shr(-16385, 1);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn shr(a: i16, b: u4) i16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return @shrExact(a, b);
|
2017-08-09 07:09:38 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("unsigned shift right overflow",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-08-09 07:09:38 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-08-09 07:09:38 -07:00
|
|
|
\\ const x = shr(0b0010111111111111, 3);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn shr(a: u16, b: u4) u16 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return @shrExact(a, b);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("integer division by zero",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-02-08 00:02:41 -08:00
|
|
|
\\pub fn main() void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = div0(999, 0);
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn div0(a: i32, b: i32) i32 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return @divTrunc(a, b);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("exact division failure",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = divExact(10, 3);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn divExact(a: i32, b: i32) i32 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return @divExact(a, b);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = widenSlice([]u8{1, 2, 3, 4, 5});
|
|
|
|
\\ if (x.len == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return ([]align(1) const i32)(slice);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("value does not fit in shortening cast",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = shorten_cast(200);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn shorten_cast(x: i32) i8 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return i8(x);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ const x = unsigned_cast(-10);
|
|
|
|
\\ if (x == 0) return error.Whatever;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn unsigned_cast(x: i32) u32 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return u32(x);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("unwrap error",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2018-01-07 15:12:56 -08:00
|
|
|
\\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {
|
|
|
|
\\ @import("std").os.exit(126); // good
|
|
|
|
\\ }
|
|
|
|
\\ @import("std").os.exit(0); // test failed
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-02-08 00:02:41 -08:00
|
|
|
\\pub fn main() void {
|
2018-01-07 15:12:56 -08:00
|
|
|
\\ bar() catch unreachable;
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\fn bar() !void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ return error.Whatever;
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-02-08 18:54:44 -08:00
|
|
|
cases.addRuntimeSafety("cast integer to global error and no code matches",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-04-19 11:41:59 -07:00
|
|
|
\\}
|
2018-02-08 00:02:41 -08:00
|
|
|
\\pub fn main() void {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ _ = bar(9999);
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn bar(x: u32) error {
|
2017-04-19 11:41:59 -07:00
|
|
|
\\ return error(x);
|
|
|
|
\\}
|
|
|
|
);
|
2017-08-29 20:33:25 -07:00
|
|
|
|
2018-02-08 18:54:44 -08:00
|
|
|
cases.addRuntimeSafety("cast integer to non-global error set and no match",
|
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
|
|
|
\\ @import("std").os.exit(126);
|
|
|
|
\\}
|
|
|
|
\\const Set1 = error{A, B};
|
|
|
|
\\const Set2 = error{A, C};
|
|
|
|
\\pub fn main() void {
|
|
|
|
\\ _ = foo(Set1.B);
|
|
|
|
\\}
|
|
|
|
\\fn foo(set1: Set1) Set2 {
|
|
|
|
\\ return Set2(set1);
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("@alignCast misaligned",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-10-15 21:20:51 -07:00
|
|
|
\\ @import("std").os.exit(126);
|
2017-08-29 20:33:25 -07:00
|
|
|
\\}
|
2018-01-31 19:48:40 -08:00
|
|
|
\\pub fn main() !void {
|
2017-08-30 01:54:33 -07:00
|
|
|
\\ var array align(4) = []u32{0x11111111, 0x11111111};
|
2017-08-29 20:33:25 -07:00
|
|
|
\\ const bytes = ([]u8)(array[0..]);
|
|
|
|
\\ if (foo(bytes) != 0x11111111) return error.Wrong;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn foo(bytes: []u8) u32 {
|
2017-08-29 20:33:25 -07:00
|
|
|
\\ const slice4 = bytes[1..5];
|
|
|
|
\\ const int_slice = ([]u32)(@alignCast(4, slice4));
|
|
|
|
\\ return int_slice[0];
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-16 18:15:15 -08:00
|
|
|
|
2018-01-24 22:46:12 -08:00
|
|
|
cases.addRuntimeSafety("bad union field access",
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
|
2017-11-16 18:15:15 -08:00
|
|
|
\\ @import("std").os.exit(126);
|
|
|
|
\\}
|
|
|
|
\\
|
|
|
|
\\const Foo = union {
|
|
|
|
\\ float: f32,
|
|
|
|
\\ int: u32,
|
|
|
|
\\};
|
|
|
|
\\
|
2018-02-08 00:02:41 -08:00
|
|
|
\\pub fn main() void {
|
2017-11-16 18:15:15 -08:00
|
|
|
\\ var f = Foo { .int = 42 };
|
|
|
|
\\ bar(&f);
|
|
|
|
\\}
|
|
|
|
\\
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn bar(f: &Foo) void {
|
2017-11-16 18:15:15 -08:00
|
|
|
\\ f.float = 12.34;
|
|
|
|
\\}
|
|
|
|
);
|
2018-03-24 19:05:29 -07:00
|
|
|
|
|
|
|
// 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: ?&@import("builtin").StackTrace) noreturn {
|
|
|
|
\\ std.os.exit(126);
|
|
|
|
\\}
|
|
|
|
\\
|
|
|
|
\\pub fn main() void {
|
|
|
|
\\ const p = nonFailing();
|
|
|
|
\\ resume p;
|
|
|
|
\\ const p2 = async<std.debug.global_allocator> printTrace(p) catch unreachable;
|
|
|
|
\\ cancel p2;
|
|
|
|
\\}
|
|
|
|
\\
|
|
|
|
\\fn nonFailing() promise->error!void {
|
|
|
|
\\ return async<std.debug.global_allocator> failing() catch unreachable;
|
|
|
|
\\}
|
|
|
|
\\
|
|
|
|
\\async fn failing() error!void {
|
|
|
|
\\ suspend;
|
|
|
|
\\ return error.Fail;
|
|
|
|
\\}
|
|
|
|
\\
|
|
|
|
\\async fn printTrace(p: promise->error!void) void {
|
|
|
|
\\ (await p) catch unreachable;
|
|
|
|
\\}
|
|
|
|
);
|
2017-04-19 11:41:59 -07:00
|
|
|
}
|