summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2011-01-04 21:58:24 +0100
committerAurelien Jarno <aurelien@aurel32.net>2011-01-04 21:58:24 +0100
commit92d675d1c1f23f3617e24b63c825074a1d1da44b (patch)
treeed33f1f49aecd88b1182f766daab6cf0345f334d /hw
parent9ae19b657ee20f4d03bdca8dbf367b932801ac93 (diff)
downloadqemu-92d675d1c1f23f3617e24b63c825074a1d1da44b.zip
cirrus_vga: fix division by 0 for color expansion rop
Commit d85d0d3883f5a567fa2969a0396e42e0a662b3fa introduces a regression with Windows ME that leads to a division by 0 and a crash. It uses the color expansion rop with the source pitch set to 0. This is something allowed, as the manual explicitely says "When the source of color-expand data is display memory, the source pitch is ignored.". This patch fixes this regression by computing sx, sy and others variables only if they are going to be used later, that is for a plain copy ROP. It basically consists in moving code. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'hw')
-rw-r--r--hw/cirrus_vga.c65
1 files changed, 33 insertions, 32 deletions
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 4f5040cf4b..199136ce7d 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -675,43 +675,44 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
{
int sx, sy;
int dx, dy;
- int width, height;
int depth;
int notify = 0;
- depth = s->vga.get_bpp(&s->vga) / 8;
- s->vga.get_resolution(&s->vga, &width, &height);
-
- /* extra x, y */
- sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
- sy = (src / ABS(s->cirrus_blt_srcpitch));
- dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
- dy = (dst / ABS(s->cirrus_blt_dstpitch));
-
- /* normalize width */
- w /= depth;
-
- /* if we're doing a backward copy, we have to adjust
- our x/y to be the upper left corner (instead of the lower
- right corner) */
- if (s->cirrus_blt_dstpitch < 0) {
- sx -= (s->cirrus_blt_width / depth) - 1;
- dx -= (s->cirrus_blt_width / depth) - 1;
- sy -= s->cirrus_blt_height - 1;
- dy -= s->cirrus_blt_height - 1;
- }
+ /* make sure to only copy if it's a plain copy ROP */
+ if (*s->cirrus_rop == cirrus_bitblt_rop_fwd_src ||
+ *s->cirrus_rop == cirrus_bitblt_rop_bkwd_src) {
- /* are we in the visible portion of memory? */
- if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
- (sx + w) <= width && (sy + h) <= height &&
- (dx + w) <= width && (dy + h) <= height) {
- notify = 1;
- }
+ int width, height;
+
+ depth = s->vga.get_bpp(&s->vga) / 8;
+ s->vga.get_resolution(&s->vga, &width, &height);
+
+ /* extra x, y */
+ sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
+ sy = (src / ABS(s->cirrus_blt_srcpitch));
+ dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
+ dy = (dst / ABS(s->cirrus_blt_dstpitch));
- /* make to sure only copy if it's a plain copy ROP */
- if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
- *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
- notify = 0;
+ /* normalize width */
+ w /= depth;
+
+ /* if we're doing a backward copy, we have to adjust
+ our x/y to be the upper left corner (instead of the lower
+ right corner) */
+ if (s->cirrus_blt_dstpitch < 0) {
+ sx -= (s->cirrus_blt_width / depth) - 1;
+ dx -= (s->cirrus_blt_width / depth) - 1;
+ sy -= s->cirrus_blt_height - 1;
+ dy -= s->cirrus_blt_height - 1;
+ }
+
+ /* are we in the visible portion of memory? */
+ if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
+ (sx + w) <= width && (sy + h) <= height &&
+ (dx + w) <= width && (dy + h) <= height) {
+ notify = 1;
+ }
+ }
/* we have to flush all pending changes so that the copy
is generated at the appropriate moment in time */