Skip to content

Instantly share code, notes, and snippets.

@Erkaman
Last active August 5, 2019 08:22
Show Gist options
  • Save Erkaman/9b8376000eee75761bbaa270b897cf7f to your computer and use it in GitHub Desktop.
Save Erkaman/9b8376000eee75761bbaa270b897cf7f to your computer and use it in GitHub Desktop.
shows how to save a payload into a NaN value.
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
int main()
{
{
float f = sqrtf(-1); // this results in f being set to nan.
// get the bitpattern of f, so we can print it.
uint32_t bitpattern;
memcpy(&bitpattern, &f, sizeof(f));
// prints "isnan = 1, bits = 0xffc00000"
printf("isnan = %d, bits = 0x%x\n", isnan(f), bitpattern);
/*
It appears that a NaN value, is in floating point numbers defined as
value where all the exponent bits are set to 1.
so for single precision floating point, it has this format:
s111 1111 1txx xxxx xxxx xxxx xxxx xxxx
so 's' is the sign bit, and can be arbitrary, and after this
's' bit, are the exponent bits, which are all set to one.
Then after the exponent bits, is a bit which specifies the type
of the NaN value. t==1 means its a "quiet NaN", and t==0 means its a
"signalling NaN".
The bits after t, can have any values, and we can store any
arbitrary payload in these bits.
*/
}
/*
Below, we demonstrate how to put a hexadecimal string "BEEF", as a payload
into a NaN-value. And if we run the below code, we can see that
even if we insert this payload, it is still considered as a NaN value.
Because as long as all the exponent bits are all 1, its still
considered a NaN value.
So we could put any 22-bit payload into this NaN value.
*/
{
// specify the bitpattern of some float:
uint32_t bitpattern = 0xffc0beef;
// convert bit pattern into float.
float f;
memcpy(&f, &bitpattern, sizeof(f));
// prints "isnan = 1, bits = 0xffc0beef"
// so still a nan!
printf("isnan = %d, bits = 0x%x\n", isnan(f), bitpattern);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment