From 928d43f61a9b08fd9c83964c34a29cca85839226 Mon Sep 17 00:00:00 2001 From: antlilja Date: Mon, 31 Jul 2023 16:49:19 +0200 Subject: [PATCH] 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. --- src/codegen.zig | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index 1d83d452b9bc14faaaef15450eb0dfd5f0181add..c1a956a7656379b34ad7ec7954713babfa443a54 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, -- 2.54.0