From 5fe327663f731337022ef0528ec12a9bc25d8392 Mon Sep 17 00:00:00 2001 From: Nicolas Hake Date: Mon, 8 Feb 2016 02:39:54 +0100 Subject: [PATCH] Fix signed int overflow in BltAlpha (#1661) The red color channel calculation could overflow into the sign bit, which is undefined behavior. At least one compiler takes advantage of this and assumes it cannot happen, resulting in incorrect results. BltAlphaAdd looks similar, but does in fact not have this bug because it shifts the color channel far enough that multiplication can't overflow. --- src/lib/StdColors.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/StdColors.h b/src/lib/StdColors.h index c5df14309..e70bc2e82 100644 --- a/src/lib/StdColors.h +++ b/src/lib/StdColors.h @@ -35,9 +35,9 @@ inline void BltAlpha(DWORD &dwDst, DWORD dwSrc) // blit one color value w/alpha on another if (dwDst>>24 == 0x00) { dwDst=dwSrc; return; } BYTE byAlphaSrc=BYTE(dwSrc>>24); BYTE byAlphaDst=255-byAlphaSrc; - dwDst = std::min((int(dwDst & 0xff ) * byAlphaDst + int(dwSrc & 0xff ) * byAlphaSrc) >>8, 0xff) | // blue - std::min((int(dwDst & 0xff00) * byAlphaDst + int(dwSrc & 0xff00 ) * byAlphaSrc) >>8 & 0xff00, 0xff00) | // green - std::min((int(dwDst & 0xff0000) * byAlphaDst + int(dwSrc & 0xff0000) * byAlphaSrc) >>8 & 0xff0000, 0xff0000) | // red + dwDst = std::min(((dwDst & 0xff ) * byAlphaDst + (dwSrc & 0xff ) * byAlphaSrc) >>8, 0xff) | // blue + std::min(((dwDst & 0xff00) * byAlphaDst + (dwSrc & 0xff00 ) * byAlphaSrc) >>8 & 0xff00, 0xff00) | // green + std::min(((dwDst & 0xff0000) * byAlphaDst + (dwSrc & 0xff0000) * byAlphaSrc) >>8 & 0xff0000, 0xff0000) | // red std::min( (dwDst >> 24) + byAlphaSrc, 255) << 24; // alpha }