Last active
August 29, 2015 14:08
-
-
Save mraleph/2df42b26b655f1c61f00 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <stdint.h> | |
struct value_t { | |
union { | |
float fx[2]; | |
int32_t ix[2]; | |
}; | |
value_t& read(const int32_t* v) { | |
ix[0] = v[0]; | |
ix[1] = v[1]; | |
return *this; | |
} | |
}; | |
value_t __attribute__((noinline)) load(const int32_t* v) { | |
return value_t().read(v); | |
} | |
int main() { | |
const int32_t value = 0xffb15062; | |
const int32_t values[] = { value, value }; | |
value_t res = load(&values[0]); | |
if (res.ix[0] != res.ix[1]) { | |
printf("(╯°□°)╯︵ ┻━┻\n"); | |
return -1; | |
} | |
return 0; | |
} | |
/** | |
* | |
* $ g++ --version | |
* g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2 | |
* $ g++ -O2 -m32 -o test test.cc && ./test | |
* (╯°□°)╯︵ ┻━┻ | |
* $ | |
* How did this happen? Well it turns out that GCC decides to copy value_t in a | |
* very funky way: partially through general purpose registers, partially | |
* through the FPU stack | |
* | |
* flds 4(%edx) | |
* movl (%edx), %edx | |
* fstps 4(%eax) | |
* movl %edx, (%eax) | |
* | |
* Of course it does not end well for 0xffb15062 which, when interpreted as | |
* floating point value is actually a signalling NaN - so it turns into a qNaN | |
* 0xfff15062 with a single bit flip. | |
* | |
* GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58416 | |
* | |
**/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment