diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/Makefile.am | 2 | ||||
-rw-r--r-- | server/red_parse_qxl.c | 43 | ||||
-rw-r--r-- | server/red_worker.c | 39 |
3 files changed, 61 insertions, 23 deletions
diff --git a/server/Makefile.am b/server/Makefile.am index dc3070fe..d82f4cf6 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -22,7 +22,7 @@ spice_built_sources = generated_marshallers.c generated_marshallers.h generated_ generated_demarshallers.c: $(top_srcdir)/spice.proto $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --server --include red_common.h $(top_srcdir)/spice.proto generated_demarshallers.c -STRUCTS=-M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlnd -M PathSegment +STRUCTS=-M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlnd generated_marshallers.c: $(top_srcdir)/spice.proto $(PYTHON) $(top_srcdir)/spice_codegen.py --include red_common.h --generate-marshallers $(STRUCTS) --server $(top_srcdir)/spice.proto generated_marshallers.c diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c index de5501b5..6fb439e5 100644 --- a/server/red_parse_qxl.c +++ b/server/red_parse_qxl.c @@ -153,8 +153,10 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id, bool free_data; QXLPath *qxl; SpicePath *red; - size_t size; + size_t size, mem_size, mem_size2, dsize; + int n_segments; int i; + uint32_t count; qxl = (QXLPath *)get_virt(slots, addr, sizeof(*qxl), group_id); size = red_get_data_chunks_ptr(slots, group_id, @@ -163,17 +165,44 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id, data = red_linearize_chunk(&chunks, size, &free_data); red_put_data_chunks(&chunks); - ASSERT(qxl->data_size == size); - ASSERT(sizeof(QXLPathSeg) == sizeof(SpicePathSeg)); /* FIXME */ - red = spice_malloc(sizeof(*red) + size); - red->size = qxl->data_size; + n_segments = 0; + mem_size = sizeof(*red); + + start = (QXLPathSeg*)data; + end = (QXLPathSeg*)(data + size); + while (start < end) { + n_segments++; + count = start->count; + mem_size += sizeof(SpicePathSeg) + count * sizeof(SpicePointFix); + start = (QXLPathSeg*)(&start->points[count]); + } + + red = spice_malloc(mem_size); + red->num_segments = n_segments; start = (QXLPathSeg*)data; end = (QXLPathSeg*)(data + size); seg = red->segments; + n_segments = 0; + mem_size2 = sizeof(*red); while (start < end) { + n_segments++; + count = start->count; + + /* Protect against overflow in size calculations before + writing to memory */ + ASSERT(mem_size2 + sizeof(SpicePathSeg) > mem_size2); + mem_size2 += sizeof(SpicePathSeg); + ASSERT(count < UINT32_MAX / sizeof(SpicePointFix)); + dsize = count * sizeof(SpicePointFix); + ASSERT(mem_size2 + dsize > mem_size2); + mem_size2 += dsize; + + /* Verify that we didn't overflow due to guest changing data */ + ASSERT(mem_size2 <= mem_size); + seg->flags = start->flags; - seg->count = start->count; + seg->count = count; for (i = 0; i < seg->count; i++) { seg->points[i].x = start->points[i].x; seg->points[i].y = start->points[i].y; @@ -181,6 +210,8 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id, start = (QXLPathSeg*)(&start->points[i]); seg = (SpicePathSeg*)(&seg->points[i]); } + /* Ensure guest didn't tamper with segment count */ + ASSERT(n_segments == red->num_segments); if (free_data) { free(data); diff --git a/server/red_worker.c b/server/red_worker.c index 272b68d9..6d821c96 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -2291,10 +2291,29 @@ static inline void __current_add_drawable(RedWorker *worker, Drawable *drawable, static int is_equal_path(RedWorker *worker, SpicePath *path1, SpicePath *path2) { - if (path1->size != path2->size) - return FALSE; - if (memcmp(path1->segments, path2->segments, path1->size) != 0) + SpicePathSeg *seg1, *seg2; + int i, j; + + if (path1->num_segments != path2->num_segments) return FALSE; + + seg1 = &path1->segments[0]; + seg2 = &path2->segments[0]; + for (i = 0; i < path1->num_segments; i++) { + if (seg1->flags != seg2->flags || + seg1->count != seg2->count) { + return FALSE; + } + for (j = 0; j < seg1->count; j++) { + if (seg1->points[j].x != seg2->points[j].x || + seg1->points[j].y != seg2->points[j].y) { + return FALSE; + } + } + seg1 = (SpicePathSeg*)(&seg1->points[seg1->count]); + seg2 = (SpicePathSeg*)(&seg2->points[seg2->count]); + } + return TRUE; } @@ -5121,18 +5140,6 @@ static void add_buf_from_info(RedChannel *channel, SpiceMarshaller *m, AddBufInf } -static void fill_path(SpiceMarshaller *m, SpicePath *path) -{ - SpicePathSeg *start, *end; - - spice_marshaller_add_uint32(m, path->size); - start = path->segments; - end = (SpicePathSeg*)((uint8_t*)(path->segments) + path->size); - while (start < end) { - start = spice_marshall_PathSegment(m, start); - } -} - static void fill_str(DisplayChannel *display_channel, SpiceMarshaller *m, QXLPHYSICAL in_str, uint32_t group_id) { @@ -8004,7 +8011,7 @@ static void red_send_qxl_draw_stroke(RedWorker *worker, &style_out, &brush_pat_out); - fill_path(path_out, stroke.path); + spice_marshall_Path(path_out, stroke.path); fill_attr(display_channel, style_out, &stroke.attr, item->group_id); if (brush_pat_out) { fill_bits(display_channel, brush_pat_out, stroke.brush.u.pattern.pat, item, FALSE); |