Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

clang-analyzer-valist.Uninitialized warning on use of a copied valist #40281

Open Quuxplusone opened 5 years ago

Quuxplusone commented 5 years ago
Bugzilla Link PR41311
Status NEW
Importance P enhancement
Reported by Julie Hockett (juliehockett@google.com)
Reported on 2019-03-29 11:33:21 -0700
Last modified on 2021-07-16 09:03:15 -0700
Version trunk
Hardware PC Linux
CC aa1ronham@gmail.com, dcoughlin@apple.com, jynelson@email.sc.edu, llvm-bugs@lists.llvm.org, nicke.claesson@gmail.com, noqnoqneo@gmail.com, oleksii.vilchanskyi@gmail.com
Fixed by commit(s)
Attachments tmp.i (16119 bytes, text/plain)
Blocks
Blocked by
See also
When running the clang-analyzer checks under clang-tidy, the clang-analyzer-
valist.Uninitialized warning is firing on a valist copied using va_copy().

Command: clang-tidy --checks="-*,clang-analyzer-*" example.cpp

Minimal example.cpp:

#include <stdarg.h>
#include <stdio.h>

void StringVPrintf(const char* format, va_list ap) {
    char stack_buf[1024u];
    va_list ap_copy;
    va_copy(ap_copy, ap);
    vsnprintf(stack_buf, 1024u, format, ap_copy);
    va_end(ap_copy);
}

Clang-tidy warning:

example.cpp:8:5: warning: Function 'vsnprintf' is called with an uninitialized
va_list argument [clang-analyzer-valist.Uninitialized]
    vsnprintf(stack_buf, 1024u, format, ap_copy);
    ^
example.cpp:8:5: note: Function 'vsnprintf' is called with an uninitialized
va_list argument
Quuxplusone commented 5 years ago

Gabor, do you know what is this about? :)

Quuxplusone commented 5 years ago
Hi!

I unfortunately could not reproduce this problem. What architecture are you
using? What standard libraries? Could you also attach a preprocessed file?

As far as I remember, for different target architectures the va_lists have
different representation. My suspicion is that, probably not all of the
possible representations are handled by the checker currently.

Thanks,
Gabor
Quuxplusone commented 5 years ago

I also cannot reproduce, but this is because in my case builtins aren't recognized at all. I guess we need to make a more consistent solution for recognizing all the builtins.

Quuxplusone commented 5 years ago

I have a similar issue. The warning only arises when there are multiple copies of the source file in the "compile_commands.json" file.

$ cat main.c
#include <stdio.h>
#include <stdarg.h>

void my_fun(int a, const char* fmt, ...) {
    char buf[100];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, 100, fmt, args);
    va_end(args);
    printf("%s", buf);
}

int main(void) {
    my_fun(42, "%d\n", 1);
    return 0;
}
$ cat compile_commands.json
[
{ "directory": "/home/niklas/projects/c-examples/vprintf",
  "command": "gcc -o main main.c",
  "file": "/home/niklas/projects/c-examples/vprintf/main.c"},
{ "directory": "/home/niklas/projects/c-examples/vprintf",
  "command": "gcc -o main main.c",
  "file": "/home/niklas/projects/c-examples/vprintf/main.c"}
]
$ clang-tidy-8 main.c
1 warning generated.
main.c:8:5: warning: Function 'vsnprintf' is called with an uninitialized va_list argument [clang-analyzer-valist.Uninitialized]
    vsnprintf(buf, 100, fmt, args);
    ^
main.c:8:5: note: Function 'vsnprintf' is called with an uninitialized va_list argument

I hope you can reproduce the issue!

Quuxplusone commented 4 years ago

Not sure what the compile_commands file is, but I have the same problem if I run clang-tidy with more than one source file:

$ cat tmp.c
#include<stdarg.h>
#include<stdio.h>
int f(char *format, ...) {
    int len;
    va_list args;
    va_start(args, format);
    len = vsnprintf((void*)0, 0, format, args);
    va_end(args);
    return len;
}

$ clang-tidy main.c tmp.c
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "main.c"
No compilation database found in /home/joshua/src/c/threaded/src or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
1 warning generated.
/home/joshua/src/c/threaded/src/tmp.c:7:11: error: Function 'vsnprintf' is called with an uninitialized va_list argument [clang-analyzer-valist.Uninitialized,-warnings-as-errors]
    len = vsnprintf((void*)0, 0, format, args);
          ^
/home/joshua/src/c/threaded/src/tmp.c:7:11: note: Function 'vsnprintf' is called with an uninitialized va_list argument
Quuxplusone commented 4 years ago

As a work-around, you can run clang-tidy on only one file at a time:

$ parallel clang-tidy -- main.c tmp.c   # parallel from `moreutils`, not GNU parallel

That avoids the false positive. (Yes, I'm still running into this a year later.)

Quuxplusone commented 4 years ago

I still can't reproduce with multiple files.

Please send us a preprocessed file because different implementations of standard headers on different systems may affect analysis results.

Quuxplusone commented 4 years ago

Attached tmp.i (16119 bytes, text/plain): tmp.i

Quuxplusone commented 3 years ago

I'm happy to help debug if you're still having trouble reproducing this.

Quuxplusone commented 3 years ago

I've created a smaller reproduction:

first_file.cpp

extern void my_extern_fn();

void first_fn() {
    my_extern_fn();
}

second_file.cpp

void second_fn(int my_arg, ...) {
    __builtin_va_list args;

    __builtin_va_start(args, my_arg);
    __builtin_va_arg(args, int);
    __builtin_va_end(args);
}

Running clang-tidy-12 first_file.cpp second_file.cpp results in the following output:

Error while trying to load a compilation database:
Could not auto-detect compilation database for file "first_file.cpp"
No compilation database found in /home/aaron/repos/tidy-bug or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
1 warning generated.
/home/aaron/repos/tidy-bug/second_file.cpp:5:5: warning: va_arg() is called on an uninitialized va_list [clang-analyzer-valist.Uninitialized]
    __builtin_va_arg(args, int);
    ^
/home/aaron/repos/tidy-bug/second_file.cpp:5:5: note: va_arg() is called on an uninitialized va_list

Running clang-tidy first_file.cpp or clang-tidy second_file.cpp does not produce any warnings.