|
|
6e1750 |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
6e1750 |
From: Frediano Ziglio <fziglio@redhat.com>
|
|
|
6e1750 |
Date: Mon, 29 Feb 2016 14:24:03 +0000
|
|
|
6e1750 |
Subject: [PATCH] create a function to validate surface parameters
|
|
|
6e1750 |
|
|
|
6e1750 |
Make possible to reuse it outside red-parse-qxl.c
|
|
|
6e1750 |
|
|
|
6e1750 |
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
|
|
|
6e1750 |
---
|
|
|
6e1750 |
server/red_parse_qxl.c | 50 ++++++++++++++++++++++++++++++++------------------
|
|
|
6e1750 |
server/red_parse_qxl.h | 5 +++++
|
|
|
6e1750 |
2 files changed, 37 insertions(+), 18 deletions(-)
|
|
|
6e1750 |
|
|
|
6e1750 |
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
|
|
|
6e1750 |
index bd0c408..7dc6a4d 100644
|
|
|
6e1750 |
--- a/server/red_parse_qxl.c
|
|
|
6e1750 |
+++ b/server/red_parse_qxl.c
|
|
|
6e1750 |
@@ -19,7 +19,6 @@
|
|
|
6e1750 |
#include <config.h>
|
|
|
6e1750 |
#endif
|
|
|
6e1750 |
|
|
|
6e1750 |
-#include <stdbool.h>
|
|
|
6e1750 |
#include <inttypes.h>
|
|
|
6e1750 |
#include <glib.h>
|
|
|
6e1750 |
#include "common/lz_common.h"
|
|
|
6e1750 |
@@ -1306,13 +1305,41 @@ static unsigned int surface_format_to_bpp(uint32_t format)
|
|
|
6e1750 |
return 0;
|
|
|
6e1750 |
}
|
|
|
6e1750 |
|
|
|
6e1750 |
+bool red_validate_surface(uint32_t width, uint32_t height,
|
|
|
6e1750 |
+ int32_t stride, uint32_t format)
|
|
|
6e1750 |
+{
|
|
|
6e1750 |
+ unsigned int bpp;
|
|
|
6e1750 |
+ uint64_t size;
|
|
|
6e1750 |
+
|
|
|
6e1750 |
+ bpp = surface_format_to_bpp(format);
|
|
|
6e1750 |
+
|
|
|
6e1750 |
+ /* check if format is valid */
|
|
|
6e1750 |
+ if (!bpp) {
|
|
|
6e1750 |
+ return false;
|
|
|
6e1750 |
+ }
|
|
|
6e1750 |
+
|
|
|
6e1750 |
+ /* check stride is larger than required bytes */
|
|
|
6e1750 |
+ size = ((uint64_t) width * bpp + 7u) / 8u;
|
|
|
6e1750 |
+ /* the uint32_t conversion is here to avoid problems with -2^31 value */
|
|
|
6e1750 |
+ if (stride == G_MININT32 || size > (uint32_t) abs(stride)) {
|
|
|
6e1750 |
+ return false;
|
|
|
6e1750 |
+ }
|
|
|
6e1750 |
+
|
|
|
6e1750 |
+ /* the multiplication can overflow, also abs(-2^31) may return a negative value */
|
|
|
6e1750 |
+ size = (uint64_t) height * abs(stride);
|
|
|
6e1750 |
+ if (size > MAX_DATA_CHUNK) {
|
|
|
6e1750 |
+ return false;
|
|
|
6e1750 |
+ }
|
|
|
6e1750 |
+
|
|
|
6e1750 |
+ return true;
|
|
|
6e1750 |
+}
|
|
|
6e1750 |
+
|
|
|
6e1750 |
int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
|
|
|
6e1750 |
RedSurfaceCmd *red, QXLPHYSICAL addr)
|
|
|
6e1750 |
{
|
|
|
6e1750 |
QXLSurfaceCmd *qxl;
|
|
|
6e1750 |
uint64_t size;
|
|
|
6e1750 |
int error;
|
|
|
6e1750 |
- unsigned int bpp;
|
|
|
6e1750 |
|
|
|
6e1750 |
qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id,
|
|
|
6e1750 |
&error);
|
|
|
6e1750 |
@@ -1331,26 +1358,13 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
|
|
|
6e1750 |
red->u.surface_create.width = qxl->u.surface_create.width;
|
|
|
6e1750 |
red->u.surface_create.height = qxl->u.surface_create.height;
|
|
|
6e1750 |
red->u.surface_create.stride = qxl->u.surface_create.stride;
|
|
|
6e1750 |
- bpp = surface_format_to_bpp(red->u.surface_create.format);
|
|
|
6e1750 |
|
|
|
6e1750 |
- /* check if format is valid */
|
|
|
6e1750 |
- if (!bpp) {
|
|
|
6e1750 |
+ if (!red_validate_surface(red->u.surface_create.width, red->u.surface_create.height,
|
|
|
6e1750 |
+ red->u.surface_create.stride, red->u.surface_create.format)) {
|
|
|
6e1750 |
return 1;
|
|
|
6e1750 |
}
|
|
|
6e1750 |
|
|
|
6e1750 |
- /* check stride is larger than required bytes */
|
|
|
6e1750 |
- size = ((uint64_t) red->u.surface_create.width * bpp + 7u) / 8u;
|
|
|
6e1750 |
- /* the uint32_t conversion is here to avoid problems with -2^31 value */
|
|
|
6e1750 |
- if (red->u.surface_create.stride == G_MININT32
|
|
|
6e1750 |
- || size > (uint32_t) abs(red->u.surface_create.stride)) {
|
|
|
6e1750 |
- return 1;
|
|
|
6e1750 |
- }
|
|
|
6e1750 |
-
|
|
|
6e1750 |
- /* the multiplication can overflow, also abs(-2^31) may return a negative value */
|
|
|
6e1750 |
- size = (uint64_t) red->u.surface_create.height * abs(red->u.surface_create.stride);
|
|
|
6e1750 |
- if (size > MAX_DATA_CHUNK) {
|
|
|
6e1750 |
- return 1;
|
|
|
6e1750 |
- }
|
|
|
6e1750 |
+ size = red->u.surface_create.height * abs(red->u.surface_create.stride);
|
|
|
6e1750 |
red->u.surface_create.data =
|
|
|
6e1750 |
(uint8_t*)get_virt(slots, qxl->u.surface_create.data, size, group_id, &error);
|
|
|
6e1750 |
if (error) {
|
|
|
6e1750 |
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
|
|
|
6e1750 |
index 3adc9fa..e18d8d0 100644
|
|
|
6e1750 |
--- a/server/red_parse_qxl.h
|
|
|
6e1750 |
+++ b/server/red_parse_qxl.h
|
|
|
6e1750 |
@@ -19,6 +19,8 @@
|
|
|
6e1750 |
#ifndef RED_ABI_TRANSLATE_H
|
|
|
6e1750 |
#define RED_ABI_TRANSLATE_H
|
|
|
6e1750 |
|
|
|
6e1750 |
+#include <stdbool.h>
|
|
|
6e1750 |
+
|
|
|
6e1750 |
#include <spice/qxl_dev.h>
|
|
|
6e1750 |
#include "red_common.h"
|
|
|
6e1750 |
#include "red_memslots.h"
|
|
|
6e1750 |
@@ -128,6 +130,9 @@ int red_get_message(RedMemSlotInfo *slots, int group_id,
|
|
|
6e1750 |
RedMessage *red, QXLPHYSICAL addr);
|
|
|
6e1750 |
void red_put_message(RedMessage *red);
|
|
|
6e1750 |
|
|
|
6e1750 |
+bool red_validate_surface(uint32_t width, uint32_t height,
|
|
|
6e1750 |
+ int32_t stride, uint32_t format);
|
|
|
6e1750 |
+
|
|
|
6e1750 |
int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
|
|
|
6e1750 |
RedSurfaceCmd *red, QXLPHYSICAL addr);
|
|
|
6e1750 |
void red_put_surface_cmd(RedSurfaceCmd *red);
|