Files
sx/examples/issue-0011.sx
2026-03-05 16:20:36 +02:00

52 lines
1.5 KiB
Plaintext

// issue-0011: Assigning to List(T).items corrupts adjacent memory when T is large
//
// Writing `list.items = xx 0` overwrites memory beyond the 8-byte items pointer
// when the List's element type T is larger than 32 bytes. The corruption spills
// into the struct field that follows the List in memory.
//
// Works correctly when size_of(T) <= 32.
// Fails when size_of(T) > 32 (e.g., 40 bytes).
//
// Likely cause: codegen confuses size_of(T) with size_of([*]T) when generating
// the store instruction for the items field.
#import "modules/std.sx";
// 40-byte struct — triggers the bug.
// Shrink to [4]s64 (32 bytes) and the bug goes away.
BigNode :: struct {
data: [5]s64; // 40 bytes
}
Tree :: struct {
nodes: List(BigNode); // items(8) + len(8) + cap(8) = 24 bytes
generation: s64; // 8 bytes — total 32 bytes
}
Container :: struct {
tree: Tree;
sentinel: s64;
do_work :: (self: *Container) {
self.tree.nodes.items = xx 0; // BUG: corrupts self.sentinel
}
}
main :: () -> void {
obj : *Container = xx context.allocator.alloc(size_of(Container));
memset(obj, 0, size_of(Container));
obj.sentinel = 0xDEADBEEF;
print("size_of BigNode = {}\n", size_of(BigNode));
print("before: sentinel = {}\n", obj.sentinel);
obj.do_work();
print("after: sentinel = {}\n", obj.sentinel);
if obj.sentinel != 0xDEADBEEF {
print("BUG: sentinel was corrupted!\n");
} else {
out("OK\n");
}
}