Commit 630d85cb by Corentin Wallez

Fix an undefined behavior in clampCast

This undefined behavior appeared in angle_end2end_tests compiled with clang 3.6 on Mac. BUG=angleproject:891 Change-Id: I840b40a7bd54c9cfaeb0fe6784b73f875f9d5502 Reviewed-on: https://chromium-review.googlesource.com/303337Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Tested-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 7aa4cae2
...@@ -69,14 +69,29 @@ inline int clampToInt(unsigned int x) ...@@ -69,14 +69,29 @@ inline int clampToInt(unsigned int x)
template <typename DestT, typename SrcT> template <typename DestT, typename SrcT>
inline DestT clampCast(SrcT value) inline DestT clampCast(SrcT value)
{ {
SrcT lo = static_cast<SrcT>(std::numeric_limits<DestT>::min()); static const DestT destLo = std::numeric_limits<DestT>::min();
SrcT hi = static_cast<SrcT>(std::numeric_limits<DestT>::max()); static const DestT destHi = std::numeric_limits<DestT>::max();
static const SrcT srcLo = static_cast<SrcT>(destLo);
// This assumes SrcT can properly represent DestT::min/max. Checking this is a bit tricky, static const SrcT srcHi = static_cast<SrcT>(destHi);
// especially given floating point representations.
ASSERT(lo < hi); // When value is outside of or equal to the limits for DestT we use the DestT limit directly.
// This avoids undefined behaviors due to loss of precision when converting from floats to
return static_cast<DestT>(value > lo ? (value > hi ? hi : value) : lo); // integers:
// destHi for ints is 2147483647 but the closest float number is around 2147483648, so when
// doing a conversion from float to int we run into an UB because the float is outside of the
// range representable by the int.
if (value <= srcLo)
{
return destLo;
}
else if (value >= srcHi)
{
return destHi;
}
else
{
return static_cast<DestT>(value);
}
} }
template<typename T, typename MIN, typename MAX> template<typename T, typename MIN, typename MAX>
......
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