Detect errors in record file. This can happen from a wrong version or corruption of files. Allocations are kept into a GList to be able to free in case some errors happened. Some macros are used to return error condition without many if. replay_t was converted to a pointer and REPLAY_EOF is NULL to have the same return for any errors. To check fscanf read all needed information a dummy "%n" is appended to any string and the value stored there is tested. Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> --- server/red-replay-qxl.c | 228 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 162 insertions(+), 66 deletions(-) diff --git a/server/red-replay-qxl.c b/server/red-replay-qxl.c index b17c38b..5462cca 100644 --- a/server/red-replay-qxl.c +++ b/server/red-replay-qxl.c @@ -34,10 +34,9 @@ #define QXLPHYSICAL_FROM_PTR(ptr) ((QXLPHYSICAL)(intptr_t)(ptr)) #define QXLPHYSICAL_TO_PTR(phy) ((void*)(intptr_t)(phy)) -typedef enum { - REPLAY_OK = 0, - REPLAY_EOF, -} replay_t; +typedef void *replay_t; +#define REPLAY_EOF NULL +#define REPLAY_OK ((replay_t)~(gsize)0) struct SpiceReplay { FILE *fd; @@ -49,6 +48,9 @@ struct SpiceReplay { GArray *id_map_inv; // replay id -> record id GArray *id_free; // free list int nsurfaces; + int end_pos; + + GList *allocated; pthread_mutex_t mutex; pthread_cond_t cond; @@ -66,12 +68,18 @@ static int replay_fread(SpiceReplay *replay, uint8_t *buf, size_t size) return fread(buf, size, 1, replay->fd); } +#define REPLAY_CHK(ret) do {\ + if ((ret) == REPLAY_EOF) return NULL; \ + }while(0) + __attribute__((format(scanf, 2, 3))) -static replay_t replay_fscanf(SpiceReplay *replay, const char *fmt, ...) +static replay_t replay_fscanf_check(SpiceReplay *replay, const char *fmt, ...) { va_list ap; int ret; + replay->end_pos = -1; + if (replay->eof) { return REPLAY_EOF; } @@ -82,11 +90,38 @@ static replay_t replay_fscanf(SpiceReplay *replay, const char *fmt, ...) va_start(ap, fmt); ret = vfscanf(replay->fd, fmt, ap); va_end(ap); - if (ret == EOF) { + if (ret == EOF || replay->end_pos < 0) { replay->eof = 1; } return replay->eof ? REPLAY_EOF : REPLAY_OK; } +#define replay_fscanf_check(r, fmt, ...) \ + replay_fscanf_check(r, fmt "%n", ## __VA_ARGS__, &r->end_pos) +#define replay_fscanf(r, fmt, ...) \ + REPLAY_CHK(replay_fscanf_check(r, fmt, ## __VA_ARGS__)) + +static inline void add_allocated(SpiceReplay *replay, void *ptr) +{ + replay->allocated = g_list_prepend(replay->allocated, ptr); + if (!replay->allocated) { + spice_error("error allocating memory"); + abort(); + } +} + +static inline void *replay_malloc(SpiceReplay *replay, size_t size) +{ + void *p = spice_malloc(size); + add_allocated(replay, p); + return p; +} + +static inline void *replay_malloc0(SpiceReplay *replay, size_t size) +{ + void *p = spice_malloc0(size); + add_allocated(replay, p); + return p; +} static uint32_t replay_id_get(SpiceReplay *replay, uint32_t id) { @@ -188,18 +223,18 @@ static void hexdump(uint8_t *hex, uint8_t bytes) static replay_t read_binary(SpiceReplay *replay, const char *prefix, size_t *size, uint8_t **buf, size_t base_size) { - char template[1024]; + char file_prefix[1024]; int with_zlib = -1; int zlib_size; - uint8_t *zlib_buffer; + uint8_t *zlib_buffer = NULL; z_stream strm; - snprintf(template, sizeof(template), "binary %%d %s %%ld:", prefix); - if (replay_fscanf(replay, template, &with_zlib, size) == REPLAY_EOF) + replay_fscanf(replay, "binary %d %1000s %ld:", &with_zlib, file_prefix, size); + if (strcmp(file_prefix, prefix) != 0) return REPLAY_EOF; if (*buf == NULL) { - *buf = spice_malloc(*size + base_size); + *buf = replay_malloc(replay, *size + base_size); } #if 0 { @@ -211,9 +246,11 @@ static replay_t read_binary(SpiceReplay *replay, const char *prefix, size_t *siz spice_return_val_if_fail(with_zlib != -1, REPLAY_EOF); if (with_zlib) { int ret; + GList *elem; replay_fscanf(replay, "%d:", &zlib_size); - zlib_buffer = spice_malloc(zlib_size); + zlib_buffer = replay_malloc(replay, zlib_size); + elem = replay->allocated; replay_fread(replay, zlib_buffer, zlib_size); strm.zalloc = Z_NULL; strm.zfree = Z_NULL; @@ -241,7 +278,9 @@ static replay_t read_binary(SpiceReplay *replay, const char *prefix, size_t *siz } } (void)inflateEnd(&strm); + replay->allocated = g_list_remove_link(replay->allocated, elem); free(zlib_buffer); // TODO - avoid repeat alloc/dealloc by keeping last + zlib_buffer = NULL; } else { replay_fread(replay, *buf + base_size, *size); } @@ -250,7 +289,7 @@ static replay_t read_binary(SpiceReplay *replay, const char *prefix, size_t *siz return REPLAY_OK; } -static size_t red_replay_data_chunks(SpiceReplay *replay, const char *prefix, +static ssize_t red_replay_data_chunks(SpiceReplay *replay, const char *prefix, uint8_t **mem, size_t base_size) { size_t data_size; @@ -301,34 +340,46 @@ static void red_replay_data_chunks_free(SpiceReplay *replay, void *data, size_t free(data); } -static void red_replay_point_ptr(SpiceReplay *replay, QXLPoint *qxl) +static replay_t red_replay_point_ptr(SpiceReplay *replay, QXLPoint *qxl) { replay_fscanf(replay, "point %d %d\n", &qxl->x, &qxl->y); + return REPLAY_OK; } +#define red_replay_point_ptr(r, q) \ + REPLAY_CHK(red_replay_point_ptr(r, q)) -static void red_replay_point16_ptr(SpiceReplay *replay, QXLPoint16 *qxl) +static replay_t red_replay_point16_ptr(SpiceReplay *replay, QXLPoint16 *qxl) { int x, y; replay_fscanf(replay, "point16 %d %d\n", &x, &y); qxl->x = x; qxl->y = y; + return REPLAY_OK; } +#define red_replay_point16_ptr(r, q) \ + REPLAY_CHK(red_replay_point16_ptr(r, q)) -static void red_replay_rect_ptr(SpiceReplay *replay, const char *prefix, QXLRect *qxl) +static replay_t red_replay_rect_ptr(SpiceReplay *replay, const char *prefix, QXLRect *qxl) { - char template[1024]; + char file_prefix[1024]; - snprintf(template, sizeof(template), "rect %s %%d %%d %%d %%d\n", prefix); - replay_fscanf(replay, template, &qxl->top, &qxl->left, &qxl->bottom, &qxl->right); + replay_fscanf(replay, "rect %1000s %d %d %d %d\n", file_prefix, &qxl->top, &qxl->left, &qxl->bottom, &qxl->right); + if (strcmp(file_prefix, prefix) != 0) + return REPLAY_EOF; + return REPLAY_OK; } +#define red_replay_rect_ptr(r, p, q) \ + REPLAY_CHK(red_replay_rect_ptr(r, p, q)) static QXLPath *red_replay_path(SpiceReplay *replay) { QXLPath *qxl = NULL; - size_t data_size; + ssize_t data_size; data_size = red_replay_data_chunks(replay, "path", (uint8_t**)&qxl, sizeof(QXLPath)); - qxl->data_size = data_size; + if (data_size >= 0) { + qxl->data_size = data_size; + } return qxl; } @@ -345,8 +396,8 @@ static QXLClipRects *red_replay_clip_rects(SpiceReplay *replay) int num_rects; replay_fscanf(replay, "num_rects %d\n", &num_rects); - red_replay_data_chunks(replay, "clip_rects", (uint8_t**)&qxl, sizeof(QXLClipRects)); - qxl->num_rects = num_rects; + if (red_replay_data_chunks(replay, "clip_rects", (uint8_t**)&qxl, sizeof(QXLClipRects)) >= 0) + qxl->num_rects = num_rects; return qxl; } @@ -365,8 +416,9 @@ static uint8_t *red_replay_image_data_flat(SpiceReplay *replay, size_t *size) static QXLImage *red_replay_image(SpiceReplay *replay, uint32_t flags) { - QXLImage* qxl = NULL; - size_t bitmap_size, size; + QXLImage *qxl = NULL; + size_t bitmap_size; + ssize_t size; uint8_t qxl_flags; int temp; int has_palette; @@ -377,7 +429,7 @@ static QXLImage *red_replay_image(SpiceReplay *replay, uint32_t flags) return NULL; } - qxl = spice_new0(QXLImage, 1); + qxl = (QXLImage*)replay_malloc0(replay, sizeof(QXLImage)); replay_fscanf(replay, "descriptor.id %"PRIu64"\n", &qxl->descriptor.id); replay_fscanf(replay, "descriptor.type %d\n", &temp); qxl->descriptor.type = temp; replay_fscanf(replay, "descriptor.flags %d\n", &temp); qxl->descriptor.flags = temp; @@ -398,7 +450,7 @@ static QXLImage *red_replay_image(SpiceReplay *replay, uint32_t flags) int i, num_ents; replay_fscanf(replay, "qp.num_ents %d\n", &num_ents); - qp = spice_malloc(sizeof(QXLPalette) + num_ents * sizeof(qp->ents[0])); + qp = replay_malloc(replay, sizeof(QXLPalette) + num_ents * sizeof(qp->ents[0])); qp->num_ents = num_ents; qxl->bitmap.palette = QXLPHYSICAL_FROM_PTR(qp); replay_fscanf(replay, "unique %"PRIu64"\n", &qp->unique); @@ -413,7 +465,7 @@ static QXLImage *red_replay_image(SpiceReplay *replay, uint32_t flags) if (qxl_flags & QXL_BITMAP_DIRECT) { qxl->bitmap.data = QXLPHYSICAL_FROM_PTR(red_replay_image_data_flat(replay, &bitmap_size)); } else { - size = red_replay_data_chunks(replay, "bitmap.data", (uint8_t**)&qxl->bitmap.data, 0); + ssize_t size = red_replay_data_chunks(replay, "bitmap.data", (uint8_t**)&qxl->bitmap.data, 0); if (size != bitmap_size) { spice_printerr("bad image, %zu != %zu", size, bitmap_size); return NULL; @@ -466,7 +518,7 @@ static void red_replay_image_free(SpiceReplay *replay, QXLPHYSICAL p, uint32_t f free(qxl); } -static void red_replay_brush_ptr(SpiceReplay *replay, QXLBrush *qxl, uint32_t flags) +static replay_t red_replay_brush_ptr(SpiceReplay *replay, QXLBrush *qxl, uint32_t flags) { replay_fscanf(replay, "type %d\n", &qxl->type); switch (qxl->type) { @@ -478,7 +530,10 @@ static void red_replay_brush_ptr(SpiceReplay *replay, QXLBrush *qxl, uint32_t fl red_replay_point_ptr(replay, &qxl->u.pattern.pos); break; } + return REPLAY_OK; } +#define red_replay_brush_ptr(r, q, f) \ + REPLAY_CHK(red_replay_brush_ptr(r, q, f)) static void red_replay_brush_free(SpiceReplay *replay, QXLBrush *qxl, uint32_t flags) { @@ -489,27 +544,31 @@ static void red_replay_brush_free(SpiceReplay *replay, QXLBrush *qxl, uint32_t f } } -static void red_replay_qmask_ptr(SpiceReplay *replay, QXLQMask *qxl, uint32_t flags) +static replay_t red_replay_qmask_ptr(SpiceReplay *replay, QXLQMask *qxl, uint32_t flags) { int temp; replay_fscanf(replay, "flags %d\n", &temp); qxl->flags = temp; red_replay_point_ptr(replay, &qxl->pos); qxl->bitmap = QXLPHYSICAL_FROM_PTR(red_replay_image(replay, flags)); + return REPLAY_OK; } +#define red_replay_qmask_ptr(r, q, f) \ + REPLAY_CHK(red_replay_qmask_ptr(r, q, f)) static void red_replay_qmask_free(SpiceReplay *replay, QXLQMask *qxl, uint32_t flags) { red_replay_image_free(replay, qxl->bitmap, flags); } -static void red_replay_fill_ptr(SpiceReplay *replay, QXLFill *qxl, uint32_t flags) +static replay_t red_replay_fill_ptr(SpiceReplay *replay, QXLFill *qxl, uint32_t flags) { int temp; red_replay_brush_ptr(replay, &qxl->brush, flags); replay_fscanf(replay, "rop_descriptor %d\n", &temp); qxl->rop_descriptor = temp; red_replay_qmask_ptr(replay, &qxl->mask, flags); + return REPLAY_OK; } static void red_replay_fill_free(SpiceReplay *replay, QXLFill *qxl, uint32_t flags) @@ -518,7 +577,7 @@ static void red_replay_fill_free(SpiceReplay *replay, QXLFill *qxl, uint32_t fla red_replay_qmask_free(replay, &qxl->mask, flags); } -static void red_replay_opaque_ptr(SpiceReplay *replay, QXLOpaque *qxl, uint32_t flags) +static replay_t red_replay_opaque_ptr(SpiceReplay *replay, QXLOpaque *qxl, uint32_t flags) { int temp; @@ -528,6 +587,7 @@ static void red_replay_opaque_ptr(SpiceReplay *replay, QXLOpaque *qxl, uint32_t replay_fscanf(replay, "rop_descriptor %d\n", &temp); qxl->rop_descriptor = temp; replay_fscanf(replay, "scale_mode %d\n", &temp); qxl->scale_mode = temp; red_replay_qmask_ptr(replay, &qxl->mask, flags); + return REPLAY_OK; } static void red_replay_opaque_free(SpiceReplay *replay, QXLOpaque *qxl, uint32_t flags) @@ -537,7 +597,7 @@ static void red_replay_opaque_free(SpiceReplay *replay, QXLOpaque *qxl, uint32_t red_replay_qmask_free(replay, &qxl->mask, flags); } -static void red_replay_copy_ptr(SpiceReplay *replay, QXLCopy *qxl, uint32_t flags) +static replay_t red_replay_copy_ptr(SpiceReplay *replay, QXLCopy *qxl, uint32_t flags) { int temp; @@ -546,6 +606,7 @@ static void red_replay_copy_ptr(SpiceReplay *replay, QXLCopy *qxl, uint32_t flag replay_fscanf(replay, "rop_descriptor %d\n", &temp); qxl->rop_descriptor = temp; replay_fscanf(replay, "scale_mode %d\n", &temp); qxl->scale_mode = temp; red_replay_qmask_ptr(replay, &qxl->mask, flags); + return REPLAY_OK; } static void red_replay_copy_free(SpiceReplay *replay, QXLCopy *qxl, uint32_t flags) @@ -554,7 +615,7 @@ static void red_replay_copy_free(SpiceReplay *replay, QXLCopy *qxl, uint32_t fla red_replay_qmask_free(replay, &qxl->mask, flags); } -static void red_replay_blend_ptr(SpiceReplay *replay, QXLBlend *qxl, uint32_t flags) +static replay_t red_replay_blend_ptr(SpiceReplay *replay, QXLBlend *qxl, uint32_t flags) { int temp; @@ -563,6 +624,7 @@ static void red_replay_blend_ptr(SpiceReplay *replay, QXLBlend *qxl, uint32_t fl replay_fscanf(replay, "rop_descriptor %d\n", &temp); qxl->rop_descriptor = temp; replay_fscanf(replay, "scale_mode %d\n", &temp); qxl->scale_mode = temp; red_replay_qmask_ptr(replay, &qxl->mask, flags); + return REPLAY_OK; } static void red_replay_blend_free(SpiceReplay *replay, QXLBlend *qxl, uint32_t flags) @@ -571,12 +633,13 @@ static void red_replay_blend_free(SpiceReplay *replay, QXLBlend *qxl, uint32_t f red_replay_qmask_free(replay, &qxl->mask, flags); } -static void red_replay_transparent_ptr(SpiceReplay *replay, QXLTransparent *qxl, uint32_t flags) +static replay_t red_replay_transparent_ptr(SpiceReplay *replay, QXLTransparent *qxl, uint32_t flags) { qxl->src_bitmap = QXLPHYSICAL_FROM_PTR(red_replay_image(replay, flags)); red_replay_rect_ptr(replay, "src_area", &qxl->src_area); replay_fscanf(replay, "src_color %d\n", &qxl->src_color); replay_fscanf(replay, "true_color %d\n", &qxl->true_color); + return REPLAY_OK; } static void red_replay_transparent_free(SpiceReplay *replay, QXLTransparent *qxl, uint32_t flags) @@ -584,7 +647,7 @@ static void red_replay_transparent_free(SpiceReplay *replay, QXLTransparent *qxl red_replay_image_free(replay, qxl->src_bitmap, flags); } -static void red_replay_alpha_blend_ptr(SpiceReplay *replay, QXLAlphaBlend *qxl, uint32_t flags) +static replay_t red_replay_alpha_blend_ptr(SpiceReplay *replay, QXLAlphaBlend *qxl, uint32_t flags) { int temp; @@ -592,6 +655,7 @@ static void red_replay_alpha_blend_ptr(SpiceReplay *replay, QXLAlphaBlend *qxl, replay_fscanf(replay, "alpha %d\n", &temp); qxl->alpha = temp; qxl->src_bitmap = QXLPHYSICAL_FROM_PTR(red_replay_image(replay, flags)); red_replay_rect_ptr(replay, "src_area", &qxl->src_area); + return REPLAY_OK; } static void red_replay_alpha_blend_free(SpiceReplay *replay, QXLAlphaBlend *qxl, uint32_t flags) @@ -599,16 +663,17 @@ static void red_replay_alpha_blend_free(SpiceReplay *replay, QXLAlphaBlend *qxl, red_replay_image_free(replay, qxl->src_bitmap, flags); } -static void red_replay_alpha_blend_ptr_compat(SpiceReplay *replay, QXLCompatAlphaBlend *qxl, uint32_t flags) +static replay_t red_replay_alpha_blend_ptr_compat(SpiceReplay *replay, QXLCompatAlphaBlend *qxl, uint32_t flags) { int temp; replay_fscanf(replay, "alpha %d\n", &temp); qxl->alpha = temp; qxl->src_bitmap = QXLPHYSICAL_FROM_PTR(red_replay_image(replay, flags)); red_replay_rect_ptr(replay, "src_area", &qxl->src_area); + return REPLAY_OK; } -static void red_replay_rop3_ptr(SpiceReplay *replay, QXLRop3 *qxl, uint32_t flags) +static replay_t red_replay_rop3_ptr(SpiceReplay *replay, QXLRop3 *qxl, uint32_t flags) { int temp; @@ -618,6 +683,7 @@ static void red_replay_rop3_ptr(SpiceReplay *replay, QXLRop3 *qxl, uint32_t flag replay_fscanf(replay, "rop3 %d\n", &temp); qxl->rop3 = temp; replay_fscanf(replay, "scale_mode %d\n", &temp); qxl->scale_mode = temp; red_replay_qmask_ptr(replay, &qxl->mask, flags); + return REPLAY_OK; } static void red_replay_rop3_free(SpiceReplay *replay, QXLRop3 *qxl, uint32_t flags) @@ -627,7 +693,7 @@ static void red_replay_rop3_free(SpiceReplay *replay, QXLRop3 *qxl, uint32_t fla red_replay_qmask_free(replay, &qxl->mask, flags); } -static void red_replay_stroke_ptr(SpiceReplay *replay, QXLStroke *qxl, uint32_t flags) +static replay_t red_replay_stroke_ptr(SpiceReplay *replay, QXLStroke *qxl, uint32_t flags) { int temp; @@ -642,6 +708,7 @@ static void red_replay_stroke_ptr(SpiceReplay *replay, QXLStroke *qxl, uint32_t red_replay_brush_ptr(replay, &qxl->brush, flags); replay_fscanf(replay, "fore_mode %d\n", &temp); qxl->fore_mode = temp; replay_fscanf(replay, "back_mode %d\n", &temp); qxl->back_mode = temp; + return REPLAY_OK; } static void red_replay_stroke_free(SpiceReplay *replay, QXLStroke *qxl, uint32_t flags) @@ -659,17 +726,19 @@ static QXLString *red_replay_string(SpiceReplay *replay) uint32_t data_size; uint16_t length; uint16_t flags; - size_t chunk_size; + ssize_t chunk_size; QXLString *qxl = NULL; replay_fscanf(replay, "data_size %d\n", &data_size); replay_fscanf(replay, "length %d\n", &temp); length = temp; replay_fscanf(replay, "flags %d\n", &temp); flags = temp; chunk_size = red_replay_data_chunks(replay, "string", (uint8_t**)&qxl, sizeof(QXLString)); - qxl->data_size = data_size; - qxl->length = length; - qxl->flags = flags; - spice_assert(chunk_size == qxl->data_size); + if (chunk_size >= 0) { + qxl->data_size = data_size; + qxl->length = length; + qxl->flags = flags; + spice_assert(chunk_size == qxl->data_size); + } return qxl; } @@ -678,7 +747,7 @@ static void red_replay_string_free(SpiceReplay *replay, QXLString *qxl) red_replay_data_chunks_free(replay, qxl, sizeof(*qxl)); } -static void red_replay_text_ptr(SpiceReplay *replay, QXLText *qxl, uint32_t flags) +static replay_t red_replay_text_ptr(SpiceReplay *replay, QXLText *qxl, uint32_t flags) { int temp; @@ -688,6 +757,7 @@ static void red_replay_text_ptr(SpiceReplay *replay, QXLText *qxl, uint32_t flag red_replay_brush_ptr(replay, &qxl->back_brush, flags); replay_fscanf(replay, "fore_mode %d\n", &temp); qxl->fore_mode = temp; replay_fscanf(replay, "back_mode %d\n", &temp); qxl->back_mode = temp; + return REPLAY_OK; } static void red_replay_text_free(SpiceReplay *replay, QXLText *qxl, uint32_t flags) @@ -697,9 +767,10 @@ static void red_replay_text_free(SpiceReplay *replay, QXLText *qxl, uint32_t fla red_replay_brush_free(replay, &qxl->back_brush, flags); } -static void red_replay_whiteness_ptr(SpiceReplay *replay, QXLWhiteness *qxl, uint32_t flags) +static replay_t red_replay_whiteness_ptr(SpiceReplay *replay, QXLWhiteness *qxl, uint32_t flags) { red_replay_qmask_ptr(replay, &qxl->mask, flags); + return REPLAY_OK; } static void red_replay_whiteness_free(SpiceReplay *replay, QXLWhiteness *qxl, uint32_t flags) @@ -707,9 +778,10 @@ static void red_replay_whiteness_free(SpiceReplay *replay, QXLWhiteness *qxl, ui red_replay_qmask_free(replay, &qxl->mask, flags); } -static void red_replay_blackness_ptr(SpiceReplay *replay, QXLBlackness *qxl, uint32_t flags) +static replay_t red_replay_blackness_ptr(SpiceReplay *replay, QXLBlackness *qxl, uint32_t flags) { red_replay_qmask_ptr(replay, &qxl->mask, flags); + return REPLAY_OK; } static void red_replay_blackness_free(SpiceReplay *replay, QXLBlackness *qxl, uint32_t flags) @@ -717,9 +789,10 @@ static void red_replay_blackness_free(SpiceReplay *replay, QXLBlackness *qxl, ui red_replay_qmask_free(replay, &qxl->mask, flags); } -static void red_replay_invers_ptr(SpiceReplay *replay, QXLInvers *qxl, uint32_t flags) +static replay_t red_replay_invers_ptr(SpiceReplay *replay, QXLInvers *qxl, uint32_t flags) { red_replay_qmask_ptr(replay, &qxl->mask, flags); + return REPLAY_OK; } static void red_replay_invers_free(SpiceReplay *replay, QXLInvers *qxl, uint32_t flags) @@ -727,7 +800,7 @@ static void red_replay_invers_free(SpiceReplay *replay, QXLInvers *qxl, uint32_t red_replay_qmask_free(replay, &qxl->mask, flags); } -static void red_replay_clip_ptr(SpiceReplay *replay, QXLClip *qxl) +static replay_t red_replay_clip_ptr(SpiceReplay *replay, QXLClip *qxl) { replay_fscanf(replay, "type %d\n", &qxl->type); switch (qxl->type) { @@ -735,6 +808,7 @@ static void red_replay_clip_ptr(SpiceReplay *replay, QXLClip *qxl) qxl->data = QXLPHYSICAL_FROM_PTR(red_replay_clip_rects(replay)); break; } + return REPLAY_OK; } static void red_replay_clip_free(SpiceReplay *replay, QXLClip *qxl) @@ -757,7 +831,7 @@ static uint8_t *red_replay_transform(SpiceReplay *replay) return data; } -static void red_replay_composite_ptr(SpiceReplay *replay, QXLComposite *qxl, uint32_t flags) +static replay_t red_replay_composite_ptr(SpiceReplay *replay, QXLComposite *qxl, uint32_t flags) { int enabled; @@ -775,6 +849,7 @@ static void red_replay_composite_ptr(SpiceReplay *replay, QXLComposite *qxl, uin replay_fscanf(replay, "src_origin %" SCNi16 " %" SCNi16 "\n", &qxl->src_origin.x, &qxl->src_origin.y); replay_fscanf(replay, "mask_origin %" SCNi16 " %" SCNi16 "\n", &qxl->mask_origin.x, &qxl->mask_origin.y); + return REPLAY_OK; } static void red_replay_composite_free(SpiceReplay *replay, QXLComposite *qxl, uint32_t flags) @@ -788,7 +863,7 @@ static void red_replay_composite_free(SpiceReplay *replay, QXLComposite *qxl, ui static QXLDrawable *red_replay_native_drawable(SpiceReplay *replay, uint32_t flags) { - QXLDrawable *qxl = spice_malloc0(sizeof(QXLDrawable)); // TODO - this is too large usually + QXLDrawable *qxl = replay_malloc0(replay, sizeof(QXLDrawable)); // TODO - this is too large usually int i; int temp; @@ -857,7 +932,10 @@ static QXLDrawable *red_replay_native_drawable(SpiceReplay *replay, uint32_t fla spice_warn_if_reached(); break; }; - return qxl; + if (!replay->eof) + return qxl; + + return NULL; } static void red_replay_native_drawable_free(SpiceReplay *replay, QXLDrawable *qxl, uint32_t flags) @@ -919,7 +997,7 @@ static void red_replay_native_drawable_free(SpiceReplay *replay, QXLDrawable *qx static QXLCompatDrawable *red_replay_compat_drawable(SpiceReplay *replay, uint32_t flags) { int temp; - QXLCompatDrawable *qxl = spice_malloc0(sizeof(QXLCompatDrawable)); // TODO - too large usually + QXLCompatDrawable *qxl = replay_malloc0(replay, sizeof(QXLCompatDrawable)); // TODO - too large usually red_replay_rect_ptr(replay, "bbox", &qxl->bbox); red_replay_clip_ptr(replay, &qxl->clip); @@ -976,14 +1054,14 @@ static QXLCompatDrawable *red_replay_compat_drawable(SpiceReplay *replay, uint32 spice_error("%s: unknown type %d", __FUNCTION__, qxl->type); break; }; - return qxl; + if (!replay->eof) + return qxl; + + return NULL; } static QXLPHYSICAL red_replay_drawable(SpiceReplay *replay, uint32_t flags) { - if (replay->eof) { - return 0; - } replay_fscanf(replay, "drawable\n"); if (flags & QXL_COMMAND_FLAG_COMPAT) { return QXLPHYSICAL_FROM_PTR(red_replay_compat_drawable(replay, flags)); @@ -994,7 +1072,7 @@ static QXLPHYSICAL red_replay_drawable(SpiceReplay *replay, uint32_t flags) static QXLUpdateCmd *red_replay_update_cmd(SpiceReplay *replay) { - QXLUpdateCmd *qxl = spice_malloc0(sizeof(QXLUpdateCmd)); + QXLUpdateCmd *qxl = replay_malloc0(replay, sizeof(QXLUpdateCmd)); replay_fscanf(replay, "update\n"); red_replay_rect_ptr(replay, "area", &qxl->area); @@ -1039,7 +1117,7 @@ static QXLSurfaceCmd *red_replay_surface_cmd(SpiceReplay *replay) spice_printerr("mismatch %zu != %zu", size, read_size); } } else { - qxl->u.surface_create.data = QXLPHYSICAL_FROM_PTR(spice_malloc(size)); + qxl->u.surface_create.data = QXLPHYSICAL_FROM_PTR(replay_malloc(replay, size)); } qxl->surface_id = replay_id_new(replay, qxl->surface_id); break; @@ -1123,7 +1201,7 @@ static void red_replay_cursor_cmd_free(SpiceReplay *replay, QXLCursorCmd *qxl) free(qxl); } -static void replay_handle_create_primary(QXLWorker *worker, SpiceReplay *replay) +static replay_t replay_handle_create_primary(QXLWorker *worker, SpiceReplay *replay) { QXLDevSurfaceCreate surface = { 0, }; size_t size; @@ -1145,6 +1223,7 @@ static void replay_handle_create_primary(QXLWorker *worker, SpiceReplay *replay) surface.group_id = 0; surface.mem = QXLPHYSICAL_FROM_PTR(mem); worker->create_primary_surface(worker, 0, &surface); + return REPLAY_OK; } static void replay_handle_dev_input(QXLWorker *worker, SpiceReplay *replay, @@ -1185,18 +1264,16 @@ static void replay_handle_dev_input(QXLWorker *worker, SpiceReplay *replay, SPICE_GNUC_VISIBLE QXLCommandExt* spice_replay_next_cmd(SpiceReplay *replay, QXLWorker *worker) { - QXLCommandExt* cmd; + QXLCommandExt* cmd = NULL; uint64_t timestamp; int type; int what = -1; int counter; while (what != 0) { - replay_fscanf(replay, "event %d %d %d %"PRIu64"\n", &counter, - &what, &type, ×tamp); - if (replay->eof) { - return NULL; - } + if (replay_fscanf_check(replay, "event %d %d %d %"PRIu64"\n", &counter, + &what, &type, ×tamp) == REPLAY_EOF) + goto eof; if (what == 1) { replay_handle_dev_input(worker, replay, type); } @@ -1224,6 +1301,9 @@ SPICE_GNUC_VISIBLE QXLCommandExt* spice_replay_next_cmd(SpiceReplay *replay, break; } + if (replay->eof) + goto eof; + QXLReleaseInfo *info; switch (cmd->cmd.type) { case QXL_CMD_DRAW: @@ -1234,9 +1314,23 @@ SPICE_GNUC_VISIBLE QXLCommandExt* spice_replay_next_cmd(SpiceReplay *replay, info->id = (uintptr_t)cmd; } + if (replay->allocated) { + g_list_free(replay->allocated); + replay->allocated = NULL; + } + replay->counter++; return cmd; + +eof: + if (replay->allocated) { + g_list_free_full(replay->allocated, free); + replay->allocated = NULL; + } + if (cmd) + g_free(cmd); + return NULL; } SPICE_GNUC_VISIBLE void spice_replay_free_cmd(SpiceReplay *replay, QXLCommandExt *cmd) @@ -1305,6 +1399,7 @@ SpiceReplay *spice_replay_new(FILE *file, int nsurfaces) replay->id_map_inv = g_array_new(FALSE, FALSE, sizeof(uint32_t)); replay->id_free = g_array_new(FALSE, FALSE, sizeof(uint32_t)); replay->nsurfaces = nsurfaces; + replay->allocated = g_list_alloc(); /* reserve id 0 */ replay_id_new(replay, 0); @@ -1316,6 +1411,7 @@ SPICE_GNUC_VISIBLE void spice_replay_free(SpiceReplay *replay) { spice_return_if_fail(replay != NULL); + g_list_free_full(replay->allocated, free); pthread_mutex_destroy(&replay->mutex); pthread_cond_destroy(&replay->cond); g_array_free(replay->id_map, TRUE); -- 2.7.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel