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>
This commit is contained in:
Frediano Ziglio 2015-09-08 16:02:59 +01:00
parent ac5f64a80a
commit 1eb93baa3c

View File

@ -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 =