Open
Description
Consider the following example:
extern void test(const char *fmt, ...);
extern void test2(const char *fmt, va_list params);
__attribute__((noinline))
void test2(const char *fmt, va_list params)
{
(void)fmt;
(void)params;
}
__attribute__((noinline))
void test(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
test2(fmt, ap);
va_end(ap);
}
void main(void) {
test("hello", 123);
}
Compiled as follows:
clang -o main.o -c -std=c18 -target mipsel-gnu-linux -ffreestanding -fno-short-enums -fno-common \
-nostdlib -g -gdwarf-4 -fno-pic -fno-pie -G0 -mno-abicalls -mfpxx -mips32r2 -modd-spreg -mmt \
-ffunction-sections -fdata-sections -nostdlibinc -mhard-float -femulated-tls \
-mllvm -msan-shadow-base=1056964608 -fsanitize=memory main.c
Starting with LLVM 16.x this will always trigger a msan warning as it thinks ap
is not initialised as seen here:
# void test(const char *fmt, ...)
.globl test
test:
fmt = -0x10
params = -0xC
var_8 = -8
var_4 = -4
var_s0 = 0
var_s4 = 4
arg_4 = 0xC
arg_8 = 0x10
arg_C = 0x14
D8 FF BD 27 addiu $sp, -0x28
24 00 BF AF sw $ra, 0x20+var_s4($sp)
20 00 BE AF sw $fp, 0x20+var_s0($sp)
25 F0 A0 03 move $fp, $sp
25 10 80 00 move $v0, $a0
34 00 C7 AF sw $a3, 0x20+arg_C($fp)
30 00 C6 AF sw $a2, 0x20+arg_8($fp)
2C 00 C5 AF sw $a1, 0x20+arg_4($fp)
00 3F 04 3C lui $a0, 0x3F00
1C 00 C1 27 addiu $at, $fp, 0x1C
21 08 24 00 addu $at, $a0
FF FF 03 24 li $v1, 0xFFFFFFFF # initialises ap shadow with POISON
00 00 23 AC sw $v1, 0($at)
00 00 20 AC sw $zero, 0($at)
1C 00 C2 AF sw $v0, 0x1C($fp)
18 00 C2 27 addiu $v0, $fp, 0x20+var_8
21 10 44 00 addu $v0, $a0
00 00 43 AC sw $v1, 0($v0) # stores poisoned ap shadow
2C 00 C3 27 addiu $v1, $fp, 0x20+arg_4
18 00 C3 AF sw $v1, 0x20+var_8($fp)
1C 00 C3 8F lw $v1, 0x20+var_4($fp)
10 00 C3 AF sw $v1, 0x20+fmt($fp)
00 00 21 8C lw $at, 0($at)
18 00 C3 8F lw $v1, 0x20+var_8($fp)
14 00 C3 AF sw $v1, 0x20+params($fp)
00 00 42 8C lw $v0, 0($v0) # reads poisoned ap shadow
25 08 22 00 or $at, $v0
05 00 20 10 beqz $at, ok
00 00 00 00 nop
35 00 40 08 j fatal
00 00 00 00 nop
# ---------------------------------------------------------------------------
fatal: # CODE XREF: test+74↑j
2A 0B 40 0C jal __msan_warning_noreturn
00 00 00 00 nop
# ---------------------------------------------------------------------------
ok:
LLVM 15 generated code does not seem to test ap
shadow at all, thus it works fine. I somewhat understand that va_list tracking is not properly implemented for architectures aside from x86_64, but this seems to be an unpleasant regression to me.
cc @vitalybuka @kcc