Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC `-fsanitize=bounds` strange behaviour with `std::array`

Tags:

c++

arrays

g++

I'm trying find out of bounds problems in my code using -fsanitize=bounds option, but I faced with strange behaviour:

For instance 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 options: $ g++ -std=c++11 -fsanitize=bounds -O0 main.cpp -o main.

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

But if I try access to element with index 1, everything OK and no errors are reported.

Is it expected behaviour and may be I've missed something?

The 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.

UPDATE
I tried -fsanitize=bounds-strict in GCC 6 and resulted the same.

like image 612
Gluttton Avatar asked Nov 18 '16 12:11

Gluttton


2 Answers

I can't immediately find documentation for this (or, really, strong documentation of any kind), but it strikes me as likely that this is an implementation detail for the feature. It is legal to obtain one-past-the-end pointers, so an implementation could not trap on this. It seems the implementation works by looking at the pointer, rather than waiting for such a pointer to be dereferenced (which makes some sense if you think about how you would create -fsanitize=bounds).

In short, this may simply be a limitation of the tool.

In GCC 6, you might try -fsanitize=bounds-strict which increases the strength of the tool (including adding support for detecting OOB access to flexible member-like arrays).

I can't tell whether this is a library or compiler issue, but either way it's worth noting that the same problem is currently an open bug against clang (#21485), and the supposition in comments there matches my ramblings above.

A third-party article on ubsan also implies that this is, ultimately, expected behaviour.

like image 198
Lightness Races in Orbit Avatar answered Nov 09 '22 00:11

Lightness Races in Orbit


As @Ripi2 mentioned, the first element past the end of the array often considered as end iterator.

In this case, -fsanitize=address can detect out-of-bound bugs, when you access illeagal position of array, compiler can give more info.

g++ -std=c++11 -fsanitize=address -O0 main.cpp -o main
like image 27
douyu Avatar answered Nov 08 '22 23:11

douyu