summaryrefslogtreecommitdiffstats
path: root/server/red_parse_qxl.c
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2015-09-08 16:02:59 +0100
committerFrediano Ziglio <fziglio@redhat.com>2015-10-06 11:11:10 +0100
commit1eb93baa3c594e1214b1c92bbad8a06e9c7e2d12 (patch)
tree0009d6b20ebbc24deeb7df5454a304df4601e0cd /server/red_parse_qxl.c
parentac5f64a80ae637742ed95fd6c98f66281b3e15c6 (diff)
downloadspice-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.c35
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 =