lang: fix struct-field null/undef over-store (issue 0154)
Assigning null/--- to a struct field picked up a leaked enclosing target_type (the function's return type, set for the whole body), so constNull/constUndef built a whole-struct-typed value. The oversized store overran the field's slot and clobbered the saved frame pointer, so the function returned to 0x0. Surfaced building a by-value-returned struct whose array field precedes a pointer field (Scheduler.init()). Fix: add null_literal/undef_literal to the needs_target switch in lowerAssignment so the field's own type is used. Regression: examples/types/0193-types-sret-array-before-pointer.sx.
This commit is contained in:
@@ -629,7 +629,14 @@ pub fn lowerAssignment(self: *Lowering, asgn: *const ast.Assignment) void {
|
||||
// unchanged into method-call arg slots (`resolveCallParamTypes` can't
|
||||
// override target_type per-arg).
|
||||
const needs_target = switch (asgn.value.data) {
|
||||
.enum_literal, .struct_literal, .tuple_literal, .if_expr, .match_expr, .block, .unary_op, .binary_op => true,
|
||||
// `null` / `---` (undef) carry NO type of their own — they take the
|
||||
// store slot's type from `target_type`. Without setting it to the
|
||||
// field type here, a leaked enclosing `target_type` (e.g. the
|
||||
// function's return type while lowering its body, decl.zig:2691)
|
||||
// reaches `constNull`/`constUndef` and builds a WHOLE-STRUCT-typed
|
||||
// null, emitting an oversized store that overruns the field's slot
|
||||
// and corrupts neighboring stack (issue 0154).
|
||||
.enum_literal, .struct_literal, .tuple_literal, .if_expr, .match_expr, .block, .unary_op, .binary_op, .null_literal, .undef_literal => true,
|
||||
.call => |vc| vc.callee.data == .enum_literal,
|
||||
else => false,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user