1
0
Fork 0

(svn r22872) -Fix [FS#4746]: Improve handling of slightly invalid BMP files using the under-specified RLE compression. Improve coding style while at it as well. (Based on patch by monoid)

release/1.2
michi_cc 2011-09-02 20:16:29 +00:00
parent 73624abd5e
commit 655d45e7d3
1 changed files with 86 additions and 69 deletions

View File

@ -130,54 +130,63 @@ static inline bool BmpRead4(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
*/ */
static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data) static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
uint i;
uint x = 0; uint x = 0;
uint y = info->height - 1; uint y = info->height - 1;
byte n, c, b;
byte *pixel = &data->bitmap[y * info->width]; byte *pixel = &data->bitmap[y * info->width];
while (y != 0 || x < info->width) { while (y != 0 || x < info->width) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
n = ReadByte(buffer);
c = ReadByte(buffer); byte n = ReadByte(buffer);
byte c = ReadByte(buffer);
if (n == 0) { if (n == 0) {
switch (c) { switch (c) {
case 0: // end of line case 0: // end of line
x = 0; x = 0;
if (y == 0) return false; if (y == 0) return false;
pixel = &data->bitmap[--y * info->width]; pixel = &data->bitmap[--y * info->width];
break; break;
case 1: // end of bitmap
x = info->width; case 1: // end of bitmap
y = 0; return true;
pixel = NULL;
break; case 2: { // delta
case 2: // delta if (EndOfBuffer(buffer)) return false;
x += ReadByte(buffer); byte dx = ReadByte(buffer);
i = ReadByte(buffer); byte dy = ReadByte(buffer);
if (x >= info->width || i > y) return false;
y -= i; /* Check for over- and underflow. */
pixel = &data->bitmap[y * info->width + x]; if (x + dx >= info->width || x + dx < x || dy > y) return false;
break;
default: // uncompressed x += dx;
i = 0; y -= dy;
while (i++ < c) { pixel = &data->bitmap[y * info->width + x];
if (EndOfBuffer(buffer) || x >= info->width) return false; break;
b = ReadByte(buffer); }
*pixel++ = GB(b, 4, 4);
x++; default: { // uncompressed
if (x < info->width && i++ < c) { uint i = 0;
*pixel++ = GB(b, 0, 4); while (i++ < c) {
x++; if (EndOfBuffer(buffer) || x >= info->width) return false;
} byte b = ReadByte(buffer);
*pixel++ = GB(b, 4, 4);
x++;
if (i++ < c) {
if (x >= info->width) return false;
*pixel++ = GB(b, 0, 4);
x++;
}
}
/* Padding for 16 bit align */
SkipBytes(buffer, ((c + 1) / 2) % 2);
break;
} }
/* Padding for 16 bit align */
SkipBytes(buffer, ((c + 1) / 2) % 2);
break;
} }
} else { } else {
i = 0; /* Apparently it is common to encounter BMPs where the count of
while (i++ < n) { * pixels to be written is higher than the remaining line width.
if (EndOfBuffer(buffer) || x >= info->width) return false; * Ignore the superfluous pixels instead of reporting an error. */
uint i = 0;
while (x < info->width && i++ < n) {
*pixel++ = GB(c, 4, 4); *pixel++ = GB(c, 4, 4);
x++; x++;
if (x < info->width && i++ < n) { if (x < info->width && i++ < n) {
@ -214,47 +223,55 @@ static inline bool BmpRead8(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
*/ */
static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data) static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
uint i;
uint x = 0; uint x = 0;
uint y = info->height - 1; uint y = info->height - 1;
byte n, c;
byte *pixel = &data->bitmap[y * info->width]; byte *pixel = &data->bitmap[y * info->width];
while (y != 0 || x < info->width) { while (y != 0 || x < info->width) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
n = ReadByte(buffer);
c = ReadByte(buffer); byte n = ReadByte(buffer);
byte c = ReadByte(buffer);
if (n == 0) { if (n == 0) {
switch (c) { switch (c) {
case 0: // end of line case 0: // end of line
x = 0; x = 0;
if (y == 0) return false; if (y == 0) return false;
pixel = &data->bitmap[--y * info->width]; pixel = &data->bitmap[--y * info->width];
break; break;
case 1: // end of bitmap
x = info->width; case 1: // end of bitmap
y = 0; return true;
pixel = NULL;
break; case 2: { // delta
case 2: // delta if (EndOfBuffer(buffer)) return false;
x += ReadByte(buffer); byte dx = ReadByte(buffer);
i = ReadByte(buffer); byte dy = ReadByte(buffer);
if (x >= info->width || i > y) return false;
y -= i; /* Check for over- and underflow. */
pixel = &data->bitmap[y * info->width + x]; if (x + dx >= info->width || x + dx < x || dy > y) return false;
break;
default: // uncompressed x += dx;
for (i = 0; i < c; i++) { y -= dy;
if (EndOfBuffer(buffer) || x >= info->width) return false; pixel = &data->bitmap[y * info->width + x];
*pixel++ = ReadByte(buffer); break;
x++; }
default: { // uncompressed
for (uint i = 0; i < c; i++) {
if (EndOfBuffer(buffer) || x >= info->width) return false;
*pixel++ = ReadByte(buffer);
x++;
}
/* Padding for 16 bit align */
SkipBytes(buffer, c % 2);
break;
} }
/* Padding for 16 bit align */
SkipBytes(buffer, c % 2);
break;
} }
} else { } else {
for (i = 0; i < n; i++) { /* Apparently it is common to encounter BMPs where the count of
if (x >= info->width) return false; * pixels to be written is higher than the remaining line width.
* Ignore the superfluous pixels instead of reporting an error. */
for (uint i = 0; x < info->width && i < n; i++) {
*pixel++ = c; *pixel++ = c;
x++; x++;
} }