Guys, I have a question about the following example from "19 Deadly Sins of Software Security". This is the only example I'm having trouble with, I just want to make sure I fully understand.
Quoted from page 7 of the book;
The following overrun is a little more interesting:
bool CopyStructs(InputFile* pInFile, unsigned long count)
{
unsigned long i;
m_pStructs = new Structs[count];
for(i = 0; i < count; i++)
{
if(!ReadFromFile(pInFile, &(m_pStructs[i])))
break;
}
}
How can this fail? Consider that when you call the C++ new[] operator, it is similar to the following code:
ptr = malloc(sizeof(type) * count);
If the user supplies the count, it isn't hard to specify a value that overflows the multiplication operation internally. You'll then allocate a buffer much smaller than you need, and the attacker is able to write over your buffer. The upcoming C++ compiler in Microsoft Visual Studio 2005 contains an internal check to prevent this problem.
Is it because the
count value that will be used to calculate the buffer's size can be too long? Will the size of the actual buffer will be truncated to something smaller while
count remains the same?
So I wrote something to test a few theories.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
const unsigned long COUNT = 18446744073709551615; // Biggest possible unsigned long on my system.
char* buf = new char[COUNT];
printf("Count: %u\n", COUNT);
printf("Strlen: %i\n", strlen(buf));
unsigned long i;
for(i = 0; i < COUNT; i++)
{
buf[i] = 'A';
}
}
Debugging this gives me the following error;
"error C2148: total size of array must not exceed 0x7fffffff". The hex value of
0x7fffffffequals
2147483647 in decimal, which is the biggest possible value of a signed int.
When I change the
count from
18446744073709551615 to
99999999999999999 I get the following output;
Count: 1569325055Strlen: 1569325059
What, no errors? So obviously the new operator doesn't like to get unsigned long values

And does indeed create a smaller buffer, but ALSO adjust the value of
count, so that overflows don't occur in the for loop. Even when
count was declared as constant. Is this because of the internal check the compiler performed? Will it just throw the
C2148 error? Is this what the author was talking about?
Maybe I'm making things too complicated for myself
Edit: Ugh, so I found out the Visual C++ compiler treats unsigned longs as 4 bytes. So they're like unsigned ints. I can imagine the risk when you think you're dealing with 8 bytes instead of 4.ZF