diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-09-12 13:32:14 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-09-12 20:08:56 -0400 |
| commit | cb6201715a7bcae2b278811186afc17a697b25f7 (patch) | |
| tree | 30db7b0844d0769b87664e83164f734fae1a9627 /src/value.zig | |
| parent | 7e2b6b0f1bc5877f11c50a217dd88c11481bbad4 (diff) | |
| download | zig-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.zig | 7 |
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); |
