fix(rle): avoid buffer overflow when compressed data is not in pixel unit (#5619)

Signed-off-by: Neo Xu <neo.xu1990@gmail.com>
This commit is contained in:
Neo Xu
2024-02-11 11:18:34 +08:00
committed by GitHub
parent 28a7c37b79
commit 73f2f547cb
2 changed files with 18 additions and 17 deletions
+1 -13
View File
@@ -1069,13 +1069,8 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image
uint32_t out_len = compressed->decompressed_size;
uint32_t input_len = compressed->compressed_size;
LV_UNUSED(input_len);
LV_UNUSED(out_len);
/**
* @todo
* FIXME, RLE compressed image needs extra memory because decompression operates on
* pixel unit not byte unit. Should optimize RLE decompress to not write to extra memory.
*/
dsc->header.h += 1;
lv_draw_buf_t * decompressed = lv_draw_buf_create(dsc->header.w, dsc->header.h, dsc->header.cf,
dsc->header.stride);
if(decompressed == NULL) {
@@ -1083,13 +1078,6 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image
return LV_RESULT_INVALID;
}
dsc->header.h -= 1; /*Change it back*/
if(decompressed->data_size < out_len) {
LV_LOG_WARN("decompressed size mismatch: %" LV_PRIu32 ", %" LV_PRIu32, decompressed->data_size, out_len);
lv_draw_buf_destroy(decompressed);
return LV_RESULT_INVALID;
}
img_data = decompressed->data;
if(compressed->method == LV_IMAGE_COMPRESS_RLE) {
+17 -4
View File
@@ -58,8 +58,12 @@ uint32_t lv_rle_decompress(const uint8_t * input,
return 0;
wr_len += bytes;
if(wr_len > output_buff_len)
return 0;
if(wr_len > output_buff_len) {
if(wr_len > output_buff_len + blk_size)
return 0; /* Error */
lv_memcpy(output, input, output_buff_len - (wr_len - bytes));
return output_buff_len;
}
lv_memcpy(output, input, bytes);
output += bytes;
@@ -71,8 +75,17 @@ uint32_t lv_rle_decompress(const uint8_t * input,
return 0;
wr_len += blk_size * ctrl_byte;
if(wr_len > output_buff_len)
return 0;
if(wr_len > output_buff_len) {
if(wr_len > output_buff_len + blk_size)
return 0; /* Error happened */
/* Skip the last pixel, which could overflow output buffer.*/
for(uint32_t i = 0; i < ctrl_byte - 1; i++) {
lv_memcpy(output, input, blk_size);
output += blk_size;
}
return output_buff_len;
}
if(blk_size == 1) {
/* optimize the most common case. */