Commit 928d43f61a

antlilja <liljaanton2001@gmail.com>
2023-07-31 16:49:19
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.
1 parent 33e4cbb
Changed files (1)
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,