Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.2] Fix a crash in the TGA loader with malformed input #45702

Merged
merged 1 commit into from Feb 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 22 additions & 3 deletions modules/tga/image_loader_tga.cpp
Expand Up @@ -55,6 +55,10 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t
compressed_pos += 1;
count = (c & 0x7f) + 1;

if (output_pos + count * p_pixel_size > output_pos) {
return ERR_PARSE_ERROR;
}

if (c & 0x80) {
for (size_t i = 0; i < p_pixel_size; i++) {
pixels_w.ptr()[i] = p_compressed_buffer[compressed_pos];
Expand All @@ -78,7 +82,7 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t
return OK;
}

Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome) {
Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_output_size) {

#define TGA_PUT_PIXEL(r, g, b, a) \
int image_data_ofs = ((y * width) + x); \
Expand Down Expand Up @@ -130,6 +134,9 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
if (p_is_monochrome) {
while (y != y_end) {
while (x != x_end) {
if (i > p_output_size) {
return ERR_PARSE_ERROR;
}
uint8_t shade = p_buffer[i];

TGA_PUT_PIXEL(shade, shade, shade, 0xff)
Expand All @@ -143,6 +150,9 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else {
while (y != y_end) {
while (x != x_end) {
if (i > p_output_size) {
return ERR_PARSE_ERROR;
}
uint8_t index = p_buffer[i];
uint8_t r = 0x00;
uint8_t g = 0x00;
Expand Down Expand Up @@ -171,6 +181,10 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else if (p_header.pixel_depth == 24) {
while (y != y_end) {
while (x != x_end) {
if (i + 2 > p_output_size) {
return ERR_PARSE_ERROR;
}

uint8_t r = p_buffer[i + 2];
uint8_t g = p_buffer[i + 1];
uint8_t b = p_buffer[i + 0];
Expand All @@ -186,6 +200,10 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else if (p_header.pixel_depth == 32) {
while (y != y_end) {
while (x != x_end) {
if (i + 3 > p_output_size) {
return ERR_PARSE_ERROR;
}

uint8_t a = p_buffer[i + 3];
uint8_t r = p_buffer[i + 2];
uint8_t g = p_buffer[i + 1];
Expand Down Expand Up @@ -280,7 +298,7 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
PoolVector<uint8_t>::Read src_image_r = src_image.read();

const size_t pixel_size = tga_header.pixel_depth >> 3;
const size_t buffer_size = (tga_header.image_width * tga_header.image_height) * pixel_size;
size_t buffer_size = (tga_header.image_width * tga_header.image_height) * pixel_size;

PoolVector<uint8_t> uncompressed_buffer;
uncompressed_buffer.resize(buffer_size);
Expand All @@ -299,11 +317,12 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
}
} else {
buffer = src_image_r.ptr();
buffer_size = src_image_len;
};

if (err == OK) {
PoolVector<uint8_t>::Read palette_r = palette.read();
err = convert_to_image(p_image, buffer, tga_header, palette_r.ptr(), is_monochrome);
err = convert_to_image(p_image, buffer, tga_header, palette_r.ptr(), is_monochrome, buffer_size);
}
}

Expand Down
2 changes: 1 addition & 1 deletion modules/tga/image_loader_tga.h
Expand Up @@ -73,7 +73,7 @@ class ImageLoaderTGA : public ImageFormatLoader {
uint8_t image_descriptor;
};
static Error decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size);
static Error convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome);
static Error convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_output_size);

public:
virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
Expand Down