Skip to content

Commit 06d08da

Browse files
Justus2308mlugg
authored andcommitted
Sema: fix illegal multi level pointer coercions
Moves a premature check that allowed pointers to mutable pointers to coerce to any other pointer to a mutable pointer.
1 parent c6b5945 commit 06d08da

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

src/Sema.zig

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29385,14 +29385,18 @@ const InMemoryCoercionResult = union(enum) {
2938529385
break;
2938629386
},
2938729387
.array_sentinel => |sentinel| {
29388-
if (sentinel.actual.toIntern() != .unreachable_value) {
29389-
try sema.errNote(src, msg, "array sentinel '{f}' cannot cast into array sentinel '{f}'", .{
29390-
sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
29388+
if (sentinel.wanted.toIntern() == .unreachable_value) {
29389+
try sema.errNote(src, msg, "source array cannot be guaranteed to maintain '{f}' sentinel", .{
29390+
sentinel.actual.fmtValueSema(pt, sema),
2939129391
});
29392-
} else {
29392+
} else if (sentinel.actual.toIntern() == .unreachable_value) {
2939329393
try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{
2939429394
sentinel.wanted.fmtValueSema(pt, sema),
2939529395
});
29396+
} else {
29397+
try sema.errNote(src, msg, "array sentinel '{f}' cannot cast into array sentinel '{f}'", .{
29398+
sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
29399+
});
2939629400
}
2939729401
break;
2939829402
},
@@ -30179,10 +30183,14 @@ fn coerceInMemoryAllowedPtrs(
3017930183
src_src,
3018030184
null,
3018130185
);
30182-
if (child != .ok and !dest_is_mut) allow: {
30186+
if (child != .ok) allow: {
3018330187
// As a special case, we also allow coercing `*[n:s]T` to `*[n]T`, akin to dropping the sentinel from a slice.
3018430188
// `*[n:s]T` cannot coerce in memory to `*[n]T` since they have different sizes.
30185-
if (src_child.zigTypeTag(zcu) == .array and dest_child.zigTypeTag(zcu) == .array and
30189+
//
30190+
// We must once again include `dest_is_mut` because `**[n:s]T -> **[n]T`
30191+
// is not allowed, as it would make it possible to assign an illegal value
30192+
// to the sentinel-terminated side.
30193+
if (!dest_is_mut and src_child.zigTypeTag(zcu) == .array and dest_child.zigTypeTag(zcu) == .array and
3018630194
src_child.arrayLen(zcu) == dest_child.arrayLen(zcu) and
3018730195
src_child.sentinel(zcu) != null and dest_child.sentinel(zcu) == null and
3018830196
.ok == try sema.coerceInMemoryAllowed(block, dest_child.childType(zcu), src_child.childType(zcu), !dest_info.flags.is_const, target, dest_src, src_src, null))
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
export fn entry1() void {
2+
const p: **u32 = undefined;
3+
const q: **i32 = p;
4+
_ = q;
5+
}
6+
7+
export fn entry2() void {
8+
const p: [*]*u32 = undefined;
9+
const q: [*]*i32 = p;
10+
_ = q;
11+
}
12+
13+
export fn entry3() void {
14+
const p: []*u32 = undefined;
15+
const q: []*i32 = p;
16+
_ = q;
17+
}
18+
19+
export fn entry4() void {
20+
const p: [*c]*u32 = undefined;
21+
const q: [*c]*i32 = p;
22+
_ = q;
23+
}
24+
25+
export fn entry5() void {
26+
const p: **[1:42]u8 = undefined;
27+
const q: **[1]u8 = p;
28+
_ = q;
29+
}
30+
31+
// error
32+
//
33+
// :3:22: error: expected type '**i32', found '**u32'
34+
// :3:22: note: pointer type child '*u32' cannot cast into pointer type child '*i32'
35+
// :3:22: note: pointer type child 'u32' cannot cast into pointer type child 'i32'
36+
// :3:22: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
37+
// :9:24: error: expected type '[*]*i32', found '[*]*u32'
38+
// :9:24: note: pointer type child '*u32' cannot cast into pointer type child '*i32'
39+
// :9:24: note: pointer type child 'u32' cannot cast into pointer type child 'i32'
40+
// :9:24: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
41+
// :15:23: error: expected type '[]*i32', found '[]*u32'
42+
// :15:23: note: pointer type child '*u32' cannot cast into pointer type child '*i32'
43+
// :15:23: note: pointer type child 'u32' cannot cast into pointer type child 'i32'
44+
// :15:23: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
45+
// :21:25: error: expected type '[*c]*i32', found '[*c]*u32'
46+
// :21:25: note: pointer type child '*u32' cannot cast into pointer type child '*i32'
47+
// :21:25: note: pointer type child 'u32' cannot cast into pointer type child 'i32'
48+
// :21:25: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
49+
// :27:24: error: expected type '**[1]u8', found '**[1:42]u8'
50+
// :27:24: note: pointer type child '*[1:42]u8' cannot cast into pointer type child '*[1]u8'
51+
// :27:24: note: pointer type child '[1:42]u8' cannot cast into pointer type child '[1]u8'
52+
// :27:24: note: source array cannot be guaranteed to maintain '42' sentinel

0 commit comments

Comments
 (0)