zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit b5cef9e8b48e81fb1f3b56cb752bac95e6a2d44b (tree)
parent e831313b10c8c0f6c1984bb1704f3ca90105c416
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Thu, 21 Mar 2024 01:47:54 -0700

Merge pull request #19374 from ziglang/slice-by-len-safety

add OOB safety check for by-length slice of array
Diffstat:
Msrc/Sema.zig | 16++++++++++------
Atest/cases/safety/out of bounds array slice by length.zig | 20++++++++++++++++++++
2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig @@ -33284,12 +33284,16 @@ fn analyzeSlice( try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); } - if (slice_ty.isSlice(mod)) { - const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); - const actual_len = if (slice_ty.sentinel(mod) == null) - slice_len_inst - else - try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true); + bounds_check: { + const actual_len = if (array_ty.zigTypeTag(mod) == .Array) + try mod.intRef(Type.usize, array_ty.arrayLenIncludingSentinel(mod)) + else if (slice_ty.isSlice(mod)) l: { + const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); + break :l if (slice_ty.sentinel(mod) == null) + slice_len_inst + else + try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true); + } else break :bounds_check; const actual_end = if (slice_sentinel != null) try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true) diff --git a/test/cases/safety/out of bounds array slice by length.zig b/test/cases/safety/out of bounds array slice by length.zig @@ -0,0 +1,20 @@ +const std = @import("std"); + +pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { + _ = stack_trace; + if (std.mem.eql(u8, message, "index out of bounds: index 16, len 5")) { + std.process.exit(0); + } + std.process.exit(1); +} +pub fn main() !void { + var buf: [5]u8 = undefined; + _ = buf[foo(6)..][0..10]; + return error.TestFailed; +} +fn foo(a: u32) u32 { + return a; +} +// run +// backend=llvm +// target=native