virtio_gpu_ctrl_response(g, cmd, &edid.hdr, sizeof(edid));
}
-static uint32_t calc_image_hostmem(pixman_format_code_t pformat,
- uint32_t width, uint32_t height)
+static bool calc_image_hostmem(pixman_format_code_t pformat,
+ uint32_t width, uint32_t height,
+ uint32_t *hostmem)
{
- /* Copied from pixman/pixman-bits-image.c, skip integer overflow check.
- * pixman_image_create_bits will fail in case it overflow.
- */
+ uint64_t bpp = PIXMAN_FORMAT_BPP(pformat);
+ uint64_t stride = (((uint64_t)width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
+ uint64_t size = (uint64_t)height * stride;
- int bpp = PIXMAN_FORMAT_BPP(pformat);
- int stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
- return height * stride;
+ if (size > UINT32_MAX) {
+ return false;
+ }
+
+ *hostmem = size;
+ return true;
}
static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
pixman_format_code_t pformat;
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_create_2d c2d;
+ uint32_t hostmem;
VIRTIO_GPU_FILL_CMD(c2d);
virtio_gpu_bswap_32(&c2d, sizeof(c2d));
return;
}
- res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height);
+ if (!calc_image_hostmem(pformat, c2d.width, c2d.height, &hostmem)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: image dimensions overflow\n",
+ __func__);
+ goto end;
+ }
+ res->hostmem = hostmem;
if (res->hostmem + g->hostmem < g->conf_max_hostmem) {
if (!qemu_pixman_image_new_shareable(
&res->image,
VirtIOGPU *g = opaque;
Error *err = NULL;
struct virtio_gpu_simple_resource *res;
- uint32_t resource_id, pformat;
+ uint32_t resource_id, pformat, hostmem;
int i, ret;
g->hostmem = 0;
return -EINVAL;
}
- res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
+ if (!calc_image_hostmem(pformat, res->width, res->height, &hostmem)) {
+ g_free(res);
+ return -EINVAL;
+ }
+ res->hostmem = hostmem;
if (!qemu_pixman_image_new_shareable(&res->image,
&res->share_handle,
"virtio-gpu res",