Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does integer promotion in pointer arithmetic behave differently in 64bit code than it does in 32bit code?

When compiled for 64bit the following code crashes with an access violation when accessing ptr[1-offset]:

char* ptr = new char[4];
strcpy(ptr, "bar");
unsigned int offset = 2;
ptr+=offset;

char test0 = (ptr-offset)[2];
char test1 = ptr[2-offset];
char test2 = (ptr-offset)[1];
char test3 = ptr[1-offset];

delete (ptr-offset);

The code executes just fine when compiled for 32bit.

When I replace ptr[1-offset] by ptr[(int)(1-offset)] or alternatively when I change unsigned int offset = 2; into int offset = 2; the code executes just fine for 64bit, too.

Apparently on 64bit the result of 1-offset gets promoted to an unsigned integer type, so that ptr[1-offset] does not resolve to ptr[-1], but to ptr[maxValueOfSomeUnsignedIntegerType].

However, why does this only happen for 64bit, while 1-offset appears to get promoted to a signed integer type for 32bit?

This seems not to be implementation specific - I get the same results with VC++ and with G++.

like image 718
Kaiserludi Avatar asked Oct 24 '25 13:10

Kaiserludi


1 Answers

First of all, the result of 1-offset is always UINT_MAX, independent of your architecture. This alone does not explain the difference.

If you cast that to int, you get an implementation defined result, but that usually is -1. Same thing with int offset, you just get normal signed integer arithmetic that results in -1. So that works.

Now for why the segfault: Apparently, on the systems you tried, overflowing arithmetic on pointers wraps mod 2^32. As far as I know this is UB, but it seems to work on your systems. So you effectively end up with ptr[1].

On the other hand, if the pointer is 64 bits wide, it can represent ptr + 2^32 - 1 (at least in this case apparently), so no wrapping happens and the pointer points to some nonsense location about 4GB after what you allocated.

like image 167
Baum mit Augen Avatar answered Oct 27 '25 04:10

Baum mit Augen