| author | |
| committer | |
| log | 802f220739c26081e3018fe7e77e199458ffa8ba |
| tree | 442689a62f99e8f0dc64e67e090e95d0aa2a0fda |
| parent | f32928c50dabde1dee40b7137beef0fe72e89b49 |
| parent | 0cd43b0f8686075cf9bb8b8655ca828bd329d60f |
| signature |
migrate runtime safety tests to the new test harness77 files changed, 1518 insertions(+), 1267 deletions(-)
build.zig+37-37| ... | @@ -40,10 +40,10 @@ pub fn build(b: *Builder) !void { | ... | @@ -40,10 +40,10 @@ pub fn build(b: *Builder) !void { |
| 40 | 40 | ||
| 41 | const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain"); | 41 | const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain"); |
| 42 | 42 | ||
| 43 | var test_stage2 = b.addTest("src/test.zig"); | 43 | var test_cases = b.addTest("src/test.zig"); |
| 44 | test_stage2.setBuildMode(mode); | 44 | test_cases.setBuildMode(mode); |
| 45 | test_stage2.addPackagePath("test_cases", "test/cases.zig"); | 45 | test_cases.addPackagePath("test_cases", "test/cases.zig"); |
| 46 | test_stage2.single_threaded = single_threaded; | 46 | test_cases.single_threaded = single_threaded; |
| 47 | 47 | ||
| 48 | const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"}); | 48 | const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"}); |
| 49 | 49 | ||
| ... | @@ -158,7 +158,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -158,7 +158,7 @@ pub fn build(b: *Builder) !void { |
| 158 | if (target.isWindows() and target.getAbi() == .gnu) { | 158 | if (target.isWindows() and target.getAbi() == .gnu) { |
| 159 | // LTO is currently broken on mingw, this can be removed when it's fixed. | 159 | // LTO is currently broken on mingw, this can be removed when it's fixed. |
| 160 | exe.want_lto = false; | 160 | exe.want_lto = false; |
| 161 | test_stage2.want_lto = false; | 161 | test_cases.want_lto = false; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | const exe_options = b.addOptions(); | 164 | const exe_options = b.addOptions(); |
| ... | @@ -175,7 +175,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -175,7 +175,7 @@ pub fn build(b: *Builder) !void { |
| 175 | 175 | ||
| 176 | if (link_libc) { | 176 | if (link_libc) { |
| 177 | exe.linkLibC(); | 177 | exe.linkLibC(); |
| 178 | test_stage2.linkLibC(); | 178 | test_cases.linkLibC(); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | const is_debug = mode == .Debug; | 181 | const is_debug = mode == .Debug; |
| ... | @@ -258,7 +258,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -258,7 +258,7 @@ pub fn build(b: *Builder) !void { |
| 258 | zig0.defineCMacro("ZIG_VERSION_PATCH", b.fmt("{d}", .{zig_version.patch})); | 258 | zig0.defineCMacro("ZIG_VERSION_PATCH", b.fmt("{d}", .{zig_version.patch})); |
| 259 | zig0.defineCMacro("ZIG_VERSION_STRING", b.fmt("\"{s}\"", .{version})); | 259 | zig0.defineCMacro("ZIG_VERSION_STRING", b.fmt("\"{s}\"", .{version})); |
| 260 | 260 | ||
| 261 | for ([_]*std.build.LibExeObjStep{ zig0, exe, test_stage2 }) |artifact| { | 261 | for ([_]*std.build.LibExeObjStep{ zig0, exe, test_cases }) |artifact| { |
| 262 | artifact.addIncludePath("src"); | 262 | artifact.addIncludePath("src"); |
| 263 | artifact.addIncludePath("deps/SoftFloat-3e/source/include"); | 263 | artifact.addIncludePath("deps/SoftFloat-3e/source/include"); |
| 264 | artifact.addIncludePath("deps/SoftFloat-3e-prebuilt"); | 264 | artifact.addIncludePath("deps/SoftFloat-3e-prebuilt"); |
| ... | @@ -335,11 +335,11 @@ pub fn build(b: *Builder) !void { | ... | @@ -335,11 +335,11 @@ pub fn build(b: *Builder) !void { |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx); | 337 | try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx); |
| 338 | try addCmakeCfgOptionsToExe(b, cfg, test_stage2, use_zig_libcxx); | 338 | try addCmakeCfgOptionsToExe(b, cfg, test_cases, use_zig_libcxx); |
| 339 | } else { | 339 | } else { |
| 340 | // Here we are -Denable-llvm but no cmake integration. | 340 | // Here we are -Denable-llvm but no cmake integration. |
| 341 | try addStaticLlvmOptionsToExe(exe); | 341 | try addStaticLlvmOptionsToExe(exe); |
| 342 | try addStaticLlvmOptionsToExe(test_stage2); | 342 | try addStaticLlvmOptionsToExe(test_cases); |
| 343 | } | 343 | } |
| 344 | } | 344 | } |
| 345 | 345 | ||
| ... | @@ -380,34 +380,35 @@ pub fn build(b: *Builder) !void { | ... | @@ -380,34 +380,35 @@ pub fn build(b: *Builder) !void { |
| 380 | 380 | ||
| 381 | const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter"); | 381 | const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter"); |
| 382 | 382 | ||
| 383 | const test_stage2_options = b.addOptions(); | 383 | const test_cases_options = b.addOptions(); |
| 384 | test_stage2.addOptions("build_options", test_stage2_options); | 384 | test_cases.addOptions("build_options", test_cases_options); |
| 385 | 385 | ||
| 386 | test_stage2_options.addOption(bool, "enable_logging", enable_logging); | 386 | test_cases_options.addOption(bool, "enable_logging", enable_logging); |
| 387 | test_stage2_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots); | 387 | test_cases_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots); |
| 388 | test_stage2_options.addOption(bool, "skip_non_native", skip_non_native); | 388 | test_cases_options.addOption(bool, "skip_non_native", skip_non_native); |
| 389 | test_stage2_options.addOption(bool, "skip_stage1", skip_stage1); | 389 | test_cases_options.addOption(bool, "skip_stage1", skip_stage1); |
| 390 | test_stage2_options.addOption(bool, "is_stage1", is_stage1); | 390 | test_cases_options.addOption(bool, "is_stage1", is_stage1); |
| 391 | test_stage2_options.addOption(bool, "omit_stage2", omit_stage2); | 391 | test_cases_options.addOption(bool, "omit_stage2", omit_stage2); |
| 392 | test_stage2_options.addOption(bool, "have_llvm", enable_llvm); | 392 | test_cases_options.addOption(bool, "have_llvm", enable_llvm); |
| 393 | test_stage2_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k); | 393 | test_cases_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k); |
| 394 | test_stage2_options.addOption(bool, "llvm_has_csky", llvm_has_csky); | 394 | test_cases_options.addOption(bool, "llvm_has_csky", llvm_has_csky); |
| 395 | test_stage2_options.addOption(bool, "llvm_has_ve", llvm_has_ve); | 395 | test_cases_options.addOption(bool, "llvm_has_ve", llvm_has_ve); |
| 396 | test_stage2_options.addOption(bool, "llvm_has_arc", llvm_has_arc); | 396 | test_cases_options.addOption(bool, "llvm_has_arc", llvm_has_arc); |
| 397 | test_stage2_options.addOption(bool, "enable_qemu", b.enable_qemu); | 397 | test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu); |
| 398 | test_stage2_options.addOption(bool, "enable_wine", b.enable_wine); | 398 | test_cases_options.addOption(bool, "enable_wine", b.enable_wine); |
| 399 | test_stage2_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime); | 399 | test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime); |
| 400 | test_stage2_options.addOption(bool, "enable_rosetta", b.enable_rosetta); | 400 | test_cases_options.addOption(bool, "enable_rosetta", b.enable_rosetta); |
| 401 | test_stage2_options.addOption(bool, "enable_darling", b.enable_darling); | 401 | test_cases_options.addOption(bool, "enable_darling", b.enable_darling); |
| 402 | test_stage2_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2); | 402 | test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2); |
| 403 | test_stage2_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir); | 403 | test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir); |
| 404 | test_stage2_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version)); | 404 | test_cases_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version)); |
| 405 | test_stage2_options.addOption(std.SemanticVersion, "semver", semver); | 405 | test_cases_options.addOption(std.SemanticVersion, "semver", semver); |
| 406 | 406 | test_cases_options.addOption(?[]const u8, "test_filter", test_filter); | |
| 407 | const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests"); | 407 | |
| 408 | test_stage2_step.dependOn(&test_stage2.step); | 408 | const test_cases_step = b.step("test-cases", "Run the main compiler test cases"); |
| 409 | test_cases_step.dependOn(&test_cases.step); | ||
| 409 | if (!skip_stage2_tests) { | 410 | if (!skip_stage2_tests) { |
| 410 | toolchain_step.dependOn(test_stage2_step); | 411 | toolchain_step.dependOn(test_cases_step); |
| 411 | } | 412 | } |
| 412 | 413 | ||
| 413 | var chosen_modes: [4]builtin.Mode = undefined; | 414 | var chosen_modes: [4]builtin.Mode = undefined; |
| ... | @@ -485,7 +486,6 @@ pub fn build(b: *Builder) !void { | ... | @@ -485,7 +486,6 @@ pub fn build(b: *Builder) !void { |
| 485 | toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes)); | 486 | toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes)); |
| 486 | toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes)); | 487 | toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes)); |
| 487 | toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); | 488 | toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); |
| 488 | toolchain_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); | ||
| 489 | toolchain_step.dependOn(tests.addTranslateCTests(b, test_filter)); | 489 | toolchain_step.dependOn(tests.addTranslateCTests(b, test_filter)); |
| 490 | if (!skip_run_translated_c) { | 490 | if (!skip_run_translated_c) { |
| 491 | toolchain_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target)); | 491 | toolchain_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target)); |
ci/azure/macos_script+1-2| ... | @@ -71,12 +71,11 @@ release/bin/zig build test-standalone -Denable-macos-sdk | ... | @@ -71,12 +71,11 @@ release/bin/zig build test-standalone -Denable-macos-sdk |
| 71 | release/bin/zig build test-stack-traces -Denable-macos-sdk | 71 | release/bin/zig build test-stack-traces -Denable-macos-sdk |
| 72 | release/bin/zig build test-cli -Denable-macos-sdk | 72 | release/bin/zig build test-cli -Denable-macos-sdk |
| 73 | release/bin/zig build test-asm-link -Denable-macos-sdk | 73 | release/bin/zig build test-asm-link -Denable-macos-sdk |
| 74 | release/bin/zig build test-runtime-safety -Denable-macos-sdk | ||
| 75 | release/bin/zig build test-translate-c -Denable-macos-sdk | 74 | release/bin/zig build test-translate-c -Denable-macos-sdk |
| 76 | release/bin/zig build test-run-translated-c -Denable-macos-sdk | 75 | release/bin/zig build test-run-translated-c -Denable-macos-sdk |
| 77 | release/bin/zig build docs -Denable-macos-sdk | 76 | release/bin/zig build docs -Denable-macos-sdk |
| 78 | release/bin/zig build test-fmt -Denable-macos-sdk | 77 | release/bin/zig build test-fmt -Denable-macos-sdk |
| 79 | release/bin/zig build test-stage2 -Denable-macos-sdk | 78 | release/bin/zig build test-cases -Denable-macos-sdk |
| 80 | 79 | ||
| 81 | if [ "${BUILD_REASON}" != "PullRequest" ]; then | 80 | if [ "${BUILD_REASON}" != "PullRequest" ]; then |
| 82 | mv ../LICENSE release/ | 81 | mv ../LICENSE release/ |
ci/drone/linux_script_test+1-2| ... | @@ -34,12 +34,11 @@ case "$1" in | ... | @@ -34,12 +34,11 @@ case "$1" in |
| 34 | ./build/zig build $BUILD_FLAGS test-stack-traces | 34 | ./build/zig build $BUILD_FLAGS test-stack-traces |
| 35 | ./build/zig build $BUILD_FLAGS test-cli | 35 | ./build/zig build $BUILD_FLAGS test-cli |
| 36 | ./build/zig build $BUILD_FLAGS test-asm-link | 36 | ./build/zig build $BUILD_FLAGS test-asm-link |
| 37 | ./build/zig build $BUILD_FLAGS test-runtime-safety | ||
| 38 | ./build/zig build $BUILD_FLAGS test-translate-c | 37 | ./build/zig build $BUILD_FLAGS test-translate-c |
| 39 | ;; | 38 | ;; |
| 40 | 7) | 39 | 7) |
| 41 | ./build/zig build $BUILD_FLAGS # test building self-hosted without LLVM | 40 | ./build/zig build $BUILD_FLAGS # test building self-hosted without LLVM |
| 42 | ./build/zig build $BUILD_FLAGS test-stage2 | 41 | ./build/zig build $BUILD_FLAGS test-cases |
| 43 | ;; | 42 | ;; |
| 44 | '') | 43 | '') |
| 45 | echo "error: expecting test group argument" | 44 | echo "error: expecting test group argument" |
ci/zinc/linux_test.sh+1-2| ... | @@ -69,12 +69,11 @@ $ZIG build test-standalone -fqemu -fwasmtime | ... | @@ -69,12 +69,11 @@ $ZIG build test-standalone -fqemu -fwasmtime |
| 69 | $ZIG build test-stack-traces -fqemu -fwasmtime | 69 | $ZIG build test-stack-traces -fqemu -fwasmtime |
| 70 | $ZIG build test-cli -fqemu -fwasmtime | 70 | $ZIG build test-cli -fqemu -fwasmtime |
| 71 | $ZIG build test-asm-link -fqemu -fwasmtime | 71 | $ZIG build test-asm-link -fqemu -fwasmtime |
| 72 | $ZIG build test-runtime-safety -fqemu -fwasmtime | ||
| 73 | $ZIG build test-translate-c -fqemu -fwasmtime | 72 | $ZIG build test-translate-c -fqemu -fwasmtime |
| 74 | $ZIG build test-run-translated-c -fqemu -fwasmtime | 73 | $ZIG build test-run-translated-c -fqemu -fwasmtime |
| 75 | $ZIG build docs -fqemu -fwasmtime | 74 | $ZIG build docs -fqemu -fwasmtime |
| 76 | $ZIG build test-fmt -fqemu -fwasmtime | 75 | $ZIG build test-fmt -fqemu -fwasmtime |
| 77 | $ZIG build test-stage2 -fqemu -fwasmtime | 76 | $ZIG build test-cases -fqemu -fwasmtime |
| 78 | 77 | ||
| 79 | # Produce the experimental std lib documentation. | 78 | # Produce the experimental std lib documentation. |
| 80 | mkdir -p "$RELEASE_STAGING/docs/std" | 79 | mkdir -p "$RELEASE_STAGING/docs/std" |
lib/std/Progress.zig+4-1| ... | @@ -93,7 +93,9 @@ pub const Node = struct { | ... | @@ -93,7 +93,9 @@ pub const Node = struct { |
| 93 | 93 | ||
| 94 | /// This is the same as calling `start` and then `end` on the returned `Node`. Thread-safe. | 94 | /// This is the same as calling `start` and then `end` on the returned `Node`. Thread-safe. |
| 95 | pub fn completeOne(self: *Node) void { | 95 | pub fn completeOne(self: *Node) void { |
| 96 | self.activate(); | 96 | if (self.parent) |parent| { |
| 97 | @atomicStore(?*Node, &parent.recently_updated_child, self, .Release); | ||
| 98 | } | ||
| 97 | _ = @atomicRmw(usize, &self.unprotected_completed_items, .Add, 1, .Monotonic); | 99 | _ = @atomicRmw(usize, &self.unprotected_completed_items, .Add, 1, .Monotonic); |
| 98 | self.context.maybeRefresh(); | 100 | self.context.maybeRefresh(); |
| 99 | } | 101 | } |
| ... | @@ -120,6 +122,7 @@ pub const Node = struct { | ... | @@ -120,6 +122,7 @@ pub const Node = struct { |
| 120 | pub fn activate(self: *Node) void { | 122 | pub fn activate(self: *Node) void { |
| 121 | if (self.parent) |parent| { | 123 | if (self.parent) |parent| { |
| 122 | @atomicStore(?*Node, &parent.recently_updated_child, self, .Release); | 124 | @atomicStore(?*Node, &parent.recently_updated_child, self, .Release); |
| 125 | self.context.maybeRefresh(); | ||
| 123 | } | 126 | } |
| 124 | } | 127 | } |
| 125 | 128 |
src/test.zig+24-1| ... | @@ -1201,6 +1201,9 @@ pub const TestContext = struct { | ... | @@ -1201,6 +1201,9 @@ pub const TestContext = struct { |
| 1201 | if (!build_options.have_llvm and case.backend == .llvm) | 1201 | if (!build_options.have_llvm and case.backend == .llvm) |
| 1202 | continue; | 1202 | continue; |
| 1203 | 1203 | ||
| 1204 | if (build_options.test_filter) |test_filter| { | ||
| 1205 | if (std.mem.indexOf(u8, case.name, test_filter) == null) continue; | ||
| 1206 | } | ||
| 1204 | var prg_node = root_node.start(case.name, case.updates.items.len); | 1207 | var prg_node = root_node.start(case.name, case.updates.items.len); |
| 1205 | prg_node.activate(); | 1208 | prg_node.activate(); |
| 1206 | defer prg_node.end(); | 1209 | defer prg_node.end(); |
| ... | @@ -1291,6 +1294,8 @@ pub const TestContext = struct { | ... | @@ -1291,6 +1294,8 @@ pub const TestContext = struct { |
| 1291 | 1294 | ||
| 1292 | if (case.is_test) { | 1295 | if (case.is_test) { |
| 1293 | try zig_args.append("test"); | 1296 | try zig_args.append("test"); |
| 1297 | } else if (update.case == .Execution) { | ||
| 1298 | try zig_args.append("run"); | ||
| 1294 | } else switch (case.output_mode) { | 1299 | } else switch (case.output_mode) { |
| 1295 | .Obj => try zig_args.append("build-obj"), | 1300 | .Obj => try zig_args.append("build-obj"), |
| 1296 | .Exe => try zig_args.append("build-exe"), | 1301 | .Exe => try zig_args.append("build-exe"), |
| ... | @@ -1330,6 +1335,7 @@ pub const TestContext = struct { | ... | @@ -1330,6 +1335,7 @@ pub const TestContext = struct { |
| 1330 | } | 1335 | } |
| 1331 | }, | 1336 | }, |
| 1332 | else => { | 1337 | else => { |
| 1338 | std.debug.print("{s}", .{result.stderr}); | ||
| 1333 | dumpArgs(zig_args.items); | 1339 | dumpArgs(zig_args.items); |
| 1334 | return error.CompilationCrashed; | 1340 | return error.CompilationCrashed; |
| 1335 | }, | 1341 | }, |
| ... | @@ -1394,7 +1400,24 @@ pub const TestContext = struct { | ... | @@ -1394,7 +1400,24 @@ pub const TestContext = struct { |
| 1394 | } | 1400 | } |
| 1395 | }, | 1401 | }, |
| 1396 | .CompareObjectFile => @panic("TODO implement in the test harness"), | 1402 | .CompareObjectFile => @panic("TODO implement in the test harness"), |
| 1397 | .Execution => @panic("TODO implement in the test harness"), | 1403 | .Execution => |expected_stdout| { |
| 1404 | switch (result.term) { | ||
| 1405 | .Exited => |code| { | ||
| 1406 | if (code != 0) { | ||
| 1407 | std.debug.print("{s}", .{result.stderr}); | ||
| 1408 | dumpArgs(zig_args.items); | ||
| 1409 | return error.CompilationFailed; | ||
| 1410 | } | ||
| 1411 | }, | ||
| 1412 | else => { | ||
| 1413 | std.debug.print("{s}", .{result.stderr}); | ||
| 1414 | dumpArgs(zig_args.items); | ||
| 1415 | return error.CompilationCrashed; | ||
| 1416 | }, | ||
| 1417 | } | ||
| 1418 | try std.testing.expectEqualStrings("", result.stderr); | ||
| 1419 | try std.testing.expectEqualStrings(expected_stdout, result.stdout); | ||
| 1420 | }, | ||
| 1398 | .Header => @panic("TODO implement in the test harness"), | 1421 | .Header => @panic("TODO implement in the test harness"), |
| 1399 | } | 1422 | } |
| 1400 | return; | 1423 | return; |
test/cases/README.md created+61| ... | @@ -0,0 +1,61 @@ | ||
| 1 | # Test Case Quick Reference | ||
| 2 | |||
| 3 | Use comments at the **end of the file** to indicate metadata about the test | ||
| 4 | case. Here are examples of different kinds of tests: | ||
| 5 | |||
| 6 | ## Compile Error Test | ||
| 7 | |||
| 8 | If you want it to be run with `zig test` and match expected error messages: | ||
| 9 | |||
| 10 | ```zig | ||
| 11 | // error | ||
| 12 | // is_test=1 | ||
| 13 | // | ||
| 14 | // :4:13: error: 'try' outside function scope | ||
| 15 | ``` | ||
| 16 | |||
| 17 | ## Execution | ||
| 18 | |||
| 19 | This will do `zig run` on the code and expect exit code 0. | ||
| 20 | |||
| 21 | ```zig | ||
| 22 | // run | ||
| 23 | ``` | ||
| 24 | |||
| 25 | ## Incremental Compilation | ||
| 26 | |||
| 27 | Make multiple files that have ".", and then an integer, before the ".zig" | ||
| 28 | extension, like this: | ||
| 29 | |||
| 30 | ``` | ||
| 31 | hello.0.zig | ||
| 32 | hello.1.zig | ||
| 33 | hello.2.zig | ||
| 34 | ``` | ||
| 35 | |||
| 36 | Each file can be a different kind of test, such as expecting compile errors, | ||
| 37 | or expecting to be run and exit(0). The test harness will use these to simulate | ||
| 38 | incremental compilation. | ||
| 39 | |||
| 40 | At the time of writing there is no way to specify multiple files being changed | ||
| 41 | as part of an update. | ||
| 42 | |||
| 43 | ## Subdirectories | ||
| 44 | |||
| 45 | Subdirectories do not have any semantic meaning but they can be used for | ||
| 46 | organization since the test harness will recurse into them. The full directory | ||
| 47 | path will be prepended as a prefix on the test case name. | ||
| 48 | |||
| 49 | ## Limiting which Backends and Targets are Tested | ||
| 50 | |||
| 51 | ```zig | ||
| 52 | // run | ||
| 53 | // backend=stage2,llvm | ||
| 54 | // target=x86_64-linux,x86_64-macos | ||
| 55 | ``` | ||
| 56 | |||
| 57 | Possible backends are: | ||
| 58 | |||
| 59 | * `stage1`: equivalent to `-fstage1`. | ||
| 60 | * `stage2`: equivalent to passing `-fno-stage1 -fno-LLVM`. | ||
| 61 | * `llvm`: equivalent to `-fLLVM -fno-stage1`. | ||
test/cases/safety/@alignCast misaligned.zig	 created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | var array align(4) = [_]u32{0x11111111, 0x11111111}; | ||
| 11 | const bytes = std.mem.sliceAsBytes(array[0..]); | ||
| 12 | if (foo(bytes) != 0x11111111) return error.Wrong; | ||
| 13 | return error.TestFailed; | ||
| 14 | } | ||
| 15 | fn foo(bytes: []u8) u32 { | ||
| 16 | const slice4 = bytes[1..5]; | ||
| 17 | const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4)); | ||
| 18 | return int_slice[0]; | ||
| 19 | } | ||
| 20 | // run | ||
| 21 | // backend=stage1 | ||
| 22 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/@asyncCall with too small a frame.zig	 created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 5 | _ = message; | ||
| 6 | _ = stack_trace; | ||
| 7 | std.process.exit(0); | ||
| 8 | } | ||
| 9 | pub fn main() !void { | ||
| 10 | if (builtin.zig_backend == .stage1 and builtin.os.tag == .wasi) { | ||
| 11 | // TODO file a bug for this failure | ||
| 12 | std.process.exit(0); // skip the test | ||
| 13 | } | ||
| 14 | var bytes: [1]u8 align(16) = undefined; | ||
| 15 | var ptr = other; | ||
| 16 | var frame = @asyncCall(&bytes, {}, ptr, .{}); | ||
| 17 | _ = frame; | ||
| 18 | return error.TestFailed; | ||
| 19 | } | ||
| 20 | fn other() callconv(.Async) void { | ||
| 21 | suspend {} | ||
| 22 | } | ||
| 23 | // run | ||
| 24 | // backend=stage1 | ||
| 25 | // target=native | ||
test/cases/safety/@errSetCast error not present in destination.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | const Set1 = error{A, B}; | ||
| 9 | const Set2 = error{A, C}; | ||
| 10 | pub fn main() !void { | ||
| 11 | foo(Set1.B) catch {}; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn foo(set1: Set1) Set2 { | ||
| 15 | return @errSetCast(Set2, set1); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/@floatToInt cannot fit - negative out of range.zig	 created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | baz(bar(-129.1)); | ||
| 10 | return error.TestFailed; | ||
| 11 | } | ||
| 12 | fn bar(a: f32) i8 { | ||
| 13 | return @floatToInt(i8, a); | ||
| 14 | } | ||
| 15 | fn baz(_: i8) void { } | ||
| 16 | // run | ||
| 17 | // backend=stage1 | ||
| 18 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/@floatToInt cannot fit - negative to unsigned.zig	 created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | baz(bar(-1.1)); | ||
| 10 | return error.TestFailed; | ||
| 11 | } | ||
| 12 | fn bar(a: f32) u8 { | ||
| 13 | return @floatToInt(u8, a); | ||
| 14 | } | ||
| 15 | fn baz(_: u8) void { } | ||
| 16 | // run | ||
| 17 | // backend=stage1 | ||
| 18 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/@floatToInt cannot fit - positive out of range.zig	 created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | baz(bar(256.2)); | ||
| 10 | return error.TestFailed; | ||
| 11 | } | ||
| 12 | fn bar(a: f32) u8 { | ||
| 13 | return @floatToInt(u8, a); | ||
| 14 | } | ||
| 15 | fn baz(_: u8) void { } | ||
| 16 | // run | ||
| 17 | // backend=stage1 | ||
| 18 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/@intCast to u0.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | bar(1, 1); | ||
| 11 | return error.TestFailed; | ||
| 12 | } | ||
| 13 | |||
| 14 | fn bar(one: u1, not_zero: i32) void { | ||
| 15 | var x = one << @intCast(u0, not_zero); | ||
| 16 | _ = x; | ||
| 17 | } | ||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/@intToEnum - no matching tag value.zig	 created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | const Foo = enum { | ||
| 9 | A, | ||
| 10 | B, | ||
| 11 | C, | ||
| 12 | }; | ||
| 13 | pub fn main() !void { | ||
| 14 | baz(bar(3)); | ||
| 15 | return error.TestFailed; | ||
| 16 | } | ||
| 17 | fn bar(a: u2) Foo { | ||
| 18 | return @intToEnum(Foo, a); | ||
| 19 | } | ||
| 20 | fn baz(_: Foo) void {} | ||
| 21 | // run | ||
| 22 | // backend=stage1 | ||
| 23 | // target=native | ||
test/cases/safety/@intToPtr address zero to non-optional byte-aligned pointer.zig	 created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var zero: usize = 0; | ||
| 10 | var b = @intToPtr(*u8, zero); | ||
| 11 | _ = b; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | // run | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
test/cases/safety/@intToPtr address zero to non-optional pointer.zig	 created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var zero: usize = 0; | ||
| 10 | var b = @intToPtr(*i32, zero); | ||
| 11 | _ = b; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | // run | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
test/cases/safety/@tagName on corrupted enum value.zig	 created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "invalid enum value")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | const E = enum(u32) { | ||
| 12 | X = 1, | ||
| 13 | }; | ||
| 14 | |||
| 15 | pub fn main() !void { | ||
| 16 | var e: E = undefined; | ||
| 17 | @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E)); | ||
| 18 | var n = @tagName(e); | ||
| 19 | _ = n; | ||
| 20 | return error.TestFailed; | ||
| 21 | } | ||
| 22 | |||
| 23 | // run | ||
| 24 | // backend=stage1 | ||
| 25 | // target=native | ||
test/cases/safety/@tagName on corrupted union value.zig	 created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "invalid enum value")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | const U = union(enum(u32)) { | ||
| 12 | X: u8, | ||
| 13 | }; | ||
| 14 | |||
| 15 | pub fn main() !void { | ||
| 16 | var u: U = undefined; | ||
| 17 | @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U)); | ||
| 18 | var t: @typeInfo(U).Union.tag_type.? = u; | ||
| 19 | var n = @tagName(t); | ||
| 20 | _ = n; | ||
| 21 | return error.TestFailed; | ||
| 22 | } | ||
| 23 | |||
| 24 | // run | ||
| 25 | // backend=stage1 | ||
| 26 | // target=native | ||
test/cases/safety/array slice sentinel mismatch.zig	 created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | pub fn main() !void { | ||
| 11 | var buf: [4]u8 = undefined; | ||
| 12 | const slice = buf[0..3 :0]; | ||
| 13 | _ = slice; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | // run | ||
| 17 | // backend=stage1 | ||
| 18 | // target=native | ||
test/cases/safety/awaiting twice.zig	 created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | var frame: anyframe = undefined; | ||
| 9 | |||
| 10 | pub fn main() !void { | ||
| 11 | _ = async amain(); | ||
| 12 | resume frame; | ||
| 13 | return error.TestFailed; | ||
| 14 | } | ||
| 15 | |||
| 16 | fn amain() void { | ||
| 17 | var f = async func(); | ||
| 18 | await f; | ||
| 19 | await f; | ||
| 20 | } | ||
| 21 | |||
| 22 | fn func() void { | ||
| 23 | suspend { | ||
| 24 | frame = @frame(); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | // run | ||
| 28 | // backend=stage1 | ||
| 29 | // target=native | ||
test/cases/safety/bad union field access.zig	 created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | const Foo = union { | ||
| 10 | float: f32, | ||
| 11 | int: u32, | ||
| 12 | }; | ||
| 13 | |||
| 14 | pub fn main() !void { | ||
| 15 | var f = Foo { .int = 42 }; | ||
| 16 | bar(&f); | ||
| 17 | return error.TestFailed; | ||
| 18 | } | ||
| 19 | |||
| 20 | fn bar(f: *Foo) void { | ||
| 21 | f.float = 12.34; | ||
| 22 | } | ||
| 23 | // run | ||
| 24 | // backend=stage1 | ||
| 25 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/calling panic.zig	 created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "oh no")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | pub fn main() !void { | ||
| 11 | if (true) @panic("oh no"); | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | // run | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/cast []u8 to bigger slice of wrong size.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = widenSlice(&[_]u8{1, 2, 3, 4, 5}); | ||
| 11 | if (x.len == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { | ||
| 15 | return std.mem.bytesAsSlice(i32, slice); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/cast integer to global error and no code matches.zig	 created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | bar(9999) catch {}; | ||
| 10 | return error.TestFailed; | ||
| 11 | } | ||
| 12 | fn bar(x: u16) anyerror { | ||
| 13 | return @intToError(x); | ||
| 14 | } | ||
| 15 | // run | ||
| 16 | // backend=stage1 | ||
| 17 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/empty slice with sentinel out of bounds.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "index out of bounds")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var buf_zero = [0]u8{}; | ||
| 13 | const input: []u8 = &buf_zero; | ||
| 14 | const slice = input[0..0 :0]; | ||
| 15 | _ = slice; | ||
| 16 | return error.TestFailed; | ||
| 17 | } | ||
| 18 | |||
| 19 | // run | ||
| 20 | // backend=stage1 | ||
| 21 | // target=native | ||
test/cases/safety/error return trace across suspend points.zig	 created+39| ... | @@ -0,0 +1,39 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | |||
| 4 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 5 | _ = message; | ||
| 6 | _ = stack_trace; | ||
| 7 | std.process.exit(0); | ||
| 8 | } | ||
| 9 | |||
| 10 | var failing_frame: @Frame(failing) = undefined; | ||
| 11 | |||
| 12 | pub fn main() !void { | ||
| 13 | const p = nonFailing(); | ||
| 14 | resume p; | ||
| 15 | const p2 = async printTrace(p); | ||
| 16 | _ = p2; | ||
| 17 | return error.TestFailed; | ||
| 18 | } | ||
| 19 | |||
| 20 | fn nonFailing() anyframe->anyerror!void { | ||
| 21 | failing_frame = async failing(); | ||
| 22 | return &failing_frame; | ||
| 23 | } | ||
| 24 | |||
| 25 | fn failing() anyerror!void { | ||
| 26 | suspend {} | ||
| 27 | return second(); | ||
| 28 | } | ||
| 29 | |||
| 30 | fn second() callconv(.Async) anyerror!void { | ||
| 31 | return error.Fail; | ||
| 32 | } | ||
| 33 | |||
| 34 | fn printTrace(p: anyframe->anyerror!void) void { | ||
| 35 | (await p) catch unreachable; | ||
| 36 | } | ||
| 37 | // run | ||
| 38 | // backend=stage1 | ||
| 39 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/exact division failure - vectors.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444}; | ||
| 11 | var b: @Vector(4, i32) = [4]i32{111, 222, 333, 441}; | ||
| 12 | const x = divExact(a, b); | ||
| 13 | _ = x; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ||
| 17 | return @divExact(a, b); | ||
| 18 | } | ||
| 19 | // run | ||
| 20 | // backend=stage1 | ||
| 21 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/exact division failure.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = divExact(10, 3); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn divExact(a: i32, b: i32) i32 { | ||
| 15 | return @divExact(a, b); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/intToPtr with misaligned address.zig	 created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "incorrect alignment")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | pub fn main() !void { | ||
| 11 | var x: usize = 5; | ||
| 12 | var y = @intToPtr([*]align(4) u8, x); | ||
| 13 | _ = y; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | // run | ||
| 17 | // backend=stage1 | ||
| 18 | // target=native | ||
test/cases/safety/integer addition overflow.zig	 created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "integer overflow")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | const x = add(65530, 10); | ||
| 13 | if (x == 0) return error.Whatever; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | |||
| 17 | fn add(a: u16, b: u16) u16 { | ||
| 18 | return a + b; | ||
| 19 | } | ||
| 20 | |||
| 21 | // run | ||
| 22 | // backend=stage1 | ||
| 23 | // target=native | ||
test/cases/safety/integer division by zero - vectors.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444}; | ||
| 10 | var b: @Vector(4, i32) = [4]i32{111, 0, 333, 444}; | ||
| 11 | const x = div0(a, b); | ||
| 12 | _ = x; | ||
| 13 | return error.TestFailed; | ||
| 14 | } | ||
| 15 | fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ||
| 16 | return @divTrunc(a, b); | ||
| 17 | } | ||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/integer division by zero.zig	 created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | const x = div0(999, 0); | ||
| 10 | _ = x; | ||
| 11 | return error.TestFailed; | ||
| 12 | } | ||
| 13 | fn div0(a: i32, b: i32) i32 { | ||
| 14 | return @divTrunc(a, b); | ||
| 15 | } | ||
| 16 | // run | ||
| 17 | // backend=stage1 | ||
| 18 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/integer multiplication overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = mul(300, 6000); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn mul(a: u16, b: u16) u16 { | ||
| 15 | return a * b; | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/integer negation overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = neg(-32768); | ||
| 11 | if (x == 32767) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn neg(a: i16) i16 { | ||
| 15 | return -a; | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/integer subtraction overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = sub(10, 20); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn sub(a: u16, b: u16) u16 { | ||
| 15 | return a - b; | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/invalid resume of async function.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var p = async suspendOnce(); | ||
| 10 | resume p; //ok | ||
| 11 | resume p; //bad | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn suspendOnce() void { | ||
| 15 | suspend {} | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
test/cases/safety/nosuspend function call, callee suspends.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | _ = nosuspend add(101, 100); | ||
| 10 | return error.TestFailed; | ||
| 11 | } | ||
| 12 | fn add(a: i32, b: i32) i32 { | ||
| 13 | if (a > 100) { | ||
| 14 | suspend {} | ||
| 15 | } | ||
| 16 | return a + b; | ||
| 17 | } | ||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
test/cases/safety/optional unwrap operator on C pointer.zig	 created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var ptr: [*c]i32 = null; | ||
| 10 | var b = ptr.?; | ||
| 11 | _ = b; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | // run | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
test/cases/safety/optional unwrap operator on null pointer.zig	 created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var ptr: ?*i32 = null; | ||
| 10 | var b = ptr.?; | ||
| 11 | _ = b; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | // run | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
test/cases/safety/out of bounds slice access.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | const a = [_]i32{1, 2, 3, 4}; | ||
| 10 | baz(bar(&a)); | ||
| 11 | return error.TestFailed; | ||
| 12 | } | ||
| 13 | fn bar(a: []const i32) i32 { | ||
| 14 | return a[4]; | ||
| 15 | } | ||
| 16 | fn baz(_: i32) void { } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/pointer casting null to non-optional pointer.zig	 created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var c_ptr: [*c]u8 = 0; | ||
| 10 | var zig_ptr: *u8 = c_ptr; | ||
| 11 | _ = zig_ptr; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | // run | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
test/cases/safety/pointer slice sentinel mismatch.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var buf: [4]u8 = undefined; | ||
| 13 | const ptr: [*]u8 = &buf; | ||
| 14 | const slice = ptr[0..3 :0]; | ||
| 15 | _ = slice; | ||
| 16 | return error.TestFailed; | ||
| 17 | } | ||
| 18 | |||
| 19 | // run | ||
| 20 | // backend=stage1 | ||
| 21 | // target=native | ||
test/cases/safety/resuming a function which is awaiting a call.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var frame = async first(); | ||
| 10 | resume frame; | ||
| 11 | return error.TestFailed; | ||
| 12 | } | ||
| 13 | fn first() void { | ||
| 14 | other(); | ||
| 15 | } | ||
| 16 | fn other() void { | ||
| 17 | suspend {} | ||
| 18 | } | ||
| 19 | // run | ||
| 20 | // backend=stage1 | ||
| 21 | // target=native | ||
test/cases/safety/resuming a function which is awaiting a frame.zig	 created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var frame = async first(); | ||
| 10 | resume frame; | ||
| 11 | return error.TestFailed; | ||
| 12 | } | ||
| 13 | fn first() void { | ||
| 14 | var frame = async other(); | ||
| 15 | await frame; | ||
| 16 | } | ||
| 17 | fn other() void { | ||
| 18 | suspend {} | ||
| 19 | } | ||
| 20 | // run | ||
| 21 | // backend=stage1 | ||
| 22 | // target=native | ||
test/cases/safety/resuming a non-suspended function which has been suspended and resumed.zig	 created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | fn foo() void { | ||
| 9 | suspend { | ||
| 10 | global_frame = @frame(); | ||
| 11 | } | ||
| 12 | var f = async bar(@frame()); | ||
| 13 | _ = f; | ||
| 14 | std.os.exit(1); | ||
| 15 | } | ||
| 16 | |||
| 17 | fn bar(frame: anyframe) void { | ||
| 18 | suspend { | ||
| 19 | resume frame; | ||
| 20 | } | ||
| 21 | std.os.exit(1); | ||
| 22 | } | ||
| 23 | |||
| 24 | var global_frame: anyframe = undefined; | ||
| 25 | pub fn main() !void { | ||
| 26 | _ = async foo(); | ||
| 27 | resume global_frame; | ||
| 28 | std.os.exit(1); | ||
| 29 | } | ||
| 30 | // run | ||
| 31 | // backend=stage1 | ||
| 32 | // target=native | ||
test/cases/safety/resuming a non-suspended function which never been suspended.zig	 created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | fn foo() void { | ||
| 9 | var f = async bar(@frame()); | ||
| 10 | _ = f; | ||
| 11 | std.os.exit(1); | ||
| 12 | } | ||
| 13 | |||
| 14 | fn bar(frame: anyframe) void { | ||
| 15 | suspend { | ||
| 16 | resume frame; | ||
| 17 | } | ||
| 18 | std.os.exit(1); | ||
| 19 | } | ||
| 20 | |||
| 21 | pub fn main() !void { | ||
| 22 | _ = async foo(); | ||
| 23 | return error.TestFailed; | ||
| 24 | } | ||
| 25 | // run | ||
| 26 | // backend=stage1 | ||
| 27 | // target=native | ||
test/cases/safety/shift left by huge amount.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "shift amount is greater than the type size")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var x: u24 = 42; | ||
| 13 | var y: u5 = 24; | ||
| 14 | var z = x >> y; | ||
| 15 | _ = z; | ||
| 16 | return error.TestFailed; | ||
| 17 | } | ||
| 18 | |||
| 19 | // run | ||
| 20 | // backend=stage1 | ||
| 21 | // target=native | ||
test/cases/safety/shift right by huge amount.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "shift amount is greater than the type size")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var x: u24 = 42; | ||
| 13 | var y: u5 = 24; | ||
| 14 | var z = x << y; | ||
| 15 | _ = z; | ||
| 16 | return error.TestFailed; | ||
| 17 | } | ||
| 18 | |||
| 19 | // run | ||
| 20 | // backend=stage1 | ||
| 21 | // target=native | ||
test/cases/safety/signed integer division overflow - vectors.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | var a: @Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 }; | ||
| 11 | var b: @Vector(4, i16) = [_]i16{ 1, 2, -1, 4 }; | ||
| 12 | const x = div(a, b); | ||
| 13 | if (x[2] == 32767) return error.Whatever; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) { | ||
| 17 | return @divTrunc(a, b); | ||
| 18 | } | ||
| 19 | // run | ||
| 20 | // backend=stage1 | ||
| 21 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/signed integer division overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = div(-32768, -1); | ||
| 11 | if (x == 32767) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn div(a: i16, b: i16) i16 { | ||
| 15 | return @divTrunc(a, b); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig	 created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var value: c_short = -1; | ||
| 10 | var casted = @intCast(u32, value); | ||
| 11 | _ = casted; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | // run | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/signed integer not fitting in cast to unsigned integer.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = unsigned_cast(-10); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn unsigned_cast(x: i32) u32 { | ||
| 15 | return @intCast(u32, x); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/signed shift left overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = shl(-16385, 1); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn shl(a: i16, b: u4) i16 { | ||
| 15 | return @shlExact(a, b); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/signed shift right overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = shr(-16385, 1); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn shr(a: i16, b: u4) i16 { | ||
| 15 | return @shrExact(a, b); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/signed-unsigned vector cast.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var x = @splat(4, @as(i32, -2147483647)); | ||
| 13 | var y = @intCast(@Vector(4, u32), x); | ||
| 14 | _ = y; | ||
| 15 | return error.TestFailed; | ||
| 16 | } | ||
| 17 | |||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
test/cases/safety/slice sentinel mismatch - floats.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var buf: [4]f32 = undefined; | ||
| 13 | const slice = buf[0..3 :1.2]; | ||
| 14 | _ = slice; | ||
| 15 | return error.TestFailed; | ||
| 16 | } | ||
| 17 | |||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
test/cases/safety/slice sentinel mismatch - optional pointers.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var buf: [4]?*i32 = undefined; | ||
| 13 | const slice = buf[0..3 :null]; | ||
| 14 | _ = slice; | ||
| 15 | return error.TestFailed; | ||
| 16 | } | ||
| 17 | |||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
test/cases/safety/slice slice sentinel mismatch.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | pub fn main() !void { | ||
| 11 | var buf: [4]u8 = undefined; | ||
| 12 | const slice = buf[0..]; | ||
| 13 | const slice2 = slice[0..3 :0]; | ||
| 14 | _ = slice2; | ||
| 15 | return error.TestFailed; | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
test/cases/safety/slice with sentinel out of bounds.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "index out of bounds")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var buf = [4]u8{ 'a', 'b', 'c', 0 }; | ||
| 13 | const input: []u8 = &buf; | ||
| 14 | const slice = input[0..4 :0]; | ||
| 15 | _ = slice; | ||
| 16 | return error.TestFailed; | ||
| 17 | } | ||
| 18 | |||
| 19 | // run | ||
| 20 | // backend=stage1 | ||
| 21 | // target=native | ||
test/cases/safety/slicing null C pointer.zig	 created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | var ptr: [*c]const u32 = null; | ||
| 11 | var slice = ptr[0..3]; | ||
| 12 | _ = slice; | ||
| 13 | return error.TestFailed; | ||
| 14 | } | ||
| 15 | // run | ||
| 16 | // backend=stage1 | ||
| 17 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/switch on corrupted enum value.zig	 created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "reached unreachable code")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | const E = enum(u32) { | ||
| 12 | X = 1, | ||
| 13 | }; | ||
| 14 | |||
| 15 | pub fn main() !void { | ||
| 16 | var e: E = undefined; | ||
| 17 | @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E)); | ||
| 18 | switch (e) { | ||
| 19 | .X => @breakpoint(), | ||
| 20 | } | ||
| 21 | return error.TestFailed; | ||
| 22 | } | ||
| 23 | |||
| 24 | // run | ||
| 25 | // backend=stage1 | ||
| 26 | // target=native | ||
test/cases/safety/switch on corrupted union value.zig	 created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "reached unreachable code")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | const U = union(enum(u32)) { | ||
| 12 | X: u8, | ||
| 13 | }; | ||
| 14 | |||
| 15 | pub fn main() !void { | ||
| 16 | var u: U = undefined; | ||
| 17 | @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U)); | ||
| 18 | switch (u) { | ||
| 19 | .X => @breakpoint(), | ||
| 20 | } | ||
| 21 | return error.TestFailed; | ||
| 22 | } | ||
| 23 | |||
| 24 | // run | ||
| 25 | // backend=stage1 | ||
| 26 | // target=native | ||
test/cases/safety/truncating vector cast.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "integer cast truncated bits")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var x = @splat(4, @as(u32, 0xdeadbeef)); | ||
| 13 | var y = @intCast(@Vector(4, u16), x); | ||
| 14 | _ = y; | ||
| 15 | return error.TestFailed; | ||
| 16 | } | ||
| 17 | |||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig	 created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var value: u8 = 245; | ||
| 10 | var casted = @intCast(i8, value); | ||
| 11 | _ = casted; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | // run | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/unsigned shift left overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = shl(0b0010111111111111, 3); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn shl(a: u16, b: u4) u16 { | ||
| 15 | return @shlExact(a, b); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/unsigned shift right overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = shr(0b0010111111111111, 3); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn shr(a: u16, b: u4) u16 { | ||
| 15 | return @shrExact(a, b); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/unsigned-signed vector cast.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "integer cast truncated bits")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn main() !void { | ||
| 12 | var x = @splat(4, @as(u32, 0x80000000)); | ||
| 13 | var y = @intCast(@Vector(4, i32), x); | ||
| 14 | _ = y; | ||
| 15 | return error.TestFailed; | ||
| 16 | } | ||
| 17 | |||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
test/cases/safety/unwrap error.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "attempt to unwrap error: Whatever")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | pub fn main() !void { | ||
| 11 | bar() catch unreachable; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn bar() !void { | ||
| 15 | return error.Whatever; | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/value does not fit in shortening cast - u0.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = shorten_cast(1); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn shorten_cast(x: u8) u0 { | ||
| 15 | return @intCast(u0, x); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/value does not fit in shortening cast.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub fn main() !void { | ||
| 10 | const x = shorten_cast(200); | ||
| 11 | if (x == 0) return error.Whatever; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn shorten_cast(x: i32) i8 { | ||
| 15 | return @intCast(i8, x); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/vector integer addition overflow.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var a: @Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 }; | ||
| 10 | var b: @Vector(4, i32) = [_]i32{ 5, 6, 7, 8 }; | ||
| 11 | const x = add(a, b); | ||
| 12 | _ = x; | ||
| 13 | return error.TestFailed; | ||
| 14 | } | ||
| 15 | fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ||
| 16 | return a + b; | ||
| 17 | } | ||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/vector integer multiplication overflow.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var a: @Vector(4, u8) = [_]u8{ 1, 2, 200, 4 }; | ||
| 10 | var b: @Vector(4, u8) = [_]u8{ 5, 6, 2, 8 }; | ||
| 11 | const x = mul(b, a); | ||
| 12 | _ = x; | ||
| 13 | return error.TestFailed; | ||
| 14 | } | ||
| 15 | fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) { | ||
| 16 | return a * b; | ||
| 17 | } | ||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/vector integer negation overflow.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var a: @Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 }; | ||
| 10 | const x = neg(a); | ||
| 11 | _ = x; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn neg(a: @Vector(4, i16)) @Vector(4, i16) { | ||
| 15 | return -a; | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=stage1 | ||
| 19 | // target=native | ||
| \ No newline at end of file | |||
test/cases/safety/vector integer subtraction overflow.zig	 created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = message; | ||
| 5 | _ = stack_trace; | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | var a: @Vector(4, u32) = [_]u32{ 1, 2, 8, 4 }; | ||
| 10 | var b: @Vector(4, u32) = [_]u32{ 5, 6, 7, 8 }; | ||
| 11 | const x = sub(b, a); | ||
| 12 | _ = x; | ||
| 13 | return error.TestFailed; | ||
| 14 | } | ||
| 15 | fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) { | ||
| 16 | return a - b; | ||
| 17 | } | ||
| 18 | // run | ||
| 19 | // backend=stage1 | ||
| 20 | // target=native | ||
| \ No newline at end of file | |||
test/runtime_safety.zig deleted-1206| ... | @@ -1,1206 +0,0 @@ | ||
| 1 | const tests = @import("tests.zig"); | ||
| 2 | |||
| 3 | pub fn addCases(cases: *tests.CompareOutputContext) void { | ||
| 4 | { | ||
| 5 | const check_panic_msg = | ||
| 6 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 7 | \\ _ = stack_trace; | ||
| 8 | \\ if (std.mem.eql(u8, message, "reached unreachable code")) { | ||
| 9 | \\ std.process.exit(126); // good | ||
| 10 | \\ } | ||
| 11 | \\ std.process.exit(0); // test failed | ||
| 12 | \\} | ||
| 13 | ; | ||
| 14 | |||
| 15 | cases.addRuntimeSafety("switch on corrupted enum value", | ||
| 16 | \\const std = @import("std"); | ||
| 17 | ++ check_panic_msg ++ | ||
| 18 | \\const E = enum(u32) { | ||
| 19 | \\ X = 1, | ||
| 20 | \\}; | ||
| 21 | \\pub fn main() void { | ||
| 22 | \\ var e: E = undefined; | ||
| 23 | \\ @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E)); | ||
| 24 | \\ switch (e) { | ||
| 25 | \\ .X => @breakpoint(), | ||
| 26 | \\ } | ||
| 27 | \\} | ||
| 28 | ); | ||
| 29 | |||
| 30 | cases.addRuntimeSafety("switch on corrupted union value", | ||
| 31 | \\const std = @import("std"); | ||
| 32 | ++ check_panic_msg ++ | ||
| 33 | \\const U = union(enum(u32)) { | ||
| 34 | \\ X: u8, | ||
| 35 | \\}; | ||
| 36 | \\pub fn main() void { | ||
| 37 | \\ var u: U = undefined; | ||
| 38 | \\ @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U)); | ||
| 39 | \\ switch (u) { | ||
| 40 | \\ .X => @breakpoint(), | ||
| 41 | \\ } | ||
| 42 | \\} | ||
| 43 | ); | ||
| 44 | } | ||
| 45 | |||
| 46 | { | ||
| 47 | const check_panic_msg = | ||
| 48 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 49 | \\ _ = stack_trace; | ||
| 50 | \\ if (std.mem.eql(u8, message, "invalid enum value")) { | ||
| 51 | \\ std.process.exit(126); // good | ||
| 52 | \\ } | ||
| 53 | \\ std.process.exit(0); // test failed | ||
| 54 | \\} | ||
| 55 | ; | ||
| 56 | |||
| 57 | cases.addRuntimeSafety("@tagName on corrupted enum value", | ||
| 58 | \\const std = @import("std"); | ||
| 59 | ++ check_panic_msg ++ | ||
| 60 | \\const E = enum(u32) { | ||
| 61 | \\ X = 1, | ||
| 62 | \\}; | ||
| 63 | \\pub fn main() void { | ||
| 64 | \\ var e: E = undefined; | ||
| 65 | \\ @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E)); | ||
| 66 | \\ var n = @tagName(e); | ||
| 67 | \\ _ = n; | ||
| 68 | \\} | ||
| 69 | ); | ||
| 70 | |||
| 71 | cases.addRuntimeSafety("@tagName on corrupted union value", | ||
| 72 | \\const std = @import("std"); | ||
| 73 | ++ check_panic_msg ++ | ||
| 74 | \\const U = union(enum(u32)) { | ||
| 75 | \\ X: u8, | ||
| 76 | \\}; | ||
| 77 | \\pub fn main() void { | ||
| 78 | \\ var u: U = undefined; | ||
| 79 | \\ @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U)); | ||
| 80 | \\ var t: @typeInfo(U).Union.tag_type.? = u; | ||
| 81 | \\ var n = @tagName(t); | ||
| 82 | \\ _ = n; | ||
| 83 | \\} | ||
| 84 | ); | ||
| 85 | } | ||
| 86 | |||
| 87 | { | ||
| 88 | const check_panic_msg = | ||
| 89 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 90 | \\ _ = stack_trace; | ||
| 91 | \\ if (std.mem.eql(u8, message, "index out of bounds")) { | ||
| 92 | \\ std.process.exit(126); // good | ||
| 93 | \\ } | ||
| 94 | \\ std.process.exit(0); // test failed | ||
| 95 | \\} | ||
| 96 | ; | ||
| 97 | |||
| 98 | cases.addRuntimeSafety("slice with sentinel out of bounds", | ||
| 99 | \\const std = @import("std"); | ||
| 100 | ++ check_panic_msg ++ | ||
| 101 | \\pub fn main() void { | ||
| 102 | \\ var buf = [4]u8{'a','b','c',0}; | ||
| 103 | \\ const input: []u8 = &buf; | ||
| 104 | \\ const slice = input[0..4 :0]; | ||
| 105 | \\ _ = slice; | ||
| 106 | \\} | ||
| 107 | ); | ||
| 108 | cases.addRuntimeSafety("empty slice with sentinel out of bounds", | ||
| 109 | \\const std = @import("std"); | ||
| 110 | ++ check_panic_msg ++ | ||
| 111 | \\pub fn main() void { | ||
| 112 | \\ var buf_zero = [0]u8{}; | ||
| 113 | \\ const input: []u8 = &buf_zero; | ||
| 114 | \\ const slice = input[0..0 :0]; | ||
| 115 | \\ _ = slice; | ||
| 116 | \\} | ||
| 117 | ); | ||
| 118 | } | ||
| 119 | |||
| 120 | cases.addRuntimeSafety("truncating vector cast", | ||
| 121 | \\const std = @import("std"); | ||
| 122 | \\const V = @import("std").meta.Vector; | ||
| 123 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 124 | \\ _ = stack_trace; | ||
| 125 | \\ if (std.mem.eql(u8, message, "integer cast truncated bits")) { | ||
| 126 | \\ std.process.exit(126); // good | ||
| 127 | \\ } | ||
| 128 | \\ std.process.exit(0); // test failed | ||
| 129 | \\} | ||
| 130 | \\pub fn main() void { | ||
| 131 | \\ var x = @splat(4, @as(u32, 0xdeadbeef)); | ||
| 132 | \\ var y = @intCast(V(4, u16), x); | ||
| 133 | \\ _ = y; | ||
| 134 | \\} | ||
| 135 | ); | ||
| 136 | |||
| 137 | cases.addRuntimeSafety("unsigned-signed vector cast", | ||
| 138 | \\const std = @import("std"); | ||
| 139 | \\const V = @import("std").meta.Vector; | ||
| 140 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 141 | \\ _ = stack_trace; | ||
| 142 | \\ if (std.mem.eql(u8, message, "integer cast truncated bits")) { | ||
| 143 | \\ std.process.exit(126); // good | ||
| 144 | \\ } | ||
| 145 | \\ std.process.exit(0); // test failed | ||
| 146 | \\} | ||
| 147 | \\pub fn main() void { | ||
| 148 | \\ var x = @splat(4, @as(u32, 0x80000000)); | ||
| 149 | \\ var y = @intCast(V(4, i32), x); | ||
| 150 | \\ _ = y; | ||
| 151 | \\} | ||
| 152 | ); | ||
| 153 | |||
| 154 | cases.addRuntimeSafety("signed-unsigned vector cast", | ||
| 155 | \\const std = @import("std"); | ||
| 156 | \\const V = @import("std").meta.Vector; | ||
| 157 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 158 | \\ _ = stack_trace; | ||
| 159 | \\ if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) { | ||
| 160 | \\ std.process.exit(126); // good | ||
| 161 | \\ } | ||
| 162 | \\ std.process.exit(0); // test failed | ||
| 163 | \\} | ||
| 164 | \\pub fn main() void { | ||
| 165 | \\ var x = @splat(4, @as(i32, -2147483647)); | ||
| 166 | \\ var y = @intCast(V(4, u32), x); | ||
| 167 | \\ _ = y; | ||
| 168 | \\} | ||
| 169 | ); | ||
| 170 | |||
| 171 | cases.addRuntimeSafety("shift left by huge amount", | ||
| 172 | \\const std = @import("std"); | ||
| 173 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 174 | \\ _ = stack_trace; | ||
| 175 | \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) { | ||
| 176 | \\ std.process.exit(126); // good | ||
| 177 | \\ } | ||
| 178 | \\ std.process.exit(0); // test failed | ||
| 179 | \\} | ||
| 180 | \\pub fn main() void { | ||
| 181 | \\ var x: u24 = 42; | ||
| 182 | \\ var y: u5 = 24; | ||
| 183 | \\ var z = x >> y; | ||
| 184 | \\ _ = z; | ||
| 185 | \\} | ||
| 186 | ); | ||
| 187 | |||
| 188 | cases.addRuntimeSafety("shift right by huge amount", | ||
| 189 | \\const std = @import("std"); | ||
| 190 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 191 | \\ _ = stack_trace; | ||
| 192 | \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) { | ||
| 193 | \\ std.process.exit(126); // good | ||
| 194 | \\ } | ||
| 195 | \\ std.process.exit(0); // test failed | ||
| 196 | \\} | ||
| 197 | \\pub fn main() void { | ||
| 198 | \\ var x: u24 = 42; | ||
| 199 | \\ var y: u5 = 24; | ||
| 200 | \\ var z = x << y; | ||
| 201 | \\ _ = z; | ||
| 202 | \\} | ||
| 203 | ); | ||
| 204 | |||
| 205 | cases.addRuntimeSafety("slice sentinel mismatch - optional pointers", | ||
| 206 | \\const std = @import("std"); | ||
| 207 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 208 | \\ _ = stack_trace; | ||
| 209 | \\ if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 210 | \\ std.process.exit(126); // good | ||
| 211 | \\ } | ||
| 212 | \\ std.process.exit(0); // test failed | ||
| 213 | \\} | ||
| 214 | \\pub fn main() void { | ||
| 215 | \\ var buf: [4]?*i32 = undefined; | ||
| 216 | \\ const slice = buf[0..3 :null]; | ||
| 217 | \\ _ = slice; | ||
| 218 | \\} | ||
| 219 | ); | ||
| 220 | |||
| 221 | cases.addRuntimeSafety("slice sentinel mismatch - floats", | ||
| 222 | \\const std = @import("std"); | ||
| 223 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 224 | \\ _ = stack_trace; | ||
| 225 | \\ if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 226 | \\ std.process.exit(126); // good | ||
| 227 | \\ } | ||
| 228 | \\ std.process.exit(0); // test failed | ||
| 229 | \\} | ||
| 230 | \\pub fn main() void { | ||
| 231 | \\ var buf: [4]f32 = undefined; | ||
| 232 | \\ const slice = buf[0..3 :1.2]; | ||
| 233 | \\ _ = slice; | ||
| 234 | \\} | ||
| 235 | ); | ||
| 236 | |||
| 237 | cases.addRuntimeSafety("pointer slice sentinel mismatch", | ||
| 238 | \\const std = @import("std"); | ||
| 239 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 240 | \\ _ = stack_trace; | ||
| 241 | \\ if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 242 | \\ std.process.exit(126); // good | ||
| 243 | \\ } | ||
| 244 | \\ std.process.exit(0); // test failed | ||
| 245 | \\} | ||
| 246 | \\pub fn main() void { | ||
| 247 | \\ var buf: [4]u8 = undefined; | ||
| 248 | \\ const ptr: [*]u8 = &buf; | ||
| 249 | \\ const slice = ptr[0..3 :0]; | ||
| 250 | \\ _ = slice; | ||
| 251 | \\} | ||
| 252 | ); | ||
| 253 | |||
| 254 | cases.addRuntimeSafety("slice slice sentinel mismatch", | ||
| 255 | \\const std = @import("std"); | ||
| 256 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 257 | \\ _ = stack_trace; | ||
| 258 | \\ if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 259 | \\ std.process.exit(126); // good | ||
| 260 | \\ } | ||
| 261 | \\ std.process.exit(0); // test failed | ||
| 262 | \\} | ||
| 263 | \\pub fn main() void { | ||
| 264 | \\ var buf: [4]u8 = undefined; | ||
| 265 | \\ const slice = buf[0..]; | ||
| 266 | \\ const slice2 = slice[0..3 :0]; | ||
| 267 | \\ _ = slice2; | ||
| 268 | \\} | ||
| 269 | ); | ||
| 270 | |||
| 271 | cases.addRuntimeSafety("array slice sentinel mismatch", | ||
| 272 | \\const std = @import("std"); | ||
| 273 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 274 | \\ _ = stack_trace; | ||
| 275 | \\ if (std.mem.eql(u8, message, "sentinel mismatch")) { | ||
| 276 | \\ std.process.exit(126); // good | ||
| 277 | \\ } | ||
| 278 | \\ std.process.exit(0); // test failed | ||
| 279 | \\} | ||
| 280 | \\pub fn main() void { | ||
| 281 | \\ var buf: [4]u8 = undefined; | ||
| 282 | \\ const slice = buf[0..3 :0]; | ||
| 283 | \\ _ = slice; | ||
| 284 | \\} | ||
| 285 | ); | ||
| 286 | |||
| 287 | cases.addRuntimeSafety("intToPtr with misaligned address", | ||
| 288 | \\const std = @import("std"); | ||
| 289 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 290 | \\ _ = stack_trace; | ||
| 291 | \\ if (std.mem.eql(u8, message, "incorrect alignment")) { | ||
| 292 | \\ std.os.exit(126); // good | ||
| 293 | \\ } | ||
| 294 | \\ std.os.exit(0); // test failed | ||
| 295 | \\} | ||
| 296 | \\pub fn main() void { | ||
| 297 | \\ var x: usize = 5; | ||
| 298 | \\ var y = @intToPtr([*]align(4) u8, x); | ||
| 299 | \\ _ = y; | ||
| 300 | \\} | ||
| 301 | ); | ||
| 302 | |||
| 303 | cases.addRuntimeSafety("resuming a non-suspended function which never been suspended", | ||
| 304 | \\const std = @import("std"); | ||
| 305 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 306 | \\ _ = message; | ||
| 307 | \\ _ = stack_trace; | ||
| 308 | \\ std.os.exit(126); | ||
| 309 | \\} | ||
| 310 | \\fn foo() void { | ||
| 311 | \\ var f = async bar(@frame()); | ||
| 312 | \\ _ = f; | ||
| 313 | \\ std.os.exit(0); | ||
| 314 | \\} | ||
| 315 | \\ | ||
| 316 | \\fn bar(frame: anyframe) void { | ||
| 317 | \\ suspend { | ||
| 318 | \\ resume frame; | ||
| 319 | \\ } | ||
| 320 | \\ std.os.exit(0); | ||
| 321 | \\} | ||
| 322 | \\ | ||
| 323 | \\pub fn main() void { | ||
| 324 | \\ _ = async foo(); | ||
| 325 | \\} | ||
| 326 | ); | ||
| 327 | |||
| 328 | cases.addRuntimeSafety("resuming a non-suspended function which has been suspended and resumed", | ||
| 329 | \\const std = @import("std"); | ||
| 330 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 331 | \\ _ = message; | ||
| 332 | \\ _ = stack_trace; | ||
| 333 | \\ std.os.exit(126); | ||
| 334 | \\} | ||
| 335 | \\fn foo() void { | ||
| 336 | \\ suspend { | ||
| 337 | \\ global_frame = @frame(); | ||
| 338 | \\ } | ||
| 339 | \\ var f = async bar(@frame()); | ||
| 340 | \\ _ = f; | ||
| 341 | \\ std.os.exit(0); | ||
| 342 | \\} | ||
| 343 | \\ | ||
| 344 | \\fn bar(frame: anyframe) void { | ||
| 345 | \\ suspend { | ||
| 346 | \\ resume frame; | ||
| 347 | \\ } | ||
| 348 | \\ std.os.exit(0); | ||
| 349 | \\} | ||
| 350 | \\ | ||
| 351 | \\var global_frame: anyframe = undefined; | ||
| 352 | \\pub fn main() void { | ||
| 353 | \\ _ = async foo(); | ||
| 354 | \\ resume global_frame; | ||
| 355 | \\ std.os.exit(0); | ||
| 356 | \\} | ||
| 357 | ); | ||
| 358 | |||
| 359 | cases.addRuntimeSafety("nosuspend function call, callee suspends", | ||
| 360 | \\const std = @import("std"); | ||
| 361 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 362 | \\ _ = message; | ||
| 363 | \\ _ = stack_trace; | ||
| 364 | \\ std.os.exit(126); | ||
| 365 | \\} | ||
| 366 | \\pub fn main() void { | ||
| 367 | \\ _ = nosuspend add(101, 100); | ||
| 368 | \\} | ||
| 369 | \\fn add(a: i32, b: i32) i32 { | ||
| 370 | \\ if (a > 100) { | ||
| 371 | \\ suspend {} | ||
| 372 | \\ } | ||
| 373 | \\ return a + b; | ||
| 374 | \\} | ||
| 375 | ); | ||
| 376 | |||
| 377 | cases.addRuntimeSafety("awaiting twice", | ||
| 378 | \\const std = @import("std"); | ||
| 379 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 380 | \\ _ = message; | ||
| 381 | \\ _ = stack_trace; | ||
| 382 | \\ std.os.exit(126); | ||
| 383 | \\} | ||
| 384 | \\var frame: anyframe = undefined; | ||
| 385 | \\ | ||
| 386 | \\pub fn main() void { | ||
| 387 | \\ _ = async amain(); | ||
| 388 | \\ resume frame; | ||
| 389 | \\} | ||
| 390 | \\ | ||
| 391 | \\fn amain() void { | ||
| 392 | \\ var f = async func(); | ||
| 393 | \\ await f; | ||
| 394 | \\ await f; | ||
| 395 | \\} | ||
| 396 | \\ | ||
| 397 | \\fn func() void { | ||
| 398 | \\ suspend { | ||
| 399 | \\ frame = @frame(); | ||
| 400 | \\ } | ||
| 401 | \\} | ||
| 402 | ); | ||
| 403 | |||
| 404 | cases.addRuntimeSafety("@asyncCall with too small a frame", | ||
| 405 | \\const std = @import("std"); | ||
| 406 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 407 | \\ _ = message; | ||
| 408 | \\ _ = stack_trace; | ||
| 409 | \\ std.os.exit(126); | ||
| 410 | \\} | ||
| 411 | \\pub fn main() void { | ||
| 412 | \\ var bytes: [1]u8 align(16) = undefined; | ||
| 413 | \\ var ptr = other; | ||
| 414 | \\ var frame = @asyncCall(&bytes, {}, ptr, .{}); | ||
| 415 | \\ _ = frame; | ||
| 416 | \\} | ||
| 417 | \\fn other() callconv(.Async) void { | ||
| 418 | \\ suspend {} | ||
| 419 | \\} | ||
| 420 | ); | ||
| 421 | |||
| 422 | cases.addRuntimeSafety("resuming a function which is awaiting a frame", | ||
| 423 | \\const std = @import("std"); | ||
| 424 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 425 | \\ _ = message; | ||
| 426 | \\ _ = stack_trace; | ||
| 427 | \\ std.os.exit(126); | ||
| 428 | \\} | ||
| 429 | \\pub fn main() void { | ||
| 430 | \\ var frame = async first(); | ||
| 431 | \\ resume frame; | ||
| 432 | \\} | ||
| 433 | \\fn first() void { | ||
| 434 | \\ var frame = async other(); | ||
| 435 | \\ await frame; | ||
| 436 | \\} | ||
| 437 | \\fn other() void { | ||
| 438 | \\ suspend {} | ||
| 439 | \\} | ||
| 440 | ); | ||
| 441 | |||
| 442 | cases.addRuntimeSafety("resuming a function which is awaiting a call", | ||
| 443 | \\const std = @import("std"); | ||
| 444 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 445 | \\ _ = message; | ||
| 446 | \\ _ = stack_trace; | ||
| 447 | \\ std.os.exit(126); | ||
| 448 | \\} | ||
| 449 | \\pub fn main() void { | ||
| 450 | \\ var frame = async first(); | ||
| 451 | \\ resume frame; | ||
| 452 | \\} | ||
| 453 | \\fn first() void { | ||
| 454 | \\ other(); | ||
| 455 | \\} | ||
| 456 | \\fn other() void { | ||
| 457 | \\ suspend {} | ||
| 458 | \\} | ||
| 459 | ); | ||
| 460 | |||
| 461 | cases.addRuntimeSafety("invalid resume of async function", | ||
| 462 | \\const std = @import("std"); | ||
| 463 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 464 | \\ _ = message; | ||
| 465 | \\ _ = stack_trace; | ||
| 466 | \\ std.os.exit(126); | ||
| 467 | \\} | ||
| 468 | \\pub fn main() void { | ||
| 469 | \\ var p = async suspendOnce(); | ||
| 470 | \\ resume p; //ok | ||
| 471 | \\ resume p; //bad | ||
| 472 | \\} | ||
| 473 | \\fn suspendOnce() void { | ||
| 474 | \\ suspend {} | ||
| 475 | \\} | ||
| 476 | ); | ||
| 477 | |||
| 478 | cases.addRuntimeSafety(".? operator on null pointer", | ||
| 479 | \\const std = @import("std"); | ||
| 480 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 481 | \\ _ = message; | ||
| 482 | \\ _ = stack_trace; | ||
| 483 | \\ std.os.exit(126); | ||
| 484 | \\} | ||
| 485 | \\pub fn main() void { | ||
| 486 | \\ var ptr: ?*i32 = null; | ||
| 487 | \\ var b = ptr.?; | ||
| 488 | \\ _ = b; | ||
| 489 | \\} | ||
| 490 | ); | ||
| 491 | |||
| 492 | cases.addRuntimeSafety(".? operator on C pointer", | ||
| 493 | \\const std = @import("std"); | ||
| 494 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 495 | \\ _ = message; | ||
| 496 | \\ _ = stack_trace; | ||
| 497 | \\ std.os.exit(126); | ||
| 498 | \\} | ||
| 499 | \\pub fn main() void { | ||
| 500 | \\ var ptr: [*c]i32 = null; | ||
| 501 | \\ var b = ptr.?; | ||
| 502 | \\ _ = b; | ||
| 503 | \\} | ||
| 504 | ); | ||
| 505 | |||
| 506 | cases.addRuntimeSafety("@intToPtr address zero to non-optional pointer", | ||
| 507 | \\const std = @import("std"); | ||
| 508 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 509 | \\ _ = message; | ||
| 510 | \\ _ = stack_trace; | ||
| 511 | \\ std.os.exit(126); | ||
| 512 | \\} | ||
| 513 | \\pub fn main() void { | ||
| 514 | \\ var zero: usize = 0; | ||
| 515 | \\ var b = @intToPtr(*i32, zero); | ||
| 516 | \\ _ = b; | ||
| 517 | \\} | ||
| 518 | ); | ||
| 519 | |||
| 520 | cases.addRuntimeSafety("@intToPtr address zero to non-optional byte-aligned pointer", | ||
| 521 | \\const std = @import("std"); | ||
| 522 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 523 | \\ _ = message; | ||
| 524 | \\ _ = stack_trace; | ||
| 525 | \\ std.os.exit(126); | ||
| 526 | \\} | ||
| 527 | \\pub fn main() void { | ||
| 528 | \\ var zero: usize = 0; | ||
| 529 | \\ var b = @intToPtr(*u8, zero); | ||
| 530 | \\ _ = b; | ||
| 531 | \\} | ||
| 532 | ); | ||
| 533 | |||
| 534 | cases.addRuntimeSafety("pointer casting null to non-optional pointer", | ||
| 535 | \\const std = @import("std"); | ||
| 536 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 537 | \\ _ = message; | ||
| 538 | \\ _ = stack_trace; | ||
| 539 | \\ std.os.exit(126); | ||
| 540 | \\} | ||
| 541 | \\pub fn main() void { | ||
| 542 | \\ var c_ptr: [*c]u8 = 0; | ||
| 543 | \\ var zig_ptr: *u8 = c_ptr; | ||
| 544 | \\ _ = zig_ptr; | ||
| 545 | \\} | ||
| 546 | ); | ||
| 547 | |||
| 548 | cases.addRuntimeSafety("@intToEnum - no matching tag value", | ||
| 549 | \\const std = @import("std"); | ||
| 550 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 551 | \\ _ = message; | ||
| 552 | \\ _ = stack_trace; | ||
| 553 | \\ std.os.exit(126); | ||
| 554 | \\} | ||
| 555 | \\const Foo = enum { | ||
| 556 | \\ A, | ||
| 557 | \\ B, | ||
| 558 | \\ C, | ||
| 559 | \\}; | ||
| 560 | \\pub fn main() void { | ||
| 561 | \\ baz(bar(3)); | ||
| 562 | \\} | ||
| 563 | \\fn bar(a: u2) Foo { | ||
| 564 | \\ return @intToEnum(Foo, a); | ||
| 565 | \\} | ||
| 566 | \\fn baz(_: Foo) void {} | ||
| 567 | ); | ||
| 568 | |||
| 569 | cases.addRuntimeSafety("@floatToInt cannot fit - negative to unsigned", | ||
| 570 | \\const std = @import("std"); | ||
| 571 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 572 | \\ _ = message; | ||
| 573 | \\ _ = stack_trace; | ||
| 574 | \\ std.os.exit(126); | ||
| 575 | \\} | ||
| 576 | \\pub fn main() void { | ||
| 577 | \\ baz(bar(-1.1)); | ||
| 578 | \\} | ||
| 579 | \\fn bar(a: f32) u8 { | ||
| 580 | \\ return @floatToInt(u8, a); | ||
| 581 | \\} | ||
| 582 | \\fn baz(_: u8) void { } | ||
| 583 | ); | ||
| 584 | |||
| 585 | cases.addRuntimeSafety("@floatToInt cannot fit - negative out of range", | ||
| 586 | \\const std = @import("std"); | ||
| 587 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 588 | \\ _ = message; | ||
| 589 | \\ _ = stack_trace; | ||
| 590 | \\ std.os.exit(126); | ||
| 591 | \\} | ||
| 592 | \\pub fn main() void { | ||
| 593 | \\ baz(bar(-129.1)); | ||
| 594 | \\} | ||
| 595 | \\fn bar(a: f32) i8 { | ||
| 596 | \\ return @floatToInt(i8, a); | ||
| 597 | \\} | ||
| 598 | \\fn baz(_: i8) void { } | ||
| 599 | ); | ||
| 600 | |||
| 601 | cases.addRuntimeSafety("@floatToInt cannot fit - positive out of range", | ||
| 602 | \\const std = @import("std"); | ||
| 603 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 604 | \\ _ = message; | ||
| 605 | \\ _ = stack_trace; | ||
| 606 | \\ std.os.exit(126); | ||
| 607 | \\} | ||
| 608 | \\pub fn main() void { | ||
| 609 | \\ baz(bar(256.2)); | ||
| 610 | \\} | ||
| 611 | \\fn bar(a: f32) u8 { | ||
| 612 | \\ return @floatToInt(u8, a); | ||
| 613 | \\} | ||
| 614 | \\fn baz(_: u8) void { } | ||
| 615 | ); | ||
| 616 | |||
| 617 | cases.addRuntimeSafety("calling panic", | ||
| 618 | \\const std = @import("std"); | ||
| 619 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 620 | \\ _ = message; | ||
| 621 | \\ _ = stack_trace; | ||
| 622 | \\ std.os.exit(126); | ||
| 623 | \\} | ||
| 624 | \\pub fn main() void { | ||
| 625 | \\ @panic("oh no"); | ||
| 626 | \\} | ||
| 627 | ); | ||
| 628 | |||
| 629 | cases.addRuntimeSafety("out of bounds slice access", | ||
| 630 | \\const std = @import("std"); | ||
| 631 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 632 | \\ _ = message; | ||
| 633 | \\ _ = stack_trace; | ||
| 634 | \\ std.os.exit(126); | ||
| 635 | \\} | ||
| 636 | \\pub fn main() void { | ||
| 637 | \\ const a = [_]i32{1, 2, 3, 4}; | ||
| 638 | \\ baz(bar(&a)); | ||
| 639 | \\} | ||
| 640 | \\fn bar(a: []const i32) i32 { | ||
| 641 | \\ return a[4]; | ||
| 642 | \\} | ||
| 643 | \\fn baz(_: i32) void { } | ||
| 644 | ); | ||
| 645 | |||
| 646 | cases.addRuntimeSafety("integer addition overflow", | ||
| 647 | \\const std = @import("std"); | ||
| 648 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 649 | \\ _ = message; | ||
| 650 | \\ _ = stack_trace; | ||
| 651 | \\ std.os.exit(126); | ||
| 652 | \\} | ||
| 653 | \\pub fn main() !void { | ||
| 654 | \\ const x = add(65530, 10); | ||
| 655 | \\ if (x == 0) return error.Whatever; | ||
| 656 | \\} | ||
| 657 | \\fn add(a: u16, b: u16) u16 { | ||
| 658 | \\ return a + b; | ||
| 659 | \\} | ||
| 660 | ); | ||
| 661 | |||
| 662 | cases.addRuntimeSafety("vector integer addition overflow", | ||
| 663 | \\const std = @import("std"); | ||
| 664 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 665 | \\ _ = message; | ||
| 666 | \\ _ = stack_trace; | ||
| 667 | \\ std.os.exit(126); | ||
| 668 | \\} | ||
| 669 | \\pub fn main() void { | ||
| 670 | \\ var a: @Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 }; | ||
| 671 | \\ var b: @Vector(4, i32) = [_]i32{ 5, 6, 7, 8 }; | ||
| 672 | \\ const x = add(a, b); | ||
| 673 | \\ _ = x; | ||
| 674 | \\} | ||
| 675 | \\fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ||
| 676 | \\ return a + b; | ||
| 677 | \\} | ||
| 678 | ); | ||
| 679 | |||
| 680 | cases.addRuntimeSafety("vector integer subtraction overflow", | ||
| 681 | \\const std = @import("std"); | ||
| 682 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 683 | \\ _ = message; | ||
| 684 | \\ _ = stack_trace; | ||
| 685 | \\ std.os.exit(126); | ||
| 686 | \\} | ||
| 687 | \\pub fn main() void { | ||
| 688 | \\ var a: @Vector(4, u32) = [_]u32{ 1, 2, 8, 4 }; | ||
| 689 | \\ var b: @Vector(4, u32) = [_]u32{ 5, 6, 7, 8 }; | ||
| 690 | \\ const x = sub(b, a); | ||
| 691 | \\ _ = x; | ||
| 692 | \\} | ||
| 693 | \\fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) { | ||
| 694 | \\ return a - b; | ||
| 695 | \\} | ||
| 696 | ); | ||
| 697 | |||
| 698 | cases.addRuntimeSafety("vector integer multiplication overflow", | ||
| 699 | \\const std = @import("std"); | ||
| 700 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 701 | \\ _ = message; | ||
| 702 | \\ _ = stack_trace; | ||
| 703 | \\ std.os.exit(126); | ||
| 704 | \\} | ||
| 705 | \\pub fn main() void { | ||
| 706 | \\ var a: @Vector(4, u8) = [_]u8{ 1, 2, 200, 4 }; | ||
| 707 | \\ var b: @Vector(4, u8) = [_]u8{ 5, 6, 2, 8 }; | ||
| 708 | \\ const x = mul(b, a); | ||
| 709 | \\ _ = x; | ||
| 710 | \\} | ||
| 711 | \\fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) { | ||
| 712 | \\ return a * b; | ||
| 713 | \\} | ||
| 714 | ); | ||
| 715 | |||
| 716 | cases.addRuntimeSafety("vector integer negation overflow", | ||
| 717 | \\const std = @import("std"); | ||
| 718 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 719 | \\ _ = message; | ||
| 720 | \\ _ = stack_trace; | ||
| 721 | \\ std.os.exit(126); | ||
| 722 | \\} | ||
| 723 | \\pub fn main() void { | ||
| 724 | \\ var a: @Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 }; | ||
| 725 | \\ const x = neg(a); | ||
| 726 | \\ _ = x; | ||
| 727 | \\} | ||
| 728 | \\fn neg(a: @Vector(4, i16)) @Vector(4, i16) { | ||
| 729 | \\ return -a; | ||
| 730 | \\} | ||
| 731 | ); | ||
| 732 | |||
| 733 | cases.addRuntimeSafety("integer subtraction overflow", | ||
| 734 | \\const std = @import("std"); | ||
| 735 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 736 | \\ _ = message; | ||
| 737 | \\ _ = stack_trace; | ||
| 738 | \\ std.os.exit(126); | ||
| 739 | \\} | ||
| 740 | \\pub fn main() !void { | ||
| 741 | \\ const x = sub(10, 20); | ||
| 742 | \\ if (x == 0) return error.Whatever; | ||
| 743 | \\} | ||
| 744 | \\fn sub(a: u16, b: u16) u16 { | ||
| 745 | \\ return a - b; | ||
| 746 | \\} | ||
| 747 | ); | ||
| 748 | |||
| 749 | cases.addRuntimeSafety("integer multiplication overflow", | ||
| 750 | \\const std = @import("std"); | ||
| 751 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 752 | \\ _ = message; | ||
| 753 | \\ _ = stack_trace; | ||
| 754 | \\ std.os.exit(126); | ||
| 755 | \\} | ||
| 756 | \\pub fn main() !void { | ||
| 757 | \\ const x = mul(300, 6000); | ||
| 758 | \\ if (x == 0) return error.Whatever; | ||
| 759 | \\} | ||
| 760 | \\fn mul(a: u16, b: u16) u16 { | ||
| 761 | \\ return a * b; | ||
| 762 | \\} | ||
| 763 | ); | ||
| 764 | |||
| 765 | cases.addRuntimeSafety("integer negation overflow", | ||
| 766 | \\const std = @import("std"); | ||
| 767 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 768 | \\ _ = message; | ||
| 769 | \\ _ = stack_trace; | ||
| 770 | \\ std.os.exit(126); | ||
| 771 | \\} | ||
| 772 | \\pub fn main() !void { | ||
| 773 | \\ const x = neg(-32768); | ||
| 774 | \\ if (x == 32767) return error.Whatever; | ||
| 775 | \\} | ||
| 776 | \\fn neg(a: i16) i16 { | ||
| 777 | \\ return -a; | ||
| 778 | \\} | ||
| 779 | ); | ||
| 780 | |||
| 781 | cases.addRuntimeSafety("signed integer division overflow", | ||
| 782 | \\const std = @import("std"); | ||
| 783 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 784 | \\ _ = message; | ||
| 785 | \\ _ = stack_trace; | ||
| 786 | \\ std.os.exit(126); | ||
| 787 | \\} | ||
| 788 | \\pub fn main() !void { | ||
| 789 | \\ const x = div(-32768, -1); | ||
| 790 | \\ if (x == 32767) return error.Whatever; | ||
| 791 | \\} | ||
| 792 | \\fn div(a: i16, b: i16) i16 { | ||
| 793 | \\ return @divTrunc(a, b); | ||
| 794 | \\} | ||
| 795 | ); | ||
| 796 | |||
| 797 | cases.addRuntimeSafety("signed integer division overflow - vectors", | ||
| 798 | \\const std = @import("std"); | ||
| 799 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 800 | \\ _ = message; | ||
| 801 | \\ _ = stack_trace; | ||
| 802 | \\ std.os.exit(126); | ||
| 803 | \\} | ||
| 804 | \\pub fn main() !void { | ||
| 805 | \\ var a: @Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 }; | ||
| 806 | \\ var b: @Vector(4, i16) = [_]i16{ 1, 2, -1, 4 }; | ||
| 807 | \\ const x = div(a, b); | ||
| 808 | \\ if (x[2] == 32767) return error.Whatever; | ||
| 809 | \\} | ||
| 810 | \\fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) { | ||
| 811 | \\ return @divTrunc(a, b); | ||
| 812 | \\} | ||
| 813 | ); | ||
| 814 | |||
| 815 | cases.addRuntimeSafety("signed shift left overflow", | ||
| 816 | \\const std = @import("std"); | ||
| 817 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 818 | \\ _ = message; | ||
| 819 | \\ _ = stack_trace; | ||
| 820 | \\ std.os.exit(126); | ||
| 821 | \\} | ||
| 822 | \\pub fn main() !void { | ||
| 823 | \\ const x = shl(-16385, 1); | ||
| 824 | \\ if (x == 0) return error.Whatever; | ||
| 825 | \\} | ||
| 826 | \\fn shl(a: i16, b: u4) i16 { | ||
| 827 | \\ return @shlExact(a, b); | ||
| 828 | \\} | ||
| 829 | ); | ||
| 830 | |||
| 831 | cases.addRuntimeSafety("unsigned shift left overflow", | ||
| 832 | \\const std = @import("std"); | ||
| 833 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 834 | \\ _ = message; | ||
| 835 | \\ _ = stack_trace; | ||
| 836 | \\ std.os.exit(126); | ||
| 837 | \\} | ||
| 838 | \\pub fn main() !void { | ||
| 839 | \\ const x = shl(0b0010111111111111, 3); | ||
| 840 | \\ if (x == 0) return error.Whatever; | ||
| 841 | \\} | ||
| 842 | \\fn shl(a: u16, b: u4) u16 { | ||
| 843 | \\ return @shlExact(a, b); | ||
| 844 | \\} | ||
| 845 | ); | ||
| 846 | |||
| 847 | cases.addRuntimeSafety("signed shift right overflow", | ||
| 848 | \\const std = @import("std"); | ||
| 849 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 850 | \\ _ = message; | ||
| 851 | \\ _ = stack_trace; | ||
| 852 | \\ std.os.exit(126); | ||
| 853 | \\} | ||
| 854 | \\pub fn main() !void { | ||
| 855 | \\ const x = shr(-16385, 1); | ||
| 856 | \\ if (x == 0) return error.Whatever; | ||
| 857 | \\} | ||
| 858 | \\fn shr(a: i16, b: u4) i16 { | ||
| 859 | \\ return @shrExact(a, b); | ||
| 860 | \\} | ||
| 861 | ); | ||
| 862 | |||
| 863 | cases.addRuntimeSafety("unsigned shift right overflow", | ||
| 864 | \\const std = @import("std"); | ||
| 865 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 866 | \\ _ = message; | ||
| 867 | \\ _ = stack_trace; | ||
| 868 | \\ std.os.exit(126); | ||
| 869 | \\} | ||
| 870 | \\pub fn main() !void { | ||
| 871 | \\ const x = shr(0b0010111111111111, 3); | ||
| 872 | \\ if (x == 0) return error.Whatever; | ||
| 873 | \\} | ||
| 874 | \\fn shr(a: u16, b: u4) u16 { | ||
| 875 | \\ return @shrExact(a, b); | ||
| 876 | \\} | ||
| 877 | ); | ||
| 878 | |||
| 879 | cases.addRuntimeSafety("integer division by zero", | ||
| 880 | \\const std = @import("std"); | ||
| 881 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 882 | \\ _ = message; | ||
| 883 | \\ _ = stack_trace; | ||
| 884 | \\ std.os.exit(126); | ||
| 885 | \\} | ||
| 886 | \\pub fn main() void { | ||
| 887 | \\ const x = div0(999, 0); | ||
| 888 | \\ _ = x; | ||
| 889 | \\} | ||
| 890 | \\fn div0(a: i32, b: i32) i32 { | ||
| 891 | \\ return @divTrunc(a, b); | ||
| 892 | \\} | ||
| 893 | ); | ||
| 894 | |||
| 895 | cases.addRuntimeSafety("integer division by zero - vectors", | ||
| 896 | \\const std = @import("std"); | ||
| 897 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 898 | \\ _ = message; | ||
| 899 | \\ _ = stack_trace; | ||
| 900 | \\ std.os.exit(126); | ||
| 901 | \\} | ||
| 902 | \\pub fn main() void { | ||
| 903 | \\ var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444}; | ||
| 904 | \\ var b: @Vector(4, i32) = [4]i32{111, 0, 333, 444}; | ||
| 905 | \\ const x = div0(a, b); | ||
| 906 | \\ _ = x; | ||
| 907 | \\} | ||
| 908 | \\fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ||
| 909 | \\ return @divTrunc(a, b); | ||
| 910 | \\} | ||
| 911 | ); | ||
| 912 | |||
| 913 | cases.addRuntimeSafety("exact division failure", | ||
| 914 | \\const std = @import("std"); | ||
| 915 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 916 | \\ _ = message; | ||
| 917 | \\ _ = stack_trace; | ||
| 918 | \\ std.os.exit(126); | ||
| 919 | \\} | ||
| 920 | \\pub fn main() !void { | ||
| 921 | \\ const x = divExact(10, 3); | ||
| 922 | \\ if (x == 0) return error.Whatever; | ||
| 923 | \\} | ||
| 924 | \\fn divExact(a: i32, b: i32) i32 { | ||
| 925 | \\ return @divExact(a, b); | ||
| 926 | \\} | ||
| 927 | ); | ||
| 928 | |||
| 929 | cases.addRuntimeSafety("exact division failure - vectors", | ||
| 930 | \\const std = @import("std"); | ||
| 931 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 932 | \\ _ = message; | ||
| 933 | \\ _ = stack_trace; | ||
| 934 | \\ std.os.exit(126); | ||
| 935 | \\} | ||
| 936 | \\pub fn main() !void { | ||
| 937 | \\ var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444}; | ||
| 938 | \\ var b: @Vector(4, i32) = [4]i32{111, 222, 333, 441}; | ||
| 939 | \\ const x = divExact(a, b); | ||
| 940 | \\ _ = x; | ||
| 941 | \\} | ||
| 942 | \\fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ||
| 943 | \\ return @divExact(a, b); | ||
| 944 | \\} | ||
| 945 | ); | ||
| 946 | |||
| 947 | cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size", | ||
| 948 | \\const std = @import("std"); | ||
| 949 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 950 | \\ _ = message; | ||
| 951 | \\ _ = stack_trace; | ||
| 952 | \\ std.os.exit(126); | ||
| 953 | \\} | ||
| 954 | \\pub fn main() !void { | ||
| 955 | \\ const x = widenSlice(&[_]u8{1, 2, 3, 4, 5}); | ||
| 956 | \\ if (x.len == 0) return error.Whatever; | ||
| 957 | \\} | ||
| 958 | \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { | ||
| 959 | \\ return std.mem.bytesAsSlice(i32, slice); | ||
| 960 | \\} | ||
| 961 | ); | ||
| 962 | |||
| 963 | cases.addRuntimeSafety("value does not fit in shortening cast", | ||
| 964 | \\const std = @import("std"); | ||
| 965 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 966 | \\ _ = message; | ||
| 967 | \\ _ = stack_trace; | ||
| 968 | \\ std.os.exit(126); | ||
| 969 | \\} | ||
| 970 | \\pub fn main() !void { | ||
| 971 | \\ const x = shorten_cast(200); | ||
| 972 | \\ if (x == 0) return error.Whatever; | ||
| 973 | \\} | ||
| 974 | \\fn shorten_cast(x: i32) i8 { | ||
| 975 | \\ return @intCast(i8, x); | ||
| 976 | \\} | ||
| 977 | ); | ||
| 978 | |||
| 979 | cases.addRuntimeSafety("value does not fit in shortening cast - u0", | ||
| 980 | \\const std = @import("std"); | ||
| 981 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 982 | \\ _ = message; | ||
| 983 | \\ _ = stack_trace; | ||
| 984 | \\ std.os.exit(126); | ||
| 985 | \\} | ||
| 986 | \\pub fn main() !void { | ||
| 987 | \\ const x = shorten_cast(1); | ||
| 988 | \\ if (x == 0) return error.Whatever; | ||
| 989 | \\} | ||
| 990 | \\fn shorten_cast(x: u8) u0 { | ||
| 991 | \\ return @intCast(u0, x); | ||
| 992 | \\} | ||
| 993 | ); | ||
| 994 | |||
| 995 | cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer", | ||
| 996 | \\const std = @import("std"); | ||
| 997 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 998 | \\ _ = message; | ||
| 999 | \\ _ = stack_trace; | ||
| 1000 | \\ std.os.exit(126); | ||
| 1001 | \\} | ||
| 1002 | \\pub fn main() !void { | ||
| 1003 | \\ const x = unsigned_cast(-10); | ||
| 1004 | \\ if (x == 0) return error.Whatever; | ||
| 1005 | \\} | ||
| 1006 | \\fn unsigned_cast(x: i32) u32 { | ||
| 1007 | \\ return @intCast(u32, x); | ||
| 1008 | \\} | ||
| 1009 | ); | ||
| 1010 | |||
| 1011 | cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening", | ||
| 1012 | \\const std = @import("std"); | ||
| 1013 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1014 | \\ _ = message; | ||
| 1015 | \\ _ = stack_trace; | ||
| 1016 | \\ std.os.exit(126); | ||
| 1017 | \\} | ||
| 1018 | \\pub fn main() void { | ||
| 1019 | \\ var value: c_short = -1; | ||
| 1020 | \\ var casted = @intCast(u32, value); | ||
| 1021 | \\ _ = casted; | ||
| 1022 | \\} | ||
| 1023 | ); | ||
| 1024 | |||
| 1025 | cases.addRuntimeSafety("unsigned integer not fitting in cast to signed integer - same bit count", | ||
| 1026 | \\const std = @import("std"); | ||
| 1027 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1028 | \\ _ = message; | ||
| 1029 | \\ _ = stack_trace; | ||
| 1030 | \\ std.os.exit(126); | ||
| 1031 | \\} | ||
| 1032 | \\pub fn main() void { | ||
| 1033 | \\ var value: u8 = 245; | ||
| 1034 | \\ var casted = @intCast(i8, value); | ||
| 1035 | \\ _ = casted; | ||
| 1036 | \\} | ||
| 1037 | ); | ||
| 1038 | |||
| 1039 | cases.addRuntimeSafety("unwrap error", | ||
| 1040 | \\const std = @import("std"); | ||
| 1041 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1042 | \\ _ = stack_trace; | ||
| 1043 | \\ if (std.mem.eql(u8, message, "attempt to unwrap error: Whatever")) { | ||
| 1044 | \\ std.os.exit(126); // good | ||
| 1045 | \\ } | ||
| 1046 | \\ std.os.exit(0); // test failed | ||
| 1047 | \\} | ||
| 1048 | \\pub fn main() void { | ||
| 1049 | \\ bar() catch unreachable; | ||
| 1050 | \\} | ||
| 1051 | \\fn bar() !void { | ||
| 1052 | \\ return error.Whatever; | ||
| 1053 | \\} | ||
| 1054 | ); | ||
| 1055 | |||
| 1056 | cases.addRuntimeSafety("cast integer to global error and no code matches", | ||
| 1057 | \\const std = @import("std"); | ||
| 1058 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1059 | \\ _ = message; | ||
| 1060 | \\ _ = stack_trace; | ||
| 1061 | \\ std.os.exit(126); | ||
| 1062 | \\} | ||
| 1063 | \\pub fn main() void { | ||
| 1064 | \\ bar(9999) catch {}; | ||
| 1065 | \\} | ||
| 1066 | \\fn bar(x: u16) anyerror { | ||
| 1067 | \\ return @intToError(x); | ||
| 1068 | \\} | ||
| 1069 | ); | ||
| 1070 | |||
| 1071 | cases.addRuntimeSafety("@errSetCast error not present in destination", | ||
| 1072 | \\const std = @import("std"); | ||
| 1073 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1074 | \\ _ = message; | ||
| 1075 | \\ _ = stack_trace; | ||
| 1076 | \\ std.os.exit(126); | ||
| 1077 | \\} | ||
| 1078 | \\const Set1 = error{A, B}; | ||
| 1079 | \\const Set2 = error{A, C}; | ||
| 1080 | \\pub fn main() void { | ||
| 1081 | \\ foo(Set1.B) catch {}; | ||
| 1082 | \\} | ||
| 1083 | \\fn foo(set1: Set1) Set2 { | ||
| 1084 | \\ return @errSetCast(Set2, set1); | ||
| 1085 | \\} | ||
| 1086 | ); | ||
| 1087 | |||
| 1088 | cases.addRuntimeSafety("@alignCast misaligned", | ||
| 1089 | \\const std = @import("std"); | ||
| 1090 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1091 | \\ _ = message; | ||
| 1092 | \\ _ = stack_trace; | ||
| 1093 | \\ std.os.exit(126); | ||
| 1094 | \\} | ||
| 1095 | \\pub fn main() !void { | ||
| 1096 | \\ var array align(4) = [_]u32{0x11111111, 0x11111111}; | ||
| 1097 | \\ const bytes = std.mem.sliceAsBytes(array[0..]); | ||
| 1098 | \\ if (foo(bytes) != 0x11111111) return error.Wrong; | ||
| 1099 | \\} | ||
| 1100 | \\fn foo(bytes: []u8) u32 { | ||
| 1101 | \\ const slice4 = bytes[1..5]; | ||
| 1102 | \\ const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4)); | ||
| 1103 | \\ return int_slice[0]; | ||
| 1104 | \\} | ||
| 1105 | ); | ||
| 1106 | |||
| 1107 | cases.addRuntimeSafety("bad union field access", | ||
| 1108 | \\const std = @import("std"); | ||
| 1109 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1110 | \\ _ = message; | ||
| 1111 | \\ _ = stack_trace; | ||
| 1112 | \\ std.os.exit(126); | ||
| 1113 | \\} | ||
| 1114 | \\ | ||
| 1115 | \\const Foo = union { | ||
| 1116 | \\ float: f32, | ||
| 1117 | \\ int: u32, | ||
| 1118 | \\}; | ||
| 1119 | \\ | ||
| 1120 | \\pub fn main() void { | ||
| 1121 | \\ var f = Foo { .int = 42 }; | ||
| 1122 | \\ bar(&f); | ||
| 1123 | \\} | ||
| 1124 | \\ | ||
| 1125 | \\fn bar(f: *Foo) void { | ||
| 1126 | \\ f.float = 12.34; | ||
| 1127 | \\} | ||
| 1128 | ); | ||
| 1129 | |||
| 1130 | // @intCast a runtime integer to u0 actually results in a comptime-known value, | ||
| 1131 | // but we still emit a safety check to ensure the integer was 0 and thus | ||
| 1132 | // did not truncate information. | ||
| 1133 | cases.addRuntimeSafety("@intCast to u0", | ||
| 1134 | \\const std = @import("std"); | ||
| 1135 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1136 | \\ _ = message; | ||
| 1137 | \\ _ = stack_trace; | ||
| 1138 | \\ std.os.exit(126); | ||
| 1139 | \\} | ||
| 1140 | \\ | ||
| 1141 | \\pub fn main() void { | ||
| 1142 | \\ bar(1, 1); | ||
| 1143 | \\} | ||
| 1144 | \\ | ||
| 1145 | \\fn bar(one: u1, not_zero: i32) void { | ||
| 1146 | \\ var x = one << @intCast(u0, not_zero); | ||
| 1147 | \\ _ = x; | ||
| 1148 | \\} | ||
| 1149 | ); | ||
| 1150 | |||
| 1151 | // This case makes sure that the code compiles and runs. There is not actually a special | ||
| 1152 | // runtime safety check having to do specifically with error return traces across suspend points. | ||
| 1153 | cases.addRuntimeSafety("error return trace across suspend points", | ||
| 1154 | \\const std = @import("std"); | ||
| 1155 | \\ | ||
| 1156 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1157 | \\ _ = message; | ||
| 1158 | \\ _ = stack_trace; | ||
| 1159 | \\ std.os.exit(126); | ||
| 1160 | \\} | ||
| 1161 | \\ | ||
| 1162 | \\var failing_frame: @Frame(failing) = undefined; | ||
| 1163 | \\ | ||
| 1164 | \\pub fn main() void { | ||
| 1165 | \\ const p = nonFailing(); | ||
| 1166 | \\ resume p; | ||
| 1167 | \\ const p2 = async printTrace(p); | ||
| 1168 | \\ _ = p2; | ||
| 1169 | \\} | ||
| 1170 | \\ | ||
| 1171 | \\fn nonFailing() anyframe->anyerror!void { | ||
| 1172 | \\ failing_frame = async failing(); | ||
| 1173 | \\ return &failing_frame; | ||
| 1174 | \\} | ||
| 1175 | \\ | ||
| 1176 | \\fn failing() anyerror!void { | ||
| 1177 | \\ suspend {} | ||
| 1178 | \\ return second(); | ||
| 1179 | \\} | ||
| 1180 | \\ | ||
| 1181 | \\fn second() callconv(.Async) anyerror!void { | ||
| 1182 | \\ return error.Fail; | ||
| 1183 | \\} | ||
| 1184 | \\ | ||
| 1185 | \\fn printTrace(p: anyframe->anyerror!void) void { | ||
| 1186 | \\ (await p) catch unreachable; | ||
| 1187 | \\} | ||
| 1188 | ); | ||
| 1189 | |||
| 1190 | // Slicing a C pointer returns a non-allowzero slice, thus we need to emit | ||
| 1191 | // a safety check to ensure the pointer is not null. | ||
| 1192 | cases.addRuntimeSafety("slicing null C pointer", | ||
| 1193 | \\const std = @import("std"); | ||
| 1194 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 1195 | \\ _ = message; | ||
| 1196 | \\ _ = stack_trace; | ||
| 1197 | \\ std.os.exit(126); | ||
| 1198 | \\} | ||
| 1199 | \\ | ||
| 1200 | \\pub fn main() void { | ||
| 1201 | \\ var ptr: [*c]const u32 = null; | ||
| 1202 | \\ var slice = ptr[0..3]; | ||
| 1203 | \\ _ = slice; | ||
| 1204 | \\} | ||
| 1205 | ); | ||
| 1206 | } | ||
test/tests.zig-16| ... | @@ -18,7 +18,6 @@ const compare_output = @import("compare_output.zig"); | ... | @@ -18,7 +18,6 @@ const compare_output = @import("compare_output.zig"); |
| 18 | const standalone = @import("standalone.zig"); | 18 | const standalone = @import("standalone.zig"); |
| 19 | const stack_traces = @import("stack_traces.zig"); | 19 | const stack_traces = @import("stack_traces.zig"); |
| 20 | const assemble_and_link = @import("assemble_and_link.zig"); | 20 | const assemble_and_link = @import("assemble_and_link.zig"); |
| 21 | const runtime_safety = @import("runtime_safety.zig"); | ||
| 22 | const translate_c = @import("translate_c.zig"); | 21 | const translate_c = @import("translate_c.zig"); |
| 23 | const run_translated_c = @import("run_translated_c.zig"); | 22 | const run_translated_c = @import("run_translated_c.zig"); |
| 24 | const gen_h = @import("gen_h.zig"); | 23 | const gen_h = @import("gen_h.zig"); |
| ... | @@ -455,21 +454,6 @@ pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, modes: [] | ... | @@ -455,21 +454,6 @@ pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, modes: [] |
| 455 | return cases.step; | 454 | return cases.step; |
| 456 | } | 455 | } |
| 457 | 456 | ||
| 458 | pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { | ||
| 459 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; | ||
| 460 | cases.* = CompareOutputContext{ | ||
| 461 | .b = b, | ||
| 462 | .step = b.step("test-runtime-safety", "Run the runtime safety tests"), | ||
| 463 | .test_index = 0, | ||
| 464 | .test_filter = test_filter, | ||
| 465 | .modes = modes, | ||
| 466 | }; | ||
| 467 | |||
| 468 | runtime_safety.addCases(cases); | ||
| 469 | |||
| 470 | return cases.step; | ||
| 471 | } | ||
| 472 | |||
| 473 | pub fn addStandaloneTests( | 457 | pub fn addStandaloneTests( |
| 474 | b: *build.Builder, | 458 | b: *build.Builder, |
| 475 | test_filter: ?[]const u8, | 459 | test_filter: ?[]const u8, |