diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2015-09-08 16:02:59 +0100 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2015-10-06 11:11:10 +0100 |
commit | 1eb93baa3c594e1214b1c92bbad8a06e9c7e2d12 (patch) | |
tree | 0009d6b20ebbc24deeb7df5454a304df4601e0cd /server/red_parse_qxl.c | |
parent | ac5f64a80ae637742ed95fd6c98f66281b3e15c6 (diff) | |
download | spice-1eb93baa3c594e1214b1c92bbad8a06e9c7e2d12.tar.gz spice-1eb93baa3c594e1214b1c92bbad8a06e9c7e2d12.tar.xz spice-1eb93baa3c594e1214b1c92bbad8a06e9c7e2d12.zip |
Check properly surface to be created
Check format is valid.
Check stride is at least the size of required bytes for a row.
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
Diffstat (limited to 'server/red_parse_qxl.c')
-rw-r--r-- | server/red_parse_qxl.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c index be900687..bdd59175 100644 --- a/server/red_parse_qxl.c +++ b/server/red_parse_qxl.c @@ -1216,12 +1216,30 @@ void red_put_message(RedMessage *red) /* nothing yet */ } +static unsigned int surface_format_to_bpp(uint32_t format) +{ + switch (format) { + case SPICE_SURFACE_FMT_1_A: + return 1; + case SPICE_SURFACE_FMT_8_A: + return 8; + case SPICE_SURFACE_FMT_16_555: + case SPICE_SURFACE_FMT_16_565: + return 16; + case SPICE_SURFACE_FMT_32_xRGB: + case SPICE_SURFACE_FMT_32_ARGB: + return 32; + } + return 0; +} + int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id, RedSurfaceCmd *red, QXLPHYSICAL addr) { QXLSurfaceCmd *qxl; uint64_t size; int error; + unsigned int bpp; qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id, &error); @@ -1240,9 +1258,24 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id, red->u.surface_create.width = qxl->u.surface_create.width; red->u.surface_create.height = qxl->u.surface_create.height; red->u.surface_create.stride = qxl->u.surface_create.stride; + bpp = surface_format_to_bpp(red->u.surface_create.format); + + /* check if format is valid */ + if (!bpp) { + return 1; + } + + /* check stride is larger than required bytes */ + size = ((uint64_t) red->u.surface_create.width * bpp + 7u) / 8u; + /* the uint32_t conversion is here to avoid problems with -2^31 value */ + if (red->u.surface_create.stride == G_MININT32 + || size > (uint32_t) abs(red->u.surface_create.stride)) { + return 1; + } + /* the multiplication can overflow, also abs(-2^31) may return a negative value */ size = (uint64_t) red->u.surface_create.height * abs(red->u.surface_create.stride); - if (size > MAX_DATA_CHUNK || red->u.surface_create.stride == G_MININT32) { + if (size > MAX_DATA_CHUNK) { return 1; } red->u.surface_create.data = |