Commit 36b884e6 by Alexis Hetu Committed by Commit Bot

Fix undefined behavior in minifloat conversion

This cl applies the same fix already applied in SwiftShader here: https://swiftshader-review.googlesource.com/c/SwiftShader/+/48069 Original description: Shifting a 32-bit value by 32 or more is undefined behavior in C++. This previously happened in this code when converting a 32-bit float value to an 11- or 10-bit minifloat which is too small to be represented as a denormal, and should produce 0 instead. Instead of going through this arithmetic for denormals, just test whether the input value is too small to produce a valid denormal, and return 0 instead. Bug: chromium:1117433 Change-Id: I227c0e4c53000df6d9260fee364351a300b113a2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2391764Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Alexis Hétu <sugoi@chromium.org>
parent b6b9cffa
......@@ -248,8 +248,9 @@ inline unsigned short float32ToFloat11(float fp32)
const unsigned short float11BitMask = 0x7FF;
const unsigned int float11ExponentBias = 14;
const unsigned int float32Maxfloat11 = 0x477E0000;
const unsigned int float32Minfloat11 = 0x38800000;
const unsigned int float32Maxfloat11 = 0x477E0000;
const unsigned int float32MinNormfloat11 = 0x38800000;
const unsigned int float32MinDenormfloat11 = 0x35000080;
const unsigned int float32Bits = bitCast<unsigned int>(fp32);
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
......@@ -285,9 +286,14 @@ inline unsigned short float32ToFloat11(float fp32)
// The number is too large to be represented as a float11, set to max
return float11Max;
}
else if (float32Val < float32MinDenormfloat11)
{
// The number is too small to be represented as a denormalized float11, set to 0
return 0;
}
else
{
if (float32Val < float32Minfloat11)
if (float32Val < float32MinNormfloat11)
{
// The number is too small to be represented as a normalized float11
// Convert it to a denormalized value.
......@@ -321,8 +327,9 @@ inline unsigned short float32ToFloat10(float fp32)
const unsigned short float10BitMask = 0x3FF;
const unsigned int float10ExponentBias = 14;
const unsigned int float32Maxfloat10 = 0x477C0000;
const unsigned int float32Minfloat10 = 0x38800000;
const unsigned int float32Maxfloat10 = 0x477C0000;
const unsigned int float32MinNormfloat10 = 0x38800000;
const unsigned int float32MinDenormfloat10 = 0x35800040;
const unsigned int float32Bits = bitCast<unsigned int>(fp32);
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
......@@ -340,7 +347,7 @@ inline unsigned short float32ToFloat10(float fp32)
}
else if (float32Sign)
{
// -INF is clamped to 0 since float11 is positive only
// -INF is clamped to 0 since float10 is positive only
return 0;
}
else
......@@ -355,14 +362,19 @@ inline unsigned short float32ToFloat10(float fp32)
}
else if (float32Val > float32Maxfloat10)
{
// The number is too large to be represented as a float11, set to max
// The number is too large to be represented as a float10, set to max
return float10Max;
}
else if (float32Val < float32MinDenormfloat10)
{
// The number is too small to be represented as a denormalized float10, set to 0
return 0;
}
else
{
if (float32Val < float32Minfloat10)
if (float32Val < float32MinNormfloat10)
{
// The number is too small to be represented as a normalized float11
// The number is too small to be represented as a normalized float10
// Convert it to a denormalized value.
const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
(float32Val >> float32ExponentFirstBit);
......@@ -371,7 +383,7 @@ inline unsigned short float32ToFloat10(float fp32)
}
else
{
// Rebias the exponent to represent the value as a normalized float11
// Rebias the exponent to represent the value as a normalized float10
float32Val += 0xC8000000;
}
......@@ -417,10 +429,10 @@ inline float float11ToFloat32(unsigned short fp11)
}
}
inline float float10ToFloat32(unsigned short fp11)
inline float float10ToFloat32(unsigned short fp10)
{
unsigned short exponent = (fp11 >> 5) & 0x1F;
unsigned short mantissa = fp11 & 0x1F;
unsigned short exponent = (fp10 >> 5) & 0x1F;
unsigned short mantissa = fp10 & 0x1F;
if (exponent == 0x1F)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment