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.x] Fix loading RLE compressed TGA files. #49603

Merged
merged 1 commit into from
Jun 14, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions modules/tga/image_loader_tga.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "core/os/os.h"
#include "core/print_string.h"

Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size) {
Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size, size_t p_input_size) {
Error error;

PoolVector<uint8_t> pixels;
Expand All @@ -56,11 +56,14 @@ 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) {
if (output_pos + count * p_pixel_size > p_output_size) {
return ERR_PARSE_ERROR;
}

if (c & 0x80) {
if (compressed_pos + p_pixel_size > p_input_size) {
return ERR_PARSE_ERROR;
}
for (size_t i = 0; i < p_pixel_size; i++) {
pixels_w.ptr()[i] = p_compressed_buffer[compressed_pos];
compressed_pos += 1;
Expand All @@ -72,6 +75,9 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t
output_pos += p_pixel_size;
}
} else {
if (compressed_pos + count * p_pixel_size > p_input_size) {
return ERR_PARSE_ERROR;
}
count *= p_pixel_size;
for (size_t i = 0; i < count; i++) {
p_uncompressed_buffer[output_pos] = p_compressed_buffer[compressed_pos];
Expand All @@ -83,7 +89,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, size_t p_output_size) {
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_input_size) {
#define TGA_PUT_PIXEL(r, g, b, a) \
int image_data_ofs = ((y * width) + x); \
image_data_w[image_data_ofs * 4 + 0] = r; \
Expand Down Expand Up @@ -134,7 +140,7 @@ 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) {
if (i >= p_input_size) {
return ERR_PARSE_ERROR;
}
uint8_t shade = p_buffer[i];
Expand All @@ -150,7 +156,7 @@ 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) {
if (i >= p_input_size) {
return ERR_PARSE_ERROR;
}
uint8_t index = p_buffer[i];
Expand Down Expand Up @@ -181,7 +187,7 @@ 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) {
if (i + 2 >= p_input_size) {
return ERR_PARSE_ERROR;
}

Expand All @@ -200,7 +206,7 @@ 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) {
if (i + 3 >= p_input_size) {
return ERR_PARSE_ERROR;
}

Expand Down Expand Up @@ -309,7 +315,7 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
const uint8_t *buffer = nullptr;

if (is_encoded) {
err = decode_tga_rle(src_image_r.ptr(), pixel_size, uncompressed_buffer_w.ptr(), buffer_size);
err = decode_tga_rle(src_image_r.ptr(), pixel_size, uncompressed_buffer_w.ptr(), buffer_size, src_image_len);

if (err == OK) {
uncompressed_buffer_r = uncompressed_buffer.read();
Expand Down
4 changes: 2 additions & 2 deletions modules/tga/image_loader_tga.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ class ImageLoaderTGA : public ImageFormatLoader {
uint8_t pixel_depth;
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, size_t p_output_size);
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, size_t p_input_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, size_t p_input_size);

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