authorgravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-03-22 23:32:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-23 13:44:31-07:00
log5374e245c50fde8bbb133bbff2db15efa3604721
treef97abf82092e557f0e73a119fe7ac36506b9e8f4
parent1c223819098e5621e2e5ad526879cd33852144e1

stage2: Remove premature elem_val index check

We were enforcing bounds on the index of an elem_ptr in pointerDeref, but we want to support out-of-bounds accesses by reinterpreting memory. This removes that check, so that the deref falls back to bitcasting, as usual. This was masked by another bug that was forcing bitcasts incorrectly, which is why this wasn't noticed earlier.

1 files changed, 7 insertions(+), 9 deletions(-)

src/Sema.zig+7-9
...@@ -18752,6 +18752,11 @@ fn beginComptimePtrLoad(...@@ -18752,6 +18752,11 @@ fn beginComptimePtrLoad(
18752 const elem_ty = elem_ptr.elem_ty;18752 const elem_ty = elem_ptr.elem_ty;
18753 var deref = try beginComptimePtrLoad(sema, block, src, elem_ptr.array_ptr, null);18753 var deref = try beginComptimePtrLoad(sema, block, src, elem_ptr.array_ptr, null);
1875418754
18755 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
18756 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
18757 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
18758 if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, target)));
18759
18755 if (elem_ptr.index != 0) {18760 if (elem_ptr.index != 0) {
18756 if (elem_ty.hasWellDefinedLayout()) {18761 if (elem_ty.hasWellDefinedLayout()) {
18757 if (deref.parent) |*parent| {18762 if (deref.parent) |*parent| {
...@@ -18780,13 +18785,6 @@ fn beginComptimePtrLoad(...@@ -18780,13 +18785,6 @@ fn beginComptimePtrLoad(
1878018785
18781 var array_tv = deref.pointee.?;18786 var array_tv = deref.pointee.?;
18782 const check_len = array_tv.ty.arrayLenIncludingSentinel();18787 const check_len = array_tv.ty.arrayLenIncludingSentinel();
18783 if (elem_ptr.index >= check_len) {
18784 // TODO have the deref include the decl so we can say "declared here"
18785 return sema.fail(block, src, "comptime load of index {d} out of bounds of array length {d}", .{
18786 elem_ptr.index, check_len,
18787 });
18788 }
18789
18790 if (maybe_array_ty) |load_ty| {18788 if (maybe_array_ty) |load_ty| {
18791 // It's possible that we're loading a [N]T, in which case we'd like to slice18789 // It's possible that we're loading a [N]T, in which case we'd like to slice
18792 // the pointee array directly from our parent array.18790 // the pointee array directly from our parent array.
...@@ -18800,10 +18798,10 @@ fn beginComptimePtrLoad(...@@ -18800,10 +18798,10 @@ fn beginComptimePtrLoad(
18800 }18798 }
18801 }18799 }
1880218800
18803 deref.pointee = .{18801 deref.pointee = if (elem_ptr.index < check_len) TypedValue{
18804 .ty = elem_ty,18802 .ty = elem_ty,
18805 .val = try array_tv.val.elemValue(sema.arena, elem_ptr.index),18803 .val = try array_tv.val.elemValue(sema.arena, elem_ptr.index),
18806 };18804 } else null;
18807 break :blk deref;18805 break :blk deref;
18808 },18806 },
1880918807