1

I found a negative index access in an embedded code I'm debugging:

for (int i = len; i > 0; i--)
{
  data[i - 1] = data[i - 2];  // negative access when i == 1
}

I read this about similar cases, but in the OP arr[-2] is guaranteed to be OK since arr points to the middle of a previously allocated array. In my case, data is a pointer inside a class that is initialized by the constructor with:

public:
  constructor_name(): ... data(new T_a[size]), ...

And the pointer data is the first member in the class:

template <class T_a, class T_b, int size>
class T_c
{
private:
  T_a            *data;
  T_b            *...;
  int             ...;
  int             ...;
  int             ...;

public:
  constructor_name(): ... data(new T_a[size]), ...

Now, is there a possibility that the negative index access was deliberate and was meaningful? Is there a way the programmer who wrote that was able to ensure that data[-1] will access a specific datum, using #pragma pack () or other any methods?

Seeing *data is the first member in the class made me think it was a bug, but I'm not sure. If it is indeed a bug - is it UB?

Azeem
  • 11,148
  • 4
  • 27
  • 40
CIsForCookies
  • 12,097
  • 11
  • 59
  • 124
  • 4
    It indeed is [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior) so you don't have any guarantee – Basile Starynkevitch Aug 03 '17 at 05:31
  • @BasileStarynkevitch if `data` was located elsewhere inside the class - would it have made any difference? – CIsForCookies Aug 03 '17 at 05:36
  • I don't think so. The C++ standard is quite strong about UB. – Basile Starynkevitch Aug 03 '17 at 05:37
  • Would it make any difference that that specific module is afterwards imported by a `C` module? (guessing not, but just want to make sure) – CIsForCookies Aug 03 '17 at 05:39
  • 1
    @ Basile Starynkevitch Let be clear, it's not UB to use negative index, it is UB to access data outside of created object. Obvious answer: to guarantee this is to ensure that public pointer to array would point to the element in middle of array – Swift - Friday Pie Aug 03 '17 at 05:39
  • @ClsForCookies: what kind of embedded code is it (consumer product like a connected brush, or life-threatening one like an implantable medical prosthesis)? What size? What industry? What kind of coding standards & regulations (e.g. [DOI-178C](https://en.wikipedia.org/wiki/DO-178C))? Please **edit your question** to improve and motivate it – Basile Starynkevitch Aug 03 '17 at 05:59
  • @BasileStarynkevitch its an enlarged communication switch. Not sure what you mean by size (the binary is about 35 MB...). Also not sure about standards & regulations – CIsForCookies Aug 03 '17 at 06:02
  • That should go into your answer. Are failures very important to avoid? In today's world, telephone switches are life threatening – Basile Starynkevitch Aug 03 '17 at 06:03
  • Not realy. This bug is about failures statistics - not the failures themselves. Could you kindly explain why the things you mentioned are relevant? – CIsForCookies Aug 03 '17 at 06:04
  • This looks a lot like code that used to read `data[i] = data[i - 1];` and then "corrected". – molbdnilo Aug 03 '17 at 07:25
  • I'm not sure, since it starts from `int i = len` and data[i] exceeds the array boundaries. I think it's a mistake still, but an original mistake :) – CIsForCookies Aug 03 '17 at 07:26
  • @CIsForCookies Exactly. I suspect the original programmer noticed that, but didn't fix it correctly. – molbdnilo Aug 03 '17 at 08:09

2 Answers2

3

You are asking about guarantee (a quite strong word). And your code has undefined behavior (because you are accessing some data outside of your object) which really means you cannot have any guarantee. Arbitrarily bad things could happen, even if in practice they usually don't (in particular when data points to a scalar type, like pointers).

I would recommend to replace for (int i = len; i > 0; i--) with for (int i = len; i > 1; i--) at least to make the code more readable and more standard conforming.

If for some weird reason the data[-1] access was meaningful for the previous programmer he should at least have commented about that. I guess that if he did not, it simply is a bug.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

It depends on the embedded chip you are using.

First, the important part to notice is data lives in the heap. So normally (in a desktop computer) you cannot make any assumption about that data being just next to another piece of information you control.

But as we are talking about embedded systems here, some of them have a single contiguous memory space for stack and heap, and start filling the heap from one side of that memory space, and the stack from the other, until they meet at the center and the program crashes.

Anyway, in this case, the programmer of your code could have been so careful that he knows which is the next heap allocation that will happen, thus ensuring which variable lives next to data, but I actually think it is very unlikely. Nonetheless, he would be exploiting an undefined behaviour because it's a "memory access outside of array bounds" and I would consider it not only a bad programming practice but straight a bug.

Found a picture of how that heap/stack model works in a specific chip here.

Daniel
  • 21,933
  • 14
  • 72
  • 101