aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-11-30 23:56:57 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-11-30 23:56:57 -0700
commit8f9d857932dfb3abb97852dacc90c88a613a1b25 (patch)
treeb61ca956811af80bdc8d9bc0115ca9d377ad6c76 /src/type.zig
parent7355a201336c8e3892427e5932fe5cdd46cf96df (diff)
downloadzig-8f9d857932dfb3abb97852dacc90c88a613a1b25.tar.gz
zig-8f9d857932dfb3abb97852dacc90c88a613a1b25.zip
Sema: fix error set merging creating references to invalid memory
Trying to use std.heap.page_allocator with stage2 now results in (incorrect) compile errors rather than UAF.
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/type.zig b/src/type.zig
index 979c5251d7..a293848b89 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -61,11 +61,17 @@ pub const Type = extern union {
.c_longdouble,
=> return .Float,
+ .error_set,
+ .error_set_single,
+ .anyerror,
+ .error_set_inferred,
+ .error_set_merged,
+ => return .ErrorSet,
+
.c_void, .@"opaque" => return .Opaque,
.bool => return .Bool,
.void => return .Void,
.type => return .Type,
- .error_set, .error_set_single, .anyerror, .error_set_inferred => return .ErrorSet,
.comptime_int => return .ComptimeInt,
.comptime_float => return .ComptimeFloat,
.noreturn => return .NoReturn,
@@ -608,6 +614,9 @@ pub const Type = extern union {
return true;
},
.ErrorSet => {
+ // TODO: revisit the language specification for how to evaluate equality
+ // for error set types.
+
if (a.tag() == .anyerror and b.tag() == .anyerror) {
return true;
}
@@ -892,6 +901,14 @@ pub const Type = extern union {
.payload = try payload.payload.copy(allocator),
});
},
+ .error_set_merged => {
+ const names = self.castTag(.error_set_merged).?.data;
+ const duped_names = try allocator.alloc([]const u8, names.len);
+ for (duped_names) |*name, i| {
+ name.* = try allocator.dupe(u8, names[i]);
+ }
+ return Tag.error_set_merged.create(allocator, duped_names);
+ },
.error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
.error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred),
.error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
@@ -1185,6 +1202,16 @@ pub const Type = extern union {
const func = ty.castTag(.error_set_inferred).?.data.func;
return writer.print("(inferred error set of {s})", .{func.owner_decl.name});
},
+ .error_set_merged => {
+ const names = ty.castTag(.error_set_merged).?.data;
+ try writer.writeAll("error{");
+ for (names) |name, i| {
+ if (i != 0) try writer.writeByte(',');
+ try writer.writeAll(name);
+ }
+ try writer.writeAll("}");
+ return;
+ },
.error_set_single => {
const name = ty.castTag(.error_set_single).?.data;
return writer.print("error{{{s}}}", .{name});
@@ -1365,6 +1392,7 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.error_set_inferred,
+ .error_set_merged,
.@"opaque",
.generic_poison,
.array_u8,
@@ -1525,6 +1553,7 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.error_set_inferred,
+ .error_set_merged,
.manyptr_u8,
.manyptr_const_u8,
.atomic_order,
@@ -1783,6 +1812,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.anyerror,
.error_set_inferred,
+ .error_set_merged,
=> return 2, // TODO revisit this when we have the concept of the error tag type
.array, .array_sentinel => return self.elemType().abiAlignment(target),
@@ -2021,6 +2051,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.anyerror,
.error_set_inferred,
+ .error_set_merged,
=> return 2, // TODO revisit this when we have the concept of the error tag type
.int_signed, .int_unsigned => {
@@ -2199,6 +2230,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.anyerror,
.error_set_inferred,
+ .error_set_merged,
=> return 16, // TODO revisit this when we have the concept of the error tag type
.int_signed, .int_unsigned => self.cast(Payload.Bits).?.data,
@@ -2961,7 +2993,7 @@ pub const Type = extern union {
return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) };
},
- .error_set, .error_set_single, .anyerror, .error_set_inferred => {
+ .error_set, .error_set_single, .anyerror, .error_set_inferred, .error_set_merged => {
// TODO revisit this when error sets support custom int types
return .{ .signedness = .unsigned, .bits = 16 };
},
@@ -3250,6 +3282,7 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.error_set_inferred,
+ .error_set_merged,
.@"opaque",
.var_args_param,
.manyptr_u8,
@@ -3882,6 +3915,7 @@ pub const Type = extern union {
error_set_single,
/// The type is the inferred error set of a specific function.
error_set_inferred,
+ error_set_merged,
empty_struct,
@"opaque",
@"struct",
@@ -3986,6 +4020,7 @@ pub const Type = extern union {
.error_set => Payload.ErrorSet,
.error_set_inferred => Payload.ErrorSetInferred,
+ .error_set_merged => Payload.ErrorSetMerged,
.array, .vector => Payload.Array,
.array_sentinel => Payload.ArraySentinel,
@@ -4090,6 +4125,13 @@ pub const Type = extern union {
data: *Module.ErrorSet,
};
+ pub const ErrorSetMerged = struct {
+ pub const base_tag = Tag.error_set_merged;
+
+ base: Payload = Payload{ .tag = base_tag },
+ data: []const []const u8,
+ };
+
pub const ErrorSetInferred = struct {
pub const base_tag = Tag.error_set_inferred;
@@ -4125,6 +4167,12 @@ pub const Type = extern union {
try self.map.put(gpa, entry.key_ptr.*, {});
}
},
+ .error_set_merged => {
+ const names = err_set_ty.castTag(.error_set_merged).?.data;
+ for (names) |name| {
+ try self.map.put(gpa, name, {});
+ }
+ },
.anyerror => {
self.is_anyerror = true;
},