US-CERT Vulnerability Note VU#162289

Robert C. Seacord rcs@cert.org
Thu Apr 10 13:26:00 GMT 2008


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
>   



More information about the Gcc mailing list