From ca16fe55014c57090dd97369256c7657aeb25975 Mon Sep 17 00:00:00 2001 From: Hugo Lefeuvre Date: Sat, 22 Sep 2018 14:33:19 -0400 Subject: [PATCH] convertbmp: fix issues with zero bitmasks In the case where a BMP file declares compression 3 (BI_BITFIELDS) with header size <= 56, all bitmask values keep their initialization value 0. This may lead to various undefined behavior later e.g. when doing 1 << (l_comp->prec - 1). This issue does not affect files with bit count 16 because of a check added in 16240e2 which sets default values to the color masks if they are all 0. This commit adds similar checks for the 32 bit case. Also, if a BMP file declares compression 3 with header size >= 56 and intentional 0 bitmasks, the same issue will be triggered in both the 16 and 32 bit count case. This commit adds checks to bmp_read_info_header() rejecting BMP files with "intentional" 0 bitmasks. These checks might be removed in the future when proper handling of zero bitmasks will be available in openjpeg2. fixes #1057 (CVE-2018-5785) --- src/bin/jp2/convertbmp.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/bin/jp2/convertbmp.c b/src/bin/jp2/convertbmp.c index 084f70bb..7fde99ab 100644 --- a/src/bin/jp2/convertbmp.c +++ b/src/bin/jp2/convertbmp.c @@ -435,16 +435,31 @@ static OPJ_BOOL bmp_read_info_header(FILE* IN, OPJ_BITMAPINFOHEADER* header) header->biRedMask |= (OPJ_UINT32)getc(IN) << 16; header->biRedMask |= (OPJ_UINT32)getc(IN) << 24; + if (!header->biRedMask) { + fprintf(stderr, "Error, invalid red mask value %d\n", header->biRedMask); + return OPJ_FALSE; + } + header->biGreenMask = (OPJ_UINT32)getc(IN); header->biGreenMask |= (OPJ_UINT32)getc(IN) << 8; header->biGreenMask |= (OPJ_UINT32)getc(IN) << 16; header->biGreenMask |= (OPJ_UINT32)getc(IN) << 24; + if (!header->biGreenMask) { + fprintf(stderr, "Error, invalid green mask value %d\n", header->biGreenMask); + return OPJ_FALSE; + } + header->biBlueMask = (OPJ_UINT32)getc(IN); header->biBlueMask |= (OPJ_UINT32)getc(IN) << 8; header->biBlueMask |= (OPJ_UINT32)getc(IN) << 16; header->biBlueMask |= (OPJ_UINT32)getc(IN) << 24; + if (!header->biBlueMask) { + fprintf(stderr, "Error, invalid blue mask value %d\n", header->biBlueMask); + return OPJ_FALSE; + } + header->biAlphaMask = (OPJ_UINT32)getc(IN); header->biAlphaMask |= (OPJ_UINT32)getc(IN) << 8; header->biAlphaMask |= (OPJ_UINT32)getc(IN) << 16; @@ -831,6 +846,12 @@ opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters) bmpmask32toimage(pData, stride, image, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, 0x00000000U); } else if (Info_h.biBitCount == 32 && Info_h.biCompression == 3) { /* bitmask */ + if ((Info_h.biRedMask == 0U) && (Info_h.biGreenMask == 0U) && + (Info_h.biBlueMask == 0U)) { + Info_h.biRedMask = 0x00FF0000U; + Info_h.biGreenMask = 0x0000FF00U; + Info_h.biBlueMask = 0x000000FFU; + } bmpmask32toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask, Info_h.biBlueMask, Info_h.biAlphaMask); } else if (Info_h.biBitCount == 16 && Info_h.biCompression == 0) { /* RGBX */ -- 2.30.2