diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2018-06-27 10:55:05 +0100 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2018-07-12 05:48:12 +0100 |
commit | e8314732a7b0b7d289f5befd0b0e4d81dfb500dc (patch) | |
tree | 5446bebb1ffd46656f69dbc87c4208ee079f5690 | |
parent | f636ef42a0dfd84337345953bf02d19f70bf8937 (diff) |
canvas_base: Check for overflows decoding LZ4
Check that we have enough data before reading.
This could lead to read buffer overflows being undetected.
This is not a security issue, read happens only in the client not causing
any information leakage, maximum can generate a crash or some garbage on
the screen.
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
-rw-r--r-- | common/canvas_base.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/common/canvas_base.c b/common/canvas_base.c index 2fd60aa..3283e88 100644 --- a/common/canvas_base.c +++ b/common/canvas_base.c @@ -537,6 +537,10 @@ static pixman_image_t *canvas_get_lz4(CanvasBase *canvas, SpiceImage *image) width = image->descriptor.width; stride_encoded = width; height = image->descriptor.height; + if (data + 2 > data_end) { + g_warning("missing header in LZ4 data"); + return NULL; + } top_down = !!*(data++); spice_format = *(data++); switch (spice_format) { @@ -579,16 +583,22 @@ static pixman_image_t *canvas_get_lz4(CanvasBase *canvas, SpiceImage *image) bits = dest; do { + if (data + 4 > data_end) { + goto format_error; + } // Read next compressed block enc_size = read_uint32_be(data); data += 4; + /* check overflow. This check is a bit different to avoid + * possible overflows. From previous check data_end - data cannot overflow. + * Computing data + enc_size on 32 bit could cause overflows. */ + if (enc_size < 0 || data_end - data < (unsigned int) enc_size) { + goto format_error; + } dec_size = LZ4_decompress_safe_continue(stream, (const char *) data, (char *) dest, enc_size, available); if (dec_size <= 0) { - spice_warning("Error decoding LZ4 block\n"); - pixman_image_unref(surface); - surface = NULL; - break; + goto format_error; } dest += dec_size; available -= dec_size; @@ -599,6 +609,12 @@ static pixman_image_t *canvas_get_lz4(CanvasBase *canvas, SpiceImage *image) LZ4_freeStreamDecode(stream); return surface; + +format_error: + spice_warning("Error decoding LZ4 block\n"); + LZ4_freeStreamDecode(stream); + pixman_image_unref(surface); + return NULL; } #endif |