gsk, testsuite: Avoid undefined behaviour in half_to_float_one()

Similar to the previous commit, to avoid undefined behaviour we need
to avoid evaluating out-of-bounds shifts, even if their result is going
to ignored by being multiplied by 0 later.

Detected by running a subset of the test suite with
-Dsanitize=address,undefined on x86_64.

Signed-off-by: Simon McVittie <smcv@debian.org>
This commit is contained in:
Simon McVittie 2024-07-27 20:15:50 +01:00
parent ad679187d3
commit 660c6c8d6f
4 changed files with 31 additions and 69 deletions

View File

@ -22,29 +22,6 @@
#include "fp16private.h"
static inline guint
as_uint (const float x)
{
return *(guint*)&x;
}
static inline float
as_float (const guint x)
{
return *(float*)&x;
}
// IEEE-754 16-bit floating-point format (without infinity): 1-5-10
static inline float
half_to_float_one (const guint16 x)
{
const guint e = (x&0x7C00)>>10; // exponent
const guint m = (x&0x03FF)<<13; // mantissa
const guint v = as_uint((float)m)>>23;
return as_float((x&0x8000)<<16 | (e!=0)*((e+112)<<23|m) | ((e==0)&(m!=0))*((v-37)<<23|((m<<(150-v))&0x007FE000)));
}
void
float_to_half4_c (const float f[4],
guint16 h[4])

View File

@ -28,6 +28,37 @@ G_BEGIN_DECLS
#define FP16_ONE ((guint16)15360)
#define FP16_MINUS_ONE ((guint16)48128)
static inline guint
as_uint (const float x)
{
return *(guint*)&x;
}
static inline float
as_float (const guint x)
{
return *(float*)&x;
}
// IEEE-754 16-bit floating-point format (without infinity): 1-5-10
static inline float
half_to_float_one (const guint16 x)
{
const guint e = (x & 0x7C00) >> 10; // exponent
const guint m = (x & 0x03FF) << 13; // mantissa
const guint v = as_uint ((float) m) >> 23;
guint normalized = 0;
guint denormalized = 0;
if (e != 0)
normalized = (e + 112) << 23 | m;
if (e == 0 && m != 0)
denormalized = (v - 37) << 23 | ((m << (150 - v)) & 0x007FE000);
return as_float ((x & 0x8000u) << 16 | normalized | denormalized);
}
static inline guint16
float_to_half_one (const float x)
{

View File

@ -46,29 +46,6 @@ struct _TextureBuilder
gsize offset;
};
static inline guint
as_uint (const float x)
{
return *(guint*)&x;
}
static inline float
as_float (const guint x)
{
return *(float*)&x;
}
// IEEE-754 16-bit floating-point format (without infinity): 1-5-10
//
static inline float
half_to_float_one (const guint16 x)
{
const guint e = (x&0x7C00)>>10; // exponent
const guint m = (x&0x03FF)<<13; // mantissa
const guint v = as_uint((float)m)>>23;
return as_float((x&0x8000)<<16 | (e!=0)*((e+112)<<23|m) | ((e==0)&(m!=0))*((v-37)<<23|((m<<(150-v))&0x007FE000)));
}
static gsize
gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
{

View File

@ -50,29 +50,6 @@ struct _TextureBuilder
gsize offset;
};
static inline guint
as_uint (const float x)
{
return *(guint*)&x;
}
static inline float
as_float (const guint x)
{
return *(float*)&x;
}
// IEEE-754 16-bit floating-point format (without infinity): 1-5-10
//
static inline float
half_to_float_one (const guint16 x)
{
const guint e = (x&0x7C00)>>10; // exponent
const guint m = (x&0x03FF)<<13; // mantissa
const guint v = as_uint((float)m)>>23;
return as_float((x&0x8000)<<16 | (e!=0)*((e+112)<<23|m) | ((e==0)&(m!=0))*((v-37)<<23|((m<<(150-v))&0x007FE000)));
}
static gsize
gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
{