Unexpected behaviour of cfamily scanner results

Must-share information (formatted with Markdown):

  • which versions are you using (SonarQube, Scanner, Plugin, and any relevant extension)
    • SonarQube Developer Edition Version 9.9 (build 65466)
    • SonarScanner 5.0.1.3006
    • CFamily plugin version: 6.41.0.60884
  • what are you trying to achieve

I’m trying to get out of bounds memory access bug reports for the following code

// test if memory access out of bounds gets recognized

#include <cstdint>
#include <array>

int main()
{
  // a simple test for C-Style array oob memory access
  uint16_t c_array[10];
  c_array[10] = 0;

  // test for std::array oob memory access
  std::array<uint16_t, 10U> std_array;
  std_array[10U] = 0;
  std_array.at(10U) = 0;   // should throw on runtime

  // test for access to position from type converting
  enum class Enum : uint8_t {
    ValueA = 0xFF,
    ValueB = 0x5A,
    ValueC = 0xA5,
  };
  const uint8_t pos = static_cast<uint8_t>(Enum::ValueA);
  c_array[pos] = 0;
  std_array[pos] = 0;

  return 0;
}
  • what have you tried so far to achieve this

I run this through build-wrapper-linux-x86-64 --out-dir .sonar/bw-output/ g++ -o memory_access_out_of_bounds memory_access_out_of_bounds.cpp && sonar-scanner -X. I expect SonarQube server (or SonarLint within VSCode) report me at out of bounds memory access 5 times.

I got just one reported!

The reported out of bounds memory access was the first c_array[10] = 0 … so if I comment that line, another run reports me one out of bounds memory access in line c_array[pos] = 0;. A third try after commenting also last reported line give me no out of bound memory access errors.

So my questions are:

  • Is it expected behaviour, that only the first type of error will be reported in compile unit?
  • Is it expected behaviour, that std::array<> out of bound memory access errors are never detected?

Hi,

Welcome to the community!

This thread explains why that’s the expected behavior:

 
Ann

Thank you for this hint!
It explains why it will only catch the first out-of-bounds memory access in my example.

However, the linked message doesn’t explain why the call to std::array<T,N>::operator[] is never reported in my case. As of std::array<T,N>::operator[], accessing a non-existent element using this operator is undefined behavior … and may kill the program.

I would expect this to be detected by static analysis. Is it a known bug in my version?

Thank you for reporting this. The problem is that we don’t inline (or see through) the implementations of standard libraries even if they are available as-per source code. There is a fine balance between inlining functions, running time, and false/true-positive rates behind this choice, but nevertheless, it’s desirable to revisit the subject.
I agree, that for lightweight C++ containers, we should definitely inline their implementations, but for more complicated ones like std::set or std::map we are probably still better off by not inlining them.

I’ve created the CPP-5072 to track the progress on this subject.

1 Like