Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang's -fcatch-undefined-behavior not working as advertised

I built the 3.1 release of llvm/compiler-rt/clang, and I'm trying to see if -fcatch-undefined-behavior really does anything. So far, no luck. E.g. I compile and run

#include <stdio.h>
#include <stdlib.h>

int main() {
    int* x = malloc(sizeof(int) * 10);
    printf("%d\n", x[20]);
    return 0;
}

with

$ /usr/local/bin/clang -fcatch-undefined-behavior undef_test.c && ./a.out
0

Am I missing something really simple?

like image 695
Oleg2718281828 Avatar asked Jun 28 '12 08:06

Oleg2718281828


2 Answers

Yes: x is not an array.

From the documentation:

-fcatch-undefined-behavior: Turn on runtime code generation to check for undefined behavior. This option, which defaults to off, controls whether or not Clang adds runtime checks for undefined runtime behavior. If a check fails, __builtin_trap() is used to indicate failure. The checks are:

  • Subscripting where the static type of one operand is a variable which is decayed from an array type and the other operand is greater than the size of the array or less than zero.
  • Shift operators where the amount shifted is greater or equal to the promoted bit-width of the left-hand-side or less than zero.
  • If control flow reaches __builtin_unreachable.
  • When llvm implements more __builtin_object_size support, reads and writes for objects that __builtin_object_size indicates we aren't accessing valid memory. Bit-fields and vectors are not yet checked.

I suppose you wanted to test the subscripting check, unfortunately you did not build an array: you built an area of memory (from malloc) and then chose to interpret it as an array; but from the point of view of the compiler it is just a chunk of memory (remember than the return type of malloc is void*).

You could probably test this behavior with:

int main() {
    int x[10] = {};
    printf("%d\n", x[20]);
}

Otherwise, for a specific memory issues tracker, you should look into the Address Sanitizer plugin.

like image 98
Matthieu M. Avatar answered Sep 23 '22 21:09

Matthieu M.


-fcatch-undefined-behavior doesn't handle random pointer dereferences. To handle this case, the compiler would have to store the size of the pointed data alongside the pointer and pass that size in every function call. That would be incompatible with the existing ABI and would require to recompile all the libraries your program link to.

You may argue that malloc is a well-known function and the compiler could just assume the returned pointer points to an array of the requested size.

But you would be forgetting that malloc may return NULL. If the compiler assumed the pointer isn't NULL, it would optimize out any NULL checking (quite dangerous). If the compiler assumed the pointer is NULL or a pointer to an array of the requested size, that would become a little complicated to manage (and we haven't talk of free and realloc yet). Moreover any code that dereferences a malloc-ated pointer without NULL checking would be considered as undefined behavior.

Not to mention that your program may not link to the standard library but to a library that provides a custom implementation of malloc with a different semantic.

like image 35
Nicolas Bachschmidt Avatar answered Sep 19 '22 21:09

Nicolas Bachschmidt