aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorantlilja <liljaanton2001@gmail.com>2023-07-31 16:49:19 +0200
committerAndrew Kelley <andrew@ziglang.org>2023-07-31 15:14:31 -0700
commit928d43f61a9b08fd9c83964c34a29cca85839226 (patch)
tree41285239ba4d29f2d75aaf44029876d4b212c15c /src/codegen.zig
parent33e4cbb20f7cac71e5feaeeeb4c7576ab4708697 (diff)
downloadzig-928d43f61a9b08fd9c83964c34a29cca85839226.tar.gz
zig-928d43f61a9b08fd9c83964c34a29cca85839226.zip
Fix integer overflow in field padding calculation
The old code was iterating and generating symbols for fields in their declared order instead of the memory optimized order while getting offsets in the memory optimized order.
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig28
1 files changed, 15 insertions, 13 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 1d83d452b9..c1a956a765 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -513,19 +513,27 @@ pub fn generateSymbol(
}
} else {
const struct_begin = code.items.len;
- for (struct_obj.fields.values(), 0..) |field, index| {
- const field_ty = field.ty;
+ const fields = struct_obj.fields.values();
+
+ var it = typed_value.ty.iterateStructOffsets(mod);
+
+ while (it.next()) |field_offset| {
+ const field_ty = fields[field_offset.field].ty;
+
if (!field_ty.hasRuntimeBits(mod)) continue;
const field_val = switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
.bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
.ty = field_ty.toIntern(),
- .storage = .{ .u64 = bytes[index] },
+ .storage = .{ .u64 = bytes[field_offset.field] },
} }),
- .elems => |elems| elems[index],
+ .elems => |elems| elems[field_offset.field],
.repeated_elem => |elem| elem,
};
+ const padding = math.cast(usize, field_offset.offset - (code.items.len - struct_begin)) orelse return error.Overflow;
+ if (padding > 0) try code.appendNTimes(0, padding);
+
switch (try generateSymbol(bin_file, src_loc, .{
.ty = field_ty,
.val = field_val.toValue(),
@@ -533,16 +541,10 @@ pub fn generateSymbol(
.ok => {},
.fail => |em| return Result{ .fail = em },
}
- const unpadded_field_end = code.items.len - struct_begin;
-
- // Pad struct members if required
- const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod);
- const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse return error.Overflow;
-
- if (padding > 0) {
- try code.appendNTimes(0, padding);
- }
}
+
+ const padding = math.cast(usize, std.mem.alignForward(u64, it.offset, @max(it.big_align, 1)) - (code.items.len - struct_begin)) orelse return error.Overflow;
+ if (padding > 0) try code.appendNTimes(0, padding);
}
},
else => unreachable,