aaron.ballman added a comment.

In D104285#2949273 <https://reviews.llvm.org/D104285#2949273>, @ASDenysPetrov 
wrote:

> @aaron.ballman
> Ok, I got your concerns.

Thanks for sticking with me!

> As I can see we shall only reason about objects within the bounds. Otherwise, 
> we shall return `UndefinedVal`.
> E.g.:
>
>   int arr[2][5];
>   int* ptr1= (int*)arr; // Valid indexing for `ptr` is in range [0,4].
>   int* ptr2 = &arr[0][0]; // Same as above.
>   ptr1[4]; // Valid object.
>   ptr2[5]; // Out of bound. UB. UndefinedVal.
>
> Would it be correct?

I believe so, yes (with a caveat below). I also believe this holds (reversing 
the pointer bases):

  ptr2[4]; // valid object
  ptr1[5]; // out of bounds

I've been staring at the C standard for a while, and I think the situation is 
also UB in C. As with C++, the array subscript operators are rewritten to be 
pointer arithmetic using addition (6.5.2.1p2). Additive operators says 
(6.5.6p9) in part: `... If both the pointer operand and the result point to 
elements of the same array object, or one past the last element of the array 
object, the evaluation shall not produce an overflow; otherwise the behavior is 
undefined. If the result points to one past the last element of the array 
object, it shall not be used as the operand of a unary * operator that is 
evaluated.` I believe we run afoul of "the same array object" and "one past the 
last element" clauses because multidimensional arrays are defined to be arrays 
of arrays (6.7.6.2).

Complicating matters somewhat, I would also say that your use of `[5]` is not 
technically out of bounds, but is a one-past-the-end that's then dereferenced 
as part of the subscript rewriting. So it's technically fine to form the 
pointer to the one-past-the-end element, but it's not okay to dereference it. 
That matters for things like:

  int arr[2][5] = {0};
  const int* ptr2 = &arr[0][0];
  const int* end = ptr2 + 5;
  
  for (; ptr2 < end; ++ptr2) {
    int whatever = *ptr2;
  }

where `end` is fine because it's never dereferenced. This distinction may 
matter to the static analyzer because a one-past-the-end pointer is valid for 
performing arithmetic on, but an out-of-bounds pointer is not.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104285/new/

https://reviews.llvm.org/D104285

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to