aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-09-12 13:32:14 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-09-12 20:08:56 -0400
commitcb6201715a7bcae2b278811186afc17a697b25f7 (patch)
tree30db7b0844d0769b87664e83164f734fae1a9627 /src/value.zig
parent7e2b6b0f1bc5877f11c50a217dd88c11481bbad4 (diff)
downloadzig-cb6201715a7bcae2b278811186afc17a697b25f7.tar.gz
zig-cb6201715a7bcae2b278811186afc17a697b25f7.zip
InternPool: prevent anon struct UAF bugs with type safety
Instead of using actual slices for InternPool.Key.AnonStructType, this commit changes to use Slice types instead, which store a long-lived index rather than a pointer. This is a follow-up to 7ef1eb1c27754cb0349fdc10db1f02ff2dddd99b.
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig7
1 files changed, 4 insertions, 3 deletions
diff --git a/src/value.zig b/src/value.zig
index 848da16cf8..13eb9106b5 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -268,6 +268,7 @@ pub const Value = struct {
pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();
+ const ip = &mod.intern_pool;
switch (val.tag()) {
.eu_payload => {
const pl = val.castTag(.eu_payload).?.data;
@@ -286,7 +287,7 @@ pub const Value = struct {
.slice => {
const pl = val.castTag(.slice).?.data;
const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod);
- var ptr_key = mod.intern_pool.indexToKey(ptr).ptr;
+ var ptr_key = ip.indexToKey(ptr).ptr;
assert(ptr_key.len == .none);
ptr_key.ty = ty.toIntern();
ptr_key.len = try pl.len.intern(Type.usize, mod);
@@ -311,11 +312,11 @@ pub const Value = struct {
const old_elems = val.castTag(.aggregate).?.data[0..len];
const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);
defer mod.gpa.free(new_elems);
- const ty_key = mod.intern_pool.indexToKey(ty.toIntern());
+ const ty_key = ip.indexToKey(ty.toIntern());
for (new_elems, old_elems, 0..) |*new_elem, old_elem, field_i|
new_elem.* = try old_elem.intern(switch (ty_key) {
.struct_type => ty.structFieldType(field_i, mod),
- .anon_struct_type => |info| info.types[field_i].toType(),
+ .anon_struct_type => |info| info.types.get(ip)[field_i].toType(),
inline .array_type, .vector_type => |info| info.child.toType(),
else => unreachable,
}, mod);