|
|
e2c81d |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
73b8f2 |
From: Frediano Ziglio <fziglio@redhat.com>
|
|
|
73b8f2 |
Date: Tue, 8 Sep 2015 10:13:24 +0100
|
|
|
e2c81d |
Subject: [PATCH] Fix integer overflow computing glyph_size in red_get_string
|
|
|
73b8f2 |
|
|
|
73b8f2 |
If bpp is int the formula can lead to weird overflows. width and height
|
|
|
73b8f2 |
are uint16_t so the formula is:
|
|
|
73b8f2 |
|
|
|
73b8f2 |
size_t = u16 * (u16 * int + const_int) / const_int;
|
|
|
73b8f2 |
|
|
|
73b8f2 |
so it became
|
|
|
73b8f2 |
|
|
|
73b8f2 |
size_t = (int) u16 * ((int) u16 * int + const_int) / const_int;
|
|
|
73b8f2 |
|
|
|
73b8f2 |
However the (int) u16 * (int) u16 can then became negative to overflow.
|
|
|
73b8f2 |
Under 64 bit architectures size_t is 64 and int usually 32 so converting
|
|
|
73b8f2 |
this negative 32 bit number to a unsigned 64 bit lead to a very big
|
|
|
73b8f2 |
number as the signed is extended and then converted to unsigned.
|
|
|
73b8f2 |
Using unsigned arithmetic prevent extending the sign.
|
|
|
73b8f2 |
|
|
|
73b8f2 |
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
|
|
|
73b8f2 |
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
|
|
|
73b8f2 |
---
|
|
|
73b8f2 |
server/red_parse_qxl.c | 8 +++++---
|
|
|
73b8f2 |
1 file changed, 5 insertions(+), 3 deletions(-)
|
|
|
73b8f2 |
|
|
|
73b8f2 |
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
|
|
|
73b8f2 |
index 2d4636e..c4b82be 100644
|
|
|
73b8f2 |
--- a/server/red_parse_qxl.c
|
|
|
73b8f2 |
+++ b/server/red_parse_qxl.c
|
|
|
73b8f2 |
@@ -807,7 +807,9 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
|
|
|
73b8f2 |
uint8_t *data;
|
|
|
73b8f2 |
bool free_data;
|
|
|
73b8f2 |
size_t chunk_size, qxl_size, red_size, glyph_size;
|
|
|
73b8f2 |
- int glyphs, bpp = 0, i;
|
|
|
73b8f2 |
+ int glyphs, i;
|
|
|
73b8f2 |
+ /* use unsigned to prevent integer overflow in multiplication below */
|
|
|
73b8f2 |
+ unsigned int bpp = 0;
|
|
|
73b8f2 |
int error;
|
|
|
73b8f2 |
uint16_t qxl_flags, qxl_length;
|
|
|
73b8f2 |
|
|
|
73b8f2 |
@@ -846,7 +848,7 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
|
|
|
73b8f2 |
while (start < end) {
|
|
|
73b8f2 |
spice_assert((QXLRasterGlyph*)(&start->data[0]) <= end);
|
|
|
73b8f2 |
glyphs++;
|
|
|
73b8f2 |
- glyph_size = start->height * ((start->width * bpp + 7) / 8);
|
|
|
73b8f2 |
+ glyph_size = start->height * ((start->width * bpp + 7u) / 8u);
|
|
|
73b8f2 |
red_size += sizeof(SpiceRasterGlyph *) + SPICE_ALIGN(sizeof(SpiceRasterGlyph) + glyph_size, 4);
|
|
|
73b8f2 |
start = (QXLRasterGlyph*)(&start->data[glyph_size]);
|
|
|
73b8f2 |
}
|
|
|
73b8f2 |
@@ -867,7 +869,7 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
|
|
|
73b8f2 |
glyph->height = start->height;
|
|
|
73b8f2 |
red_get_point_ptr(&glyph->render_pos, &start->render_pos);
|
|
|
73b8f2 |
red_get_point_ptr(&glyph->glyph_origin, &start->glyph_origin);
|
|
|
73b8f2 |
- glyph_size = glyph->height * ((glyph->width * bpp + 7) / 8);
|
|
|
73b8f2 |
+ glyph_size = glyph->height * ((glyph->width * bpp + 7u) / 8u);
|
|
|
73b8f2 |
spice_assert((QXLRasterGlyph*)(&start->data[glyph_size]) <= end);
|
|
|
73b8f2 |
memcpy(glyph->data, start->data, glyph_size);
|
|
|
73b8f2 |
start = (QXLRasterGlyph*)(&start->data[glyph_size]);
|