Skip to content

Commit e6f4d1c

Browse files
committed
Fix HalfToFloat() and FloatToHalf() dereferencing issues with an union
1 parent 139de05 commit e6f4d1c

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

src/rtextures.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5384,19 +5384,27 @@ int GetPixelDataSize(int width, int height, int format)
53845384
//----------------------------------------------------------------------------------
53855385
// Module specific Functions Definition
53865386
//----------------------------------------------------------------------------------
5387+
union floatUnsignedUnion {
5388+
float fm;
5389+
unsigned int ui;
5390+
};
5391+
53875392
// Convert half-float (stored as unsigned short) to float
53885393
// REF: https://stackoverflow.com/questions/1659440/32-bit-to-16-bit-floating-point-conversion/60047308#60047308
53895394
static float HalfToFloat(unsigned short x)
53905395
{
53915396
float result = 0.0f;
53925397

5398+
union floatUnsignedUnion uni;
5399+
uni.fm = 0.0f;
5400+
53935401
const unsigned int e = (x & 0x7C00) >> 10; // Exponent
53945402
const unsigned int m = (x & 0x03FF) << 13; // Mantissa
5395-
const float fm = (float)m;
5396-
const unsigned int v = (*(unsigned int *)&fm) >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
5397-
const unsigned int r = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized
5403+
uni.fm = (float)m;
5404+
const unsigned int v = uni.ui >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
5405+
uni.ui = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized
53985406

5399-
result = *(float *)&r;
5407+
result = uni.fm;
54005408

54015409
return result;
54025410
}
@@ -5406,7 +5414,10 @@ static unsigned short FloatToHalf(float x)
54065414
{
54075415
unsigned short result = 0;
54085416

5409-
const unsigned int b = (*(unsigned int *) & x) + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
5417+
union floatUnsignedUnion uni;
5418+
uni.fm = x;
5419+
5420+
const unsigned int b = uni.ui + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
54105421
const unsigned int e = (b & 0x7F800000) >> 23; // Exponent
54115422
const unsigned int m = b & 0x007FFFFF; // Mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
54125423

0 commit comments

Comments
 (0)