Because no truncation happens. In this case [] operator doesn't specify any type, only that the expression inside is an integer expression. While normally the type size_t is used for object and array sizes, [] takes any integer expression and the compiler won't complain.
uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
size + chunk_size is clearly unsafe to truncate to 32 bits, but it truncates anyway. When I say 'inside the new operator' I'm including the allocation function. Something truncates it. If it actually allocated 8GB, or failed to allocate 8GB, there would be no exploit.
Apparently new is a "special" operator, or there is a bug in the compiler. I also can't get a warning with g++.
The problem seems to be that, as I said, [] takes any integer expression, it is there where the value gets truncated when operator sizeof or new is applied on it since they either return or take a size_t value.