Spectre diagnostic in Visual Studio 2017 Version 15.7 Preview 4

Visual Studio 2017 version 15.7 Preview 4 adds a new capability to our Spectre mitigation: the ability to see where the compiler would have inserted a mitigation and what data led to that action. A new warning, C5045, lets you see what patterns in your code would have caused a mitigation, such as an LFENCE, to be inserted.

This change builds upon our existing Spectre mitigation support, including the changes introduced in Preview 3. Complete details about are available in context in the original MSVC Spectre mitigation post on VCBlog. The new warning is also discussed below.

Enabling C5045

The C5045 warning is off by default. You can enable it in one of two ways:

  1. Set the warning level to EnableAllWarnings in Project Properties > C/C++ > General > Warning Level. This option enables all warnings so it can be a bit noisy. Even the VC++ libraries don’t attempt to be clean for all warnings (/Wall).
  2. Set the warning level of C5045 to a level specified in the “Warning Level” setting. The default level for C++ projects is /W3, so you can set the warning level of C5045 to level 3. To do this, put /w35045 on the command line: it says to treat warning number 5045 as level 3. You can do this in the text box in Project Properties > C/C++ > Command Line > Additional Options.

Using C5045

Once you’ve enabled the warning, just compile your code to see where mitigations would be inserted. This code sample contains one vulnerability:

int G, G1, G2;

__forceinline
int * bar(int **p, int i)
{
	return p[i];
}

__forceinline
void bar1(int ** p, int i)
{
	if (i < G1) {
		auto x = p[i]; // mitigation here
		G = *x;
	}
}

__forceinline
void foo(int * p)
{
	G = *p;
}
 
void baz(int ** p, int i)
{
	if (i < G1) {
		foo(bar(p, i + G2));
	}
	bar1(p, i);
}

int main() { }

Compiling the code above shows that a mitigation would have been inserted on line 13. It also notes that the mitigation is needed because the index i on line 12 feeds the memory load on line 14. The speculation is done across bar and bar1 but the mitigation is effective when placed at line 12.

1>------ Rebuild All started: Project: Spectre, Configuration: Debug Win32 ------ 
1>Source.cpp 
1>c:\users\apardoe\source\repos\spectre\spectre\source.cpp(13): warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified 
1>c:\users\apardoe\source\repos\spectre\spectre\source.cpp(12) : note: index 'i' range checked by comparison on this line 
1>c:\users\apardoe\source\repos\spectre\spectre\source.cpp(14) : note: feeds memory load on this line 
1>Spectre.vcxproj -> c:\Users\apardoe\source\repos\Spectre\Debug\Spectre.exe 
1>Done building project "Spectre.vcxproj". 
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ========== 

Note that this warning is purely informational: the mitigation is not inserted until you recompile using the /Qspectre switch. The functionality of C5045 is independent of the /Qspectre switch so you can use them both in the same compilation.

In closing

We on the MSVC team are committed to the continuous improvement and security of your Windows software. We’ll continue to develop technologies that help developers mitigate speculative execution side channel vulnerabilities and other security issues.

We encourage you to recompile and redeploy your vulnerable software as soon as possible. Continue watching this blog and the @visualc Twitter feed for updates on this topic.

If you have any questions, please feel free to ask us below. You can also send us your comments through e-mail at visualcpp@microsoft.com, through Twitter @visualc, or Facebook at Microsoft Visual Cpp. Thank you.