Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is performing arithmetic on a null pointer undefined behavior?

Tags:

It looks to me like the following program computes an invalid pointer, since NULL is no good for anything but assignment and comparison for equality:

#include <stdlib.h>
#include <stdio.h>

int main() {

  char *c = NULL;
  c--;

  printf("c: %p\n", c);

  return 0;
}

However, it seems like none of the warnings or instrumentations in GCC or Clang targeted at undefined behavior say that this is in fact UB. Is that arithmetic actually valid and I'm being too pedantic, or is this a deficiency in their checking mechanisms that I should report?

Tested:

$ clang-3.3 -Weverything -g -O0 -fsanitize=undefined -fsanitize=null -fsanitize=address offsetnull.c -o offsetnull
$ ./offsetnull
c: 0xffffffffffffffff

$ gcc-4.8 -g -O0 -fsanitize=address offsetnull.c -o offsetnull
$ ./offsetnull 
c: 0xffffffffffffffff

It seems to be pretty well documented that AddressSanitizer as used by Clang and GCC is more focused on dereference of bad pointers, so that's fair enough. But the other checks don't catch it either :-/

Edit: part of the reason that I asked this question is that the -fsanitize flags enable dynamic checks of well-definedness in the generated code. Is this something they should have caught?

like image 526
Phil Miller Avatar asked Mar 25 '13 05:03

Phil Miller


People also ask

Is pointer arithmetic undefined behavior?

That's because pointers don't behave like integers. It's undefined behavior because the standard says so. On most platforms however (if not all), you won't get a crash or run into dubious behavior if you don't dereference the array.

Why arithmetic operation Cannot be perform on a void pointer?

Since void is an incomplete type, it is not an object type. Therefore it is not a valid operand to an addition operation. Therefore you cannot perform pointer arithmetic on a void pointer.

Why is dereferencing a null pointer undefined behavior?

Null dereferencing In C, dereferencing a null pointer is undefined behavior. Many implementations cause such code to result in the program being halted with an access violation, because the null pointer representation is chosen to be an address that is never allocated by the system for storing objects.

What happens when a pointer points to null?

Explanation: What happens here is that when a Null pointer is created, it points to null, without any doubt. But the variable of Null pointer takes some memory. Hence when a pointer to a null pointer is created, it points to an actual memory space, which in turn points to null.


2 Answers

Pointer arithmetic on a pointer not pointing to an array is Undefined behavior.
Also, Dereferencing a NULL pointer is undefined behavior.

char *c = NULL;
c--;

is Undefined defined behavior because c does not point to an array.

C++11 Standard 5.7.5:

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i + n-th and i − n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. 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.

like image 87
Alok Save Avatar answered Nov 02 '22 19:11

Alok Save


Yes, this is undefined behavior, and is something that -fsanitize=undefined should have caught; it's already on my TODO list to add a check for this.

FWIW, the C and C++ rules here are slightly different: adding 0 to a null pointer and subtracting one null pointer from another have undefined behavior in C but not in C++. All other arithmetic on null pointers has undefined behavior in both languages.

like image 38
Richard Smith Avatar answered Nov 02 '22 17:11

Richard Smith