From cd095a44db262351b09ea144a44b76e22d62c77a Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Mon, 8 Nov 2021 10:46:20 +0100 Subject: fix for sloppy reg->mem in arm64 abi Michael found a bug where some copies from registers to memory in the arm64 abi clobber the stack. The test case is: type :T = { w } function w $f() { @start %p =:T call $g() %x =w loadw %p ret %x } qbe will write 4 bytes out of bounds when pulling the result struct from its register. The same bug can be observed if :T's definition is {w 3}; in this case qbe writes 16 bytes in a slot of 12 bytes. This patch changes stkblob() to use the rounded argument size if it is going to be restored from registers. Relatedly, mem->reg loads for structs with size < 16 and != 8, are treated a bit sloppily both in the arm64 and in the sysv abis. That is much less harmful than the present bug. --- arm64/abi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arm64') diff --git a/arm64/abi.c b/arm64/abi.c index 8209944..f37c892 100644 --- a/arm64/abi.c +++ b/arm64/abi.c @@ -312,12 +312,14 @@ stkblob(Ref r, Class *c, Fn *fn, Insl **ilp) { Insl *il; int al; + uint64_t sz; il = alloc(sizeof *il); al = c->t->align - 2; /* NAlign == 3 */ if (al < 0) al = 0; - il->i = (Ins){Oalloc+al, Kl, r, {getcon(c->t->size, fn)}}; + sz = c->class & Cptr ? c->t->size : c->size; + il->i = (Ins){Oalloc+al, Kl, r, {getcon(sz, fn)}}; il->link = *ilp; *ilp = il; } -- cgit 1.4.1