"Fix" stack bounds check when compiled by Clang 4.0. Fix from Andrew
Morrow, analysis by Florian Krohm.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12947 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index 1330c2a..0e83d36 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -1618,12 +1618,24 @@
VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
{ HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
HChar* limHi = limLo + sizeof(VG_(interim_stack));
- HChar* aLocal = (HChar*)&limLo; /* any auto local will do */
- /* "Apple clang version 4.0 (tags/Apple/clang-421.0.57) (based on
- LLVM 3.1svn)" appears to miscompile the following check,
- causing run to abort at this point (in 64-bit mode) even
- though aLocal is within limLo .. limHi. Try building with
- gcc instead. */
+ HChar* volatile
+ aLocal = (HChar*)&limLo; /* any auto local will do */
+ /* Re "volatile": Apple clang version 4.0
+ (tags/Apple/clang-421.0.57) (based on LLVM 3.1svn)" appeared
+ to miscompile the following check, causing run to abort at
+ this point (in 64-bit mode) even though aLocal is within limLo
+ .. limHi. But in fact clang is within its rights to do
+ strange things here. "The reason is that the comparisons
+ aLocal < limLo and aLocal >= limHi cause undefined behaviour
+ (according to c99 6.5.8) because they compare pointers that do
+ not point into the same aggregate." Adding "volatile" appears
+ to fix it because "The compiler would have to prove that there
+ is undefined behavior in order to exploit it. But as a
+ volatile variable can change its value in ways invisible to
+ the compiler, the compiler must make the conservative
+ assumption that it points into the same aggregate as the other
+ pointer its compared against. I.e. the behaviour is possibly
+ defined." (Analysis by Florian Krohm). */
if (aLocal < limLo || aLocal >= limHi) {
/* something's wrong. Stop. */
VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",