authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2023-07-31 16:49:19+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-31 15:14:31-07:00
log928d43f61a9b08fd9c83964c34a29cca85839226
tree41285239ba4d29f2d75aaf44029876d4b212c15c
parent33e4cbb20f7cac71e5feaeeeb4c7576ab4708697

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 files changed, 15 insertions(+), 13 deletions(-)

src/codegen.zig+15-13
......@@ -513,19 +513,27 @@ pub fn generateSymbol(
513513 }
514514 } else {
515515 const struct_begin = code.items.len;
516 for (struct_obj.fields.values(), 0..) |field, index| {
517 const field_ty = field.ty;
516 const fields = struct_obj.fields.values();
517
518 var it = typed_value.ty.iterateStructOffsets(mod);
519
520 while (it.next()) |field_offset| {
521 const field_ty = fields[field_offset.field].ty;
522
518523 if (!field_ty.hasRuntimeBits(mod)) continue;
519524
520525 const field_val = switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
521526 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
522527 .ty = field_ty.toIntern(),
523 .storage = .{ .u64 = bytes[index] },
528 .storage = .{ .u64 = bytes[field_offset.field] },
524529 } }),
525 .elems => |elems| elems[index],
530 .elems => |elems| elems[field_offset.field],
526531 .repeated_elem => |elem| elem,
527532 };
528533
534 const padding = math.cast(usize, field_offset.offset - (code.items.len - struct_begin)) orelse return error.Overflow;
535 if (padding > 0) try code.appendNTimes(0, padding);
536
529537 switch (try generateSymbol(bin_file, src_loc, .{
530538 .ty = field_ty,
531539 .val = field_val.toValue(),
......@@ -533,16 +541,10 @@ pub fn generateSymbol(
533541 .ok => {},
534542 .fail => |em| return Result{ .fail = em },
535543 }
536 const unpadded_field_end = code.items.len - struct_begin;
537
538 // Pad struct members if required
539 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod);
540 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse return error.Overflow;
541
542 if (padding > 0) {
543 try code.appendNTimes(0, padding);
544 }
545544 }
545
546 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;
547 if (padding > 0) try code.appendNTimes(0, padding);
546548 }
547549 },
548550 else => unreachable,