convertbmp: detect invalid file dimensions early

width/length dimensions read from bmp headers are not necessarily
valid. For instance they may have been maliciously set to very large
values with the intention to cause DoS (large memory allocation, stack
overflow). In these cases we want to detect the invalid size as early
as possible.

This commit introduces a counter which verifies that the number of
written bytes corresponds to the advertized width/length.

See commit 8ee335227b for details.

Signed-off-by: Young Xiao <YangX92@hotmail.com>
This commit is contained in:
Young Xiao 2019-03-16 19:57:27 +08:00 committed by Young Xiao
parent d0dd894ae2
commit 21399f6b7d
1 changed files with 8 additions and 2 deletions

View File

@ -622,13 +622,13 @@ static OPJ_BOOL bmp_read_rle8_data(FILE* IN, OPJ_UINT8* pData,
static OPJ_BOOL bmp_read_rle4_data(FILE* IN, OPJ_UINT8* pData, static OPJ_BOOL bmp_read_rle4_data(FILE* IN, OPJ_UINT8* pData,
OPJ_UINT32 stride, OPJ_UINT32 width, OPJ_UINT32 height) OPJ_UINT32 stride, OPJ_UINT32 width, OPJ_UINT32 height)
{ {
OPJ_UINT32 x, y; OPJ_UINT32 x, y, written;
OPJ_UINT8 *pix; OPJ_UINT8 *pix;
const OPJ_UINT8 *beyond; const OPJ_UINT8 *beyond;
beyond = pData + stride * height; beyond = pData + stride * height;
pix = pData; pix = pData;
x = y = 0U; x = y = written = 0U;
while (y < height) { while (y < height) {
int c = getc(IN); int c = getc(IN);
if (c == EOF) { if (c == EOF) {
@ -642,6 +642,7 @@ static OPJ_BOOL bmp_read_rle4_data(FILE* IN, OPJ_UINT8* pData,
for (j = 0; (j < c) && (x < width) && for (j = 0; (j < c) && (x < width) &&
((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) { ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
*pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU)); *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU));
written++;
} }
} else { /* absolute mode */ } else { /* absolute mode */
c = getc(IN); c = getc(IN);
@ -671,6 +672,7 @@ static OPJ_BOOL bmp_read_rle4_data(FILE* IN, OPJ_UINT8* pData,
c1 = (OPJ_UINT8)getc(IN); c1 = (OPJ_UINT8)getc(IN);
} }
*pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU)); *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU));
written++;
} }
if (((c & 3) == 1) || ((c & 3) == 2)) { /* skip padding byte */ if (((c & 3) == 1) || ((c & 3) == 2)) { /* skip padding byte */
getc(IN); getc(IN);
@ -678,6 +680,10 @@ static OPJ_BOOL bmp_read_rle4_data(FILE* IN, OPJ_UINT8* pData,
} }
} }
} /* while(y < height) */ } /* while(y < height) */
if (written != width * height) {
fprintf(stderr, "warning, image's actual size does not match advertized one\n");
return OPJ_FALSE;
}
return OPJ_TRUE; return OPJ_TRUE;
} }