summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/Makefile.am2
-rw-r--r--server/red_parse_qxl.c43
-rw-r--r--server/red_worker.c39
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);