1

In the context of a tool comparison, I do not want to be unfair to ASan if it can detect the problem in the program below:

$ cat t.c
#include <stdio.h>

int *G;

int f(void) {
  int l = 1;
  int res = *G;
  G = &l;
  return res + *G;
}

int main(void) {
  int x = 2;
  G = &x;
  f();
  printf("%d\n", f());
}
$ clang -v
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9
...
$ clang -O2 -fsanitize=address t.c
$ ./a.out 
1
$ clang -fsanitize=address t.c
$ ./a.out 
2

The first occurence of G the second time f is called invokes undefined behavior, because G is indeterminate at that point. In addition, G is immediately dereferenced, making this the sort of memory error that one may expect ASan to detect. It is part of ASan's specifications that it sometimes fails to detect problems of the kind it is supposed to find, but I want to know if I could have used it to find this particular problem here.

I found the option -fsanitize-address-use-after-scope here, but this option does not work in the version of Clang I am using:

$ clang -fsanitize=address t.c -fsanitize-address-use-after-scope
clang: error: unknown argument: '-fsanitize-address-use-after-scope'

Is there an ASan version that flags an error at the execution of the above program, with or without special commandline options?

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • This is a really hard case actually. First of all you have to remember that arguments to a function must be evaluated before they are used in a function call, which means the second call to `f` happens *before* the call to `printf`. That in turn most likely mean that the location of the local variables in the function `f` will be exactly the same in the second call as in the first, which in turn means that the pointer `G` is actually pointing to the correct location in the second call. – Some programmer dude May 31 '17 at 10:21
  • @olaf I do not understand what element of your list is missing. Code is there and is certainly short, desired behavior: a warning, obtained behavior: no warning. Thanks for the link. Oh that's right you didn't provide a link. Don't worry, I know what a Minimal, Complete, and Verifiable example is. – Pascal Cuoq May 31 '17 at 11:46
  • 1
    @Olaf You removed the C tag and now I agree that after your change, the question is nonsensical. It doesn't even specify the programming language! You made it so though, not me. – Pascal Cuoq May 31 '17 at 11:47
  • Adding again the C tag because for all I know, there exists a programming language in which my program is syntactically valid and does not have undefined behavior. This question couldn't make sense if it were asked about that programming language. And you need to understand C in order to understand the question. – Pascal Cuoq May 31 '17 at 11:53

3 Answers3

2

You are talking about use-after-return errors here. These should be supported by ASan but disabled by default due to significantly higher memory overhead (see e.g. here for details). To enable, run with ASAN_OPTIONS=detect_stack_use_after_return=1.

Unfortunately I can't check whether it works on your particular case but if it doesn't, you should probly file a bug at ASan's tracker.

yugr
  • 19,769
  • 3
  • 51
  • 96
0

yugr has pointed me to the correct way to activate detection of the error in my test program. This functionality already exists in Clang 3.8.

For completeness, the results with Clang 3.8 are below. It is interesting that the issue is detected at the default optimization level but is not detected at -O2.

$ clang -fsanitize=address t.c -Wall
$ ASAN_OPTIONS=detect_stack_use_after_return=1 ./a.out 
=================================================================
==21949==ERROR: AddressSanitizer: stack-use-after-return on address 0x7f5eeb100060 ...
READ of size 4 at 0x7f5eeb100060 thread T0
...
$ clang -O2 -fsanitize=address t.c -Wall
$ ASAN_OPTIONS=detect_stack_use_after_return=1 ./a.out
1
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • 1
    "not detected at -O2" - unfortunately GCC and Clang like to exploit UB and ASan developers chose to not alter this behavior. Also check the "Why didn't ASan report an obviously invalid memory access in my code?" question in [FAQ](https://github.com/google/sanitizers/wiki/AddressSanitizer). – yugr May 31 '17 at 17:46
  • "ASan developers chose to not alter this behavior" - probly because compiler should emit a warning when exploiting undefined behavior (and if it doesn't, it could be considered as bug in compiler). – yugr Jun 01 '17 at 08:45
  • @yugr “if it doesn't, it could be considered as bug in compiler” This is not what the developers of Clang and GCC say. There is a three-blog-post essay by Chris Lattner, but so sum them up: No, and it won't happen. http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html – Pascal Cuoq Jun 01 '17 at 09:36
  • @yugr One idea that is currently too widespread for its truth value is that sanitizers such as ASan, UBSan, … are an exhaustive solution to the problem. It is while working on a blog post on this subject that I ended up testing the C program in this question. – Pascal Cuoq Jun 01 '17 at 09:40
  • True, sanitizers try really hard but are not exhaustive. Default options are quite permissive (for a fuller list see Asan's FAQ), unrelated compiler passes may prevent sanitizers from detecting errors (which should arguably be reported and fixed, either by Asan or Clang devs), finally some low level memory bugs can not be uncovered due to tool limitations. Finally, MemorySanitizer (tool for detecting uninitialized values) is still prohibitively hard to integrate to production systems. – yugr Jun 01 '17 at 09:58
  • 1
    For completeness, the final article has been published [here](https://blog.regehr.org/archives/1520). – yugr Jul 11 '17 at 12:30
-1

Your version: clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)

Header of page: Clang 5 documentation

You have to update your clang

Alistra
  • 5,177
  • 2
  • 30
  • 42