summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2010-06-29 21:42:59 +0200
committerGerd Hoffmann <kraxel@redhat.com>2010-06-30 22:35:17 +0200
commita24a8ff72ae40432f2ffe246f973057e38b042b0 (patch)
tree34fa9ddf1033ec22e3bc113582bef07f7e29c6b5 /server
parent0f5a6f57b70bb7c94e15e908db4627d44c339b9c (diff)
Store SpicePath segment count rather than size
Internally and in the network protocol (for the new version) we now store the actual number of segments rather than the size of the full segments array in bytes. This change consists of multiple changes to handle this: * Make the qxl parser calculate num_segments * Make the canvas stroke code handle the new SpicePath layout. * Fix up is_equal_path in red_worker.c for the new layout * replace multiple calls to spice_marshall_PathSegment with a single spice_marshall_Path call * Make the byte_size() array size handling do the conversion from network size to number of elements when marshalling/demarshalling. * Update the current spice protocol to send the segment count rather than the size * Update the old spice protocol to use the new byte_size functionallity to calculate the size sent and the number of elements recieved
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 dc3070f..d82f4cf 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 de5501b..6fb439e 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 272b68d..6d821c9 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);