mirror of
https://github.com/lvgl/lvgl.git
synced 2026-06-01 00:51:49 +08:00
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:
@@ -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
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user