GCC `-fsanitize = bounds` weird behavior with` std :: array`

I am trying to find border problems in my code using the -fsanitize=bounds option, but have -fsanitize=bounds into strange behavior:

For example, in the following code:

 #include <cstdlib> #include <array> int main (int, char **) { std::array <char, 1> a; const char b = a [X]; // X <--- put index here! return EXIT_SUCCESS; } 

compiled with parameters: $ g++ -std=c++11 -fsanitize=bounds -O0 main.cpp -o main .

If I try to access an element with an index greater than 1, errors will be reported: /usr/include/c++/5/array:53:36: runtime error: index 2 out of bounds for type 'char [1]' .

But if I try to access the element with index 1 - everything is OK and error messages are not reported.

Is behavior expected, and maybe I missed something?

An example is tested on:
- $ g++ --version g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609 ;
- $ g++ --version g++ (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005 .

UPD
I tried -fsanitize=bounds-stric in GCC 6 and got the same.

+5
source share
2 answers

I cannot immediately find the documentation for this (or, indeed, strong documentation of any type), but it seems likely to me that this is a detail of the implementation of this function. The right to get pointers from one end to the end, so the implementation cannot trap on this. It seems that the implementation works by looking at the pointer, rather than waiting for the pointer to be dereferenced (which makes sense if you are thinking about how to create -fsanitize=bounds ).

In short, this may just be a tool limitation.

In GCC 6, you can try -fsanitize=bounds-strict , which increases the strength of the tool (including adding support to detect OOB access to flexible members such as arrays).

I can’t say whether this is a problem for the library or the compiler, but in any case it is worth noting that at the same time the problem is an open error against clang ( # 21485 ), and the assumption in the comments matches my misses above.

A third-party article on ubsan also implies that this is ultimately the expected behavior.

+1
source

From https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html

-fsanitize = limits This option allows you to measure the bounds of the array. Various extraordinary calls have been detected. Flexible array elements, flexible arrays like elements, and variable initializers with static storage are not performed.

Using X> 1 forces this check (array outside) to run, as expected due to the declaration of 'a' char, with size = 1.

EDIT

Being what he said, as @Lightness Races says in orbit, this is not the answer. But it offers some information for readers.

The fact that the case X == 1 is one end makes me think of iterators where one end is allowed. IOW, it seems that the GCC sanitizer is getting an iterator for testing instead of a [X] link.

@Gluttton confirms that using a C-like array instead of std :: array, case a [1] is shown as an error, as expected.

0
source

Source: https://habr.com/ru/post/1259967/


All Articles