Skip to content

Commit 36b884e

Browse files
sugoi1Commit Bot
authored andcommitted
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/+/2391764 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Alexis Hétu <sugoi@chromium.org>
1 parent b6b9cff commit 36b884e

File tree

1 file changed

+25
-13
lines changed

1 file changed

+25
-13
lines changed

src/common/mathutil.h

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,9 @@ inline unsigned short float32ToFloat11(float fp32)
248248
const unsigned short float11BitMask = 0x7FF;
249249
const unsigned int float11ExponentBias = 14;
250250

251-
const unsigned int float32Maxfloat11 = 0x477E0000;
252-
const unsigned int float32Minfloat11 = 0x38800000;
251+
const unsigned int float32Maxfloat11 = 0x477E0000;
252+
const unsigned int float32MinNormfloat11 = 0x38800000;
253+
const unsigned int float32MinDenormfloat11 = 0x35000080;
253254

254255
const unsigned int float32Bits = bitCast<unsigned int>(fp32);
255256
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
@@ -285,9 +286,14 @@ inline unsigned short float32ToFloat11(float fp32)
285286
// The number is too large to be represented as a float11, set to max
286287
return float11Max;
287288
}
289+
else if (float32Val < float32MinDenormfloat11)
290+
{
291+
// The number is too small to be represented as a denormalized float11, set to 0
292+
return 0;
293+
}
288294
else
289295
{
290-
if (float32Val < float32Minfloat11)
296+
if (float32Val < float32MinNormfloat11)
291297
{
292298
// The number is too small to be represented as a normalized float11
293299
// Convert it to a denormalized value.
@@ -321,8 +327,9 @@ inline unsigned short float32ToFloat10(float fp32)
321327
const unsigned short float10BitMask = 0x3FF;
322328
const unsigned int float10ExponentBias = 14;
323329

324-
const unsigned int float32Maxfloat10 = 0x477C0000;
325-
const unsigned int float32Minfloat10 = 0x38800000;
330+
const unsigned int float32Maxfloat10 = 0x477C0000;
331+
const unsigned int float32MinNormfloat10 = 0x38800000;
332+
const unsigned int float32MinDenormfloat10 = 0x35800040;
326333

327334
const unsigned int float32Bits = bitCast<unsigned int>(fp32);
328335
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
@@ -340,7 +347,7 @@ inline unsigned short float32ToFloat10(float fp32)
340347
}
341348
else if (float32Sign)
342349
{
343-
// -INF is clamped to 0 since float11 is positive only
350+
// -INF is clamped to 0 since float10 is positive only
344351
return 0;
345352
}
346353
else
@@ -355,14 +362,19 @@ inline unsigned short float32ToFloat10(float fp32)
355362
}
356363
else if (float32Val > float32Maxfloat10)
357364
{
358-
// The number is too large to be represented as a float11, set to max
365+
// The number is too large to be represented as a float10, set to max
359366
return float10Max;
360367
}
368+
else if (float32Val < float32MinDenormfloat10)
369+
{
370+
// The number is too small to be represented as a denormalized float10, set to 0
371+
return 0;
372+
}
361373
else
362374
{
363-
if (float32Val < float32Minfloat10)
375+
if (float32Val < float32MinNormfloat10)
364376
{
365-
// The number is too small to be represented as a normalized float11
377+
// The number is too small to be represented as a normalized float10
366378
// Convert it to a denormalized value.
367379
const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
368380
(float32Val >> float32ExponentFirstBit);
@@ -371,7 +383,7 @@ inline unsigned short float32ToFloat10(float fp32)
371383
}
372384
else
373385
{
374-
// Rebias the exponent to represent the value as a normalized float11
386+
// Rebias the exponent to represent the value as a normalized float10
375387
float32Val += 0xC8000000;
376388
}
377389

@@ -417,10 +429,10 @@ inline float float11ToFloat32(unsigned short fp11)
417429
}
418430
}
419431

420-
inline float float10ToFloat32(unsigned short fp11)
432+
inline float float10ToFloat32(unsigned short fp10)
421433
{
422-
unsigned short exponent = (fp11 >> 5) & 0x1F;
423-
unsigned short mantissa = fp11 & 0x1F;
434+
unsigned short exponent = (fp10 >> 5) & 0x1F;
435+
unsigned short mantissa = fp10 & 0x1F;
424436

425437
if (exponent == 0x1F)
426438
{

0 commit comments

Comments
 (0)