MSVC just released an update which has added a new warning about some code the compiler will inject to mitigate (apparently some small bit) of Spectre:
https://blogs.msdn.microsoft.com/vcblog/2018/01/15/spectre-mitigations-in-msvc/
Here's a little MCVE derived from their example of "problematic" code:
#include <stdio.h>
int main(int argc, char *argv) {
unsigned char array1[1] = {0};
int array1_length = 1;
unsigned char array2[1] = {99};
int untrusted_index = 0; /* in this MCVE, I trust it, compiler doesn't */
for (; untrusted_index < array1_length; ++untrusted_index) {
unsigned char value = array1[untrusted_index];
unsigned char value2 = array2[value * 64];
printf("Picked value %d\n", value2);
}
return 0;
}
"In the above example, the code performs an array-bounds check to ensure that untrusted_index is less than the length of array1. This is needed to ensure that the program does not read beyond the bounds of the array. While this appears to be sound as written, it does not take into account microarchitectural behaviors of the CPU involving speculative execution."
So you now get a warning:
Warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
Which is its way of telling you that this code could end up being slower than you might like it to be (if compiled /Qspectre), because it's going to put in some extra protections.
Since it doesn't seem you can take anything for granted, I'm suspicious of making changes that "just make the warning go away". For instance, changing untrusted_index < array1_length
to untrusted_index != array1_length
seems to do it, for the specific instance of the MCVE code I give here. But is that a viable patch, or is their warning just incomplete--and in the next update, it will complain about that too?
I know I can disable the warning, with /wd5040, or otherwise. But I'm interested in making sure that if the code is compiled with /Qspectre that there are not slowdowns, and that there are no warnings if it is not compiled with /Qspectre. I don't want to go around touching files changing <
to !=
in loop conditions--or whatever--if that's just churn.
So a bigger question would be if there are legitimate workaround patterns that are this basic, why aren't there some mentions of them? For instance the case I describe is an iteration where I control the index, and don't have to worry about it coming from an "untrusted source". Yet I got a warning, and switching from <
to !=
made it go away. Why? Should it have?