Skip to content

[MSan] LLVM 16 causes MSan false positives with va_list on MIPS #64135

Open
@vit9696

Description

@vit9696

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions