Vanishing warning
6/Aug 2018
Yet another MSVC story. Visual Studio has a nice compile-time warning when trying to access a static array with invalid index - C4789. According to documentation it’s mostly meant for various ‘copy’ functions (memcpy/strcpy etc), but it seems to work on ‘simple’ accesses as well. Consider (here’s a Godbolt link):
struct Tab
{
float tab[2];
};
void Foo(const Tab&);
void Bar(float forward)
{
Tab tab;
tab.tab[0] = forward;
tab.tab[2] = forward; // OOB access!
Foo(tab);
}
Compile this one without any optimizations and we get:
warning C4789: buffer 'tab' of size 8 bytes will be overrun; 4 bytes will be written starting at offset 8
.
Nice! (obviously code is simplified a bit and very wrong, but it’s mostly to demonstrate).
However, we now build our Release build, add an /Ox compilation option and… the code compiles silently, warning is gone.
1movss DWORD PTR tab$[rsp], xmm0
2movss DWORD PTR tab$[rsp+8], xmm0
3call void Foo(Tab const & __ptr64)
If you analyze how compiler manages the stack, it’s actually ‘harmless’ as we seem to dedicated more memory than
necessary for tab
(16 bytes).
tab$ = 32
__$ArrayPad$ = 48
Let’s see what happens if you access an index that way out of range (so that we’d actually be outside even the generously ‘allocated’ space):
tab.tab[4] = forward; // OOB access!
Compile with /Ox and… not only the warning is not there, the invalid access is actually silently eliminated!
1; tab[0] only, where's my (badly broken) tab[4]?
2movss DWORD PTR tab$[rsp], xmm0
3call void Foo(Tab const & __ptr64)
You could argue it’s not the worst thing, since it’s very unlikely we do want to write to index 4, but I’m not sure I can fully endorse it here ;)
If you’d like to follow this bug I filed a report here