Gerald,
Here is another version of the program (same compiler version/flags).
#include <stdio.h>
void test_signed(char *buf) {
signed int len;
len = 1<<30;
printf("buf = %p; buf+len = %p; buf+len < buf = %d %d",
buf, buf+len, buf+len < buf, (uintptr_t)buf+len < (uintptr_t)buf);
if((buf+len < buf) != ((uintptr_t)buf+len < (uintptr_t)buf))
printf(" BUG!");
printf("\n");
}
void test_unsigned(char *buf) {
unsigned int len;
len = 1<<30;
printf("buf = %p; buf+len = %p; buf+len < buf = %d %d",
buf, buf+len, buf+len < buf, (uintptr_t)buf+len < (uintptr_t)buf);
if((buf+len < buf) != ((uintptr_t)buf+len < (uintptr_t)buf))
printf(" BUG!");
printf("\n");
}
int main(void) {
test_signed(0);
test_signed((char*)0x70000000);
test_signed((char*)0xf0000000);
test_unsigned(0);
test_unsigned((char*)0x70000000);
test_unsigned((char*)0xf0000000);
return 0;
}
output:
buf = 00000000; buf+len = 40000000; buf+len < buf = 0 0
buf = 70000000; buf+len = B0000000; buf+len < buf = 0 0
buf = F0000000; buf+len = 30000000; buf+len < buf = 1 1
buf = 00000000; buf+len = 40000000; buf+len < buf = 0 0
buf = 70000000; buf+len = B0000000; buf+len < buf = 0 0
buf = F0000000; buf+len = 30000000; buf+len < buf = 1 1
The unsigned test was one we performed on the gcc versions. I added the
signed test, but it didn't make a difference on Visual Studio. My
understanding is that it shouldn't, because the real issue here is
pointer arithmetic and the resulting type should always be a pointer.
rCs
Robert C. Seacord wrote:
void f(char *buf) {
unsigned int len = len = 0xFFFFFF00;
if (buf+len < buf) puts("true");
}
You need to be more precise. That is not the same example
that you quoted for GCC.
In fact, if you vary the criteria too much, you will find
situations where GCC already behaved that way. The test in
the following example is optimized out by old versions of
GCC (certainly my version 3.4.5 compiler does it, with no
warnings even when using -Wall):
int f(char *buf, int i)
{
i = 1<<30;
if ((int)buf + i < (int)buf)
return 0;
return 1;
}
That's quite a bit less changed than your example, which
brings unsigned-ness into the picture. [This is exactly
the problem--signed overflow and pointer overflow aren't
defined, unlike unsigned overflow.]
Given that current Microsoft compilers reportedly exhibit
this behavior, it sounds like the advisory is going to at
least need some significant rewriting. :-)
-Jerry