diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 2d5b4b24c..ac98b78e1 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -11,6 +11,8 @@ /// \file r_segs.c /// \brief All the clipping: columns, horizontal spans, sky columns +#include + #include #include "command.h" @@ -717,16 +719,45 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) R_SetColumnFunc(BASEDRAWFUNC, false); } +template +static constexpr T saturating_add(T x, T y) noexcept +{ + INT64 z; + z = static_cast(x) + static_cast(y); + if (z > static_cast(std::numeric_limits::max())) + { + z = static_cast(std::numeric_limits::max()); + } + else if (z < static_cast(std::numeric_limits::min())) + { + z = static_cast(std::numeric_limits::min()); + } + return static_cast(z); +} + +template +static constexpr T saturating_mul(T x, T y) noexcept +{ + INT64 z; + z = static_cast(x) * static_cast(y); + if (z > static_cast(std::numeric_limits::max())) + { + z = static_cast(std::numeric_limits::max()); + } + else if (z < static_cast(std::numeric_limits::min())) + { + z = static_cast(std::numeric_limits::min()); + } + return static_cast(z); +} + // Loop through R_DrawMaskedColumn calls static void R_DrawRepeatMaskedColumn(drawcolumndata_t* dc, column_t *col, column_t *bm, INT32 baseclip) { while (sprtopscreen < sprbotscreen) { R_DrawMaskedColumn(dc, col, bm, baseclip); - if ((INT64)sprtopscreen + dc->texheight*spryscale > (INT64)INT32_MAX) // prevent overflow - sprtopscreen = INT32_MAX; - else - sprtopscreen += dc->texheight*spryscale; + sprtopscreen = saturating_add(sprtopscreen, saturating_mul(dc->texheight, spryscale)); } } @@ -734,7 +765,7 @@ static void R_DrawRepeatFlippedMaskedColumn(drawcolumndata_t* dc, column_t *col, { do { R_DrawFlippedMaskedColumn(dc, col, bm, baseclip); - sprtopscreen += dc->texheight*spryscale; + sprtopscreen = saturating_add(sprtopscreen, saturating_mul(dc->texheight, spryscale)); } while (sprtopscreen < sprbotscreen); }