Skip to content

Commit

Permalink
Fix some BMP loading bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
aaaaaa123456789 committed Jan 30, 2022
1 parent 94e1fbf commit 6183bea
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 14 deletions.
7 changes: 6 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@ Note: releases are listed from latest to oldest.
- Fixed a file descriptor leak that would keep an open `FILE *` if a `PLUM_ERR_FILE_ERROR` error was raised while
reading from a file
- Fixed a bug that prevented non-vertically-flipped BMP files from ever loading
- Fixed read-past-the-end bug when loading monochrome BMP files with a width that is a multiple of 8
- Added safeguards to prevent internal `longjmp` misuse when generating image files
- Ensured that the `PLUM_FILENAME`, `PLUM_BUFFER` and `PLUM_CALLBACK` constants are always `size_t` as documented
- Enforced the size limitation on the value returned by a callback when using the `PLUM_CALLBACK` loading/storing mode
- Handled out-of-palette background colors when generating a GIF file, ensuring that they would never cause the
process to fail (the background is ignored instead if there are no available palette slots)
- Added some warning flags for debug builds, and cleared some warnings that would be raised by them
- Added and improved some safety checks that detect maliciously-crafted and other pathological files
- Added detection for empty GIF files (erroring out with `PLUM_ERR_NO_DATA` instead of `PLUM_ERR_INVALID_FILE_FORMAT`)
- Added detection for empty BMP and GIF files (erroring out with `PLUM_ERR_NO_DATA` instead of
`PLUM_ERR_INVALID_FILE_FORMAT`)
- Allowed decompressing BMP files that end their last line with a row end marker (and maybe no data end marker)
- Improved PNG compression by fixing a lookback bug in the compressor and adjusting the lookback length
- Prevented BMP images with a height of `0x80000000` from loading, since this is a negative 32-bit value that has no
positive counterpart (erroring out with `PLUM_ERR_INVALID_FILE_FORMAT`)
- Added and documented a restriction requiring `size_t` to be at least 32 bits wide
- Updated documentation for `plum_load_image` to indicate that a `PLUM_ERR_IMAGE_TOO_LARGE` error may also occur if
the image's overall dimensions are too large
Expand Down
29 changes: 16 additions & 13 deletions src/bmpread.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ void load_BMP_data (struct context * context, unsigned flags, size_t limit) {
uint_fast32_t dataoffset = read_le32_unaligned(context -> data + 10);
uint_fast32_t subheader = read_le32_unaligned(context -> data + 14);
if ((subheader < 40) || (subheader >= 0xffffffe6u)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if ((dataoffset < (subheader + 14)) || (dataoffset >= context -> size)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
context -> image -> type = PLUM_IMAGE_BMP;
context -> image -> frames = 1;
context -> image -> width = read_le32_unaligned(context -> data + 18);
context -> image -> height = read_le32_unaligned(context -> data + 22);
if (context -> image -> width > 0x7fffffffu) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if ((context -> image -> width > 0x7fffffffu) || (context -> image -> height == 0x80000000u)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
int inverted = 1;
if (context -> image -> height > 0x7fffffffu) {
context -> image -> height = -context -> image -> height;
inverted = 0;
}
validate_image_size(context, limit);
if ((dataoffset < (subheader + 14)) || (dataoffset >= context -> size)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if (read_le16_unaligned(context -> data + 26) != 1) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
uint_fast16_t bits = read_le16_unaligned(context -> data + 28);
uint_fast32_t compression = read_le32_unaligned(context -> data + 30);
Expand Down Expand Up @@ -160,9 +160,10 @@ uint8_t * load_monochrome_BMP (struct context * context, size_t offset, int inve
frame[cell ++] = !!(*pixeldata & 2);
frame[cell ++] = *pixeldata & 1;
}
unsigned char remainder = *pixeldata;
for (pos = context -> image -> width & 7; pos; pos --, remainder <<= 1)
frame[cell ++] = !!(remainder & 0x80);
if (context -> image -> width & 7) {
unsigned char remainder = *pixeldata;
for (pos = context -> image -> width & 7; pos; pos --, remainder <<= 1) frame[cell ++] = !!(remainder & 0x80);
}
if (inverted)
rowdata -= rowsize;
else
Expand Down Expand Up @@ -231,10 +232,11 @@ uint8_t * load_halfbyte_compressed_BMP (struct context * context, size_t offset,
}
} else switch (databyte) {
case 0:
if (!row) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
row --;
col = 0;
break;
if (row) {
row --;
col = 0;
break;
}
case 1:
return frame;
case 2:
Expand Down Expand Up @@ -279,10 +281,11 @@ uint8_t * load_byte_compressed_BMP (struct context * context, size_t offset, int
col += length;
} else switch (databyte) {
case 0:
if (!row) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
row --;
col = 0;
break;
if (row) {
row --;
col = 0;
break;
}
case 1:
return frame;
case 2:
Expand Down

0 comments on commit 6183bea

Please sign in to comment.