summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2018-06-27 10:55:05 +0100
committerFrediano Ziglio <fziglio@redhat.com>2018-07-12 05:48:12 +0100
commite8314732a7b0b7d289f5befd0b0e4d81dfb500dc (patch)
tree5446bebb1ffd46656f69dbc87c4208ee079f5690
parentf636ef42a0dfd84337345953bf02d19f70bf8937 (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.c24
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