[xorg-x11-server] crtc confine, pointer barriers, vbe malloc fix

Adam Tkac atkac at fedoraproject.org
Tue Mar 22 10:01:40 UTC 2011


commit dbc91b7571ef2a08dbd4448366a5e5239df52299
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Mar 17 14:15:32 2011 -0400

    crtc confine, pointer barriers, vbe malloc fix

 xorg-x11-server.spec                |   10 +-
 xserver-1.10-pointer-barriers.patch | 1054 +++++++++++++++++++++++++++++++++++
 xserver-1.10-vbe-malloc.patch       |   43 ++
 3 files changed, 1106 insertions(+), 1 deletions(-)
---
diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec
index 75b4fc6..c57d1df 100644
--- a/xorg-x11-server.spec
+++ b/xorg-x11-server.spec
@@ -30,7 +30,7 @@
 Summary:   X.Org X11 X server
 Name:      xorg-x11-server
 Version:   1.10.0
-Release:   3%{?gitdate:.%{gitdate}}%{dist}
+Release:   4%{?gitdate:.%{gitdate}}%{dist}
 URL:       http://www.x.org
 License:   MIT
 Group:     User Interface/X
@@ -85,6 +85,9 @@ Patch6053: xserver-1.8-disable-vboxvideo.patch
 # misc
 Patch7005: xserver-1.9.0-qxl-fallback.patch
 
+Patch7006: xserver-1.10-pointer-barriers.patch
+Patch7007: xserver-1.10-vbe-malloc.patch
+
 %define moduledir	%{_libdir}/xorg/modules
 %define drimoduledir	%{_libdir}/dri
 %define sdkdir		%{_includedir}/xorg
@@ -545,6 +548,11 @@ rm -rf $RPM_BUILD_ROOT
 %{xserver_source_dir}
 
 %changelog
+* Thu Mar 17 2011 Adam Jackson <ajax at redhat.com> 1.10.0-4
+- xserver-1.10-pointer-barriers.patch: Backport CRTC confinement from master
+  and pointer barriers from the development tree for same.
+- xserver-1.10-vbe-malloc.patch: Fix a buffer overrun in the VBE code.
+
 * Fri Mar 11 2011 Peter Hutterer <peter.hutterer at redhat.com> 1.10.0-3
 - Add Xen virtual pointer quirk to 10-quirks.conf (#523914, #679699)
 
diff --git a/xserver-1.10-pointer-barriers.patch b/xserver-1.10-pointer-barriers.patch
new file mode 100644
index 0000000..d3083a9
--- /dev/null
+++ b/xserver-1.10-pointer-barriers.patch
@@ -0,0 +1,1054 @@
+From 14f1112bec18ccece8e732fe6c200a56546230c7 Mon Sep 17 00:00:00 2001
+From: Adam Jackson <ajax at redhat.com>
+Date: Thu, 17 Mar 2011 13:56:17 -0400
+Subject: [PATCH] CRTC confine and pointer barriers
+
+---
+ dix/events.c                |    7 +
+ dix/getevents.c             |   12 +-
+ include/dix.h               |    1 +
+ include/protocol-versions.h |    2 +-
+ mi/mipointer.c              |   16 ++-
+ mi/mipointer.h              |    6 +
+ randr/randr.c               |    2 +
+ randr/randrstr.h            |    4 +
+ randr/rrcrtc.c              |  155 ++++++++++++++++
+ test/Makefile.am            |    4 +-
+ xfixes/cursor.c             |  408 ++++++++++++++++++++++++++++++++++++++++++-
+ xfixes/xfixes.c             |   24 ++-
+ xfixes/xfixes.h             |   17 ++
+ xfixes/xfixesint.h          |   16 ++
+ 14 files changed, 658 insertions(+), 16 deletions(-)
+
+diff --git a/dix/events.c b/dix/events.c
+index 07f8b05..d2be84f 100644
+--- a/dix/events.c
++++ b/dix/events.c
+@@ -328,6 +328,13 @@ IsMaster(DeviceIntPtr dev)
+     return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
+ }
+ 
++Bool
++IsFloating(DeviceIntPtr dev)
++{
++    return GetMaster(dev, MASTER_KEYBOARD) == NULL;
++}
++
++
+ /**
+  * Max event opcode.
+  */
+diff --git a/dix/getevents.c b/dix/getevents.c
+index 794df42..c66e516 100644
+--- a/dix/getevents.c
++++ b/dix/getevents.c
+@@ -812,7 +812,11 @@ accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
+  * miPointerSetPosition() and then scale back into device coordinates (if
+  * needed). miPSP will change x/y if the screen was crossed.
+  *
++ * The coordinates provided are always absolute. The parameter mode whether
++ * it was relative or absolute movement that landed us at those coordinates.
++ *
+  * @param dev The device to be moved.
++ * @param mode Movement mode (Absolute or Relative)
+  * @param x Pointer to current x-axis value, may be modified.
+  * @param y Pointer to current y-axis value, may be modified.
+  * @param x_frac Fractional part of current x-axis value, may be modified.
+@@ -824,7 +828,8 @@ accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
+  * @param screeny_frac Fractional part of screen y coordinate, as above.
+  */
+ static void
+-positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
++positionSprite(DeviceIntPtr dev, int mode,
++               int *x, int *y, float x_frac, float y_frac,
+                ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
+ {
+     int old_screenx, old_screeny;
+@@ -863,7 +868,7 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
+     old_screeny = *screeny;
+     /* This takes care of crossing screens for us, as well as clipping
+      * to the current screen. */
+-    miPointerSetPosition(dev, screenx, screeny);
++    _miPointerSetPosition(dev, mode, screenx, screeny);
+ 
+     if (dev->u.master) {
+         dev->u.master->last.valuators[0] = *screenx;
+@@ -1193,7 +1198,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
+ 
+     set_raw_valuators(raw, &mask, raw->valuators.data);
+ 
+-    positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
++    positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
++                   &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
+     updateHistory(pDev, &mask, ms);
+ 
+     /* Update the valuators with the true value sent to the client*/
+diff --git a/include/dix.h b/include/dix.h
+index 12e4b59..3f99098 100644
+--- a/include/dix.h
++++ b/include/dix.h
+@@ -570,6 +570,7 @@ extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
+ extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
+ extern Bool IsPointerEvent(InternalEvent *event);
+ extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
++extern _X_EXPORT Bool IsFloating(DeviceIntPtr dev);
+ 
+ extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
+ extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what);
+diff --git a/include/protocol-versions.h b/include/protocol-versions.h
+index 1d33bdd..1dc66ad 100644
+--- a/include/protocol-versions.h
++++ b/include/protocol-versions.h
+@@ -126,7 +126,7 @@
+ #define SERVER_XF86VIDMODE_MINOR_VERSION	2
+ 
+ /* Fixes */
+-#define SERVER_XFIXES_MAJOR_VERSION		4
++#define SERVER_XFIXES_MAJOR_VERSION		5
+ #define SERVER_XFIXES_MINOR_VERSION		0
+ 
+ /* X Input */
+diff --git a/mi/mipointer.c b/mi/mipointer.c
+index 554397a..85f1949 100644
+--- a/mi/mipointer.c
++++ b/mi/mipointer.c
+@@ -229,6 +229,10 @@ miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
+     SetupScreen (pScreen);
+ 
+     GenerateEvent = generateEvent;
++
++    if (pScreen->ConstrainCursorHarder)
++	pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
++
+     /* device dependent - must pend signal and call miPointerWarpCursor */
+     (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
+     if (!generateEvent)
+@@ -484,7 +488,7 @@ miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
+ }
+ 
+ void
+-miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
++_miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
+ {
+     miPointerScreenPtr	pScreenPriv;
+     ScreenPtr		pScreen;
+@@ -529,6 +533,9 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
+     if (*y >= pPointer->limits.y2)
+ 	*y = pPointer->limits.y2 - 1;
+ 
++    if (pScreen->ConstrainCursorHarder)
++       pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y);
++
+     if (pPointer->x == *x && pPointer->y == *y && 
+             pPointer->pScreen == pScreen) 
+         return;
+@@ -536,6 +543,13 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
+     miPointerMoveNoEvent(pDev, pScreen, *x, *y);
+ }
+ 
++/* ABI hack */
++void
++miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
++{
++    _miPointerSetPosition(pDev, Absolute, x, y);
++}
++
+ void
+ miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
+ {
+diff --git a/mi/mipointer.h b/mi/mipointer.h
+index 3c86110..6b6010c 100644
+--- a/mi/mipointer.h
++++ b/mi/mipointer.h
+@@ -131,6 +131,12 @@ extern _X_EXPORT void miPointerGetPosition(
+ 
+ /* Moves the cursor to the specified position.  May clip the co-ordinates:
+  * x and y are modified in-place. */
++extern _X_EXPORT void _miPointerSetPosition(
++    DeviceIntPtr pDev,
++    int mode,
++    int *x,
++    int *y);
++
+ extern _X_EXPORT void miPointerSetPosition(
+     DeviceIntPtr pDev,
+     int *x,
+diff --git a/randr/randr.c b/randr/randr.c
+index 6077705..d337129 100644
+--- a/randr/randr.c
++++ b/randr/randr.c
+@@ -270,6 +270,8 @@ Bool RRScreenInit(ScreenPtr pScreen)
+     
+     wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
+ 
++    pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
++
+     pScrPriv->numOutputs = 0;
+     pScrPriv->outputs = NULL;
+     pScrPriv->numCrtcs = 0;
+diff --git a/randr/randrstr.h b/randr/randrstr.h
+index 7ea6080..d8dd37d 100644
+--- a/randr/randrstr.h
++++ b/randr/randrstr.h
+@@ -297,6 +297,7 @@ typedef struct _rrScrPriv {
+     int			    rate;
+     int			    size;
+ #endif
++    Bool                   discontiguous;
+ } rrScrPrivRec, *rrScrPrivPtr;
+ 
+ extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
+@@ -700,6 +701,9 @@ ProcRRGetPanning (ClientPtr client);
+ int
+ ProcRRSetPanning (ClientPtr client);
+ 
++void
++RRConstrainCursorHarder (DeviceIntPtr, ScreenPtr, int, int *, int *);
++
+ /* rrdispatch.c */
+ extern _X_EXPORT Bool
+ RRClientKnowsRates (ClientPtr	pClient);
+diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
+index 98206a2..d4d8f2a 100644
+--- a/randr/rrcrtc.c
++++ b/randr/rrcrtc.c
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright © 2006 Keith Packard
++ * Copyright 2010 Red Hat, Inc
+  *
+  * Permission to use, copy, modify, distribute, and sell this software and its
+  * documentation for any purpose is hereby granted without fee, provided that
+@@ -22,6 +23,7 @@
+ 
+ #include "randrstr.h"
+ #include "swaprep.h"
++#include "mipointer.h"
+ 
+ RESTYPE	RRCrtcType;
+ 
+@@ -292,6 +294,92 @@ RRCrtcPendingProperties (RRCrtcPtr crtc)
+     return FALSE;
+ }
+ 
++static void
++crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom)
++{
++    *left = crtc->x;
++    *top = crtc->y;
++
++    switch (crtc->rotation) {
++    case RR_Rotate_0:
++    case RR_Rotate_180:
++    default:
++       *right = crtc->x + crtc->mode->mode.width;
++       *bottom = crtc->y + crtc->mode->mode.height;
++       return;
++    case RR_Rotate_90:
++    case RR_Rotate_270:
++       *right = crtc->x + crtc->mode->mode.height;
++       *bottom = crtc->y + crtc->mode->mode.width;
++       return;
++    }
++}
++
++/* overlapping counts as adjacent */
++static Bool
++crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b)
++{
++    /* left, right, top, bottom... */
++    int al, ar, at, ab;
++    int bl, br, bt, bb;
++    int cl, cr, ct, cb; /* the overlap, if any */
++
++    crtc_bounds(a, &al, &ar, &at, &ab);
++    crtc_bounds(b, &bl, &br, &bt, &bb);
++
++    cl = max(al, bl);
++    cr = min(ar, br);
++    ct = max(at, bt);
++    cb = min(ab, bb);
++
++    return (cl <= cr) && (ct <= cb);
++}
++
++/* Depth-first search and mark all CRTCs reachable from cur */
++static void
++mark_crtcs (rrScrPrivPtr pScrPriv, int *reachable, int cur)
++{
++    int i;
++    reachable[cur] = TRUE;
++    for (i = 0; i < pScrPriv->numCrtcs; ++i) {
++        if (reachable[i] || !pScrPriv->crtcs[i]->mode)
++            continue;
++        if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i]))
++            mark_crtcs(pScrPriv, reachable, i);
++    }
++}
++
++static void
++RRComputeContiguity (ScreenPtr pScreen)
++{
++    rrScrPriv(pScreen);
++    Bool discontiguous = TRUE;
++    int i, n = pScrPriv->numCrtcs;
++
++    int *reachable = calloc(n, sizeof(int));
++    if (!reachable)
++        goto out;
++
++    /* Find first enabled CRTC and start search for reachable CRTCs from it */
++    for (i = 0; i < n; ++i) {
++        if (pScrPriv->crtcs[i]->mode) {
++            mark_crtcs(pScrPriv, reachable, i);
++            break;
++        }
++    }
++
++    /* Check that all enabled CRTCs were marked as reachable */
++    for (i = 0; i < n; ++i)
++        if (pScrPriv->crtcs[i]->mode && !reachable[i])
++            goto out;
++
++    discontiguous = FALSE;
++
++out:
++    free(reachable);
++    pScrPriv->discontiguous = discontiguous;
++}
++
+ /*
+  * Request that the Crtc be reconfigured
+  */
+@@ -306,6 +394,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
+ {
+     ScreenPtr	pScreen = crtc->pScreen;
+     Bool	ret = FALSE;
++    Bool	recompute = TRUE;
+     rrScrPriv(pScreen);
+ 
+     /* See if nothing changed */
+@@ -318,6 +407,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
+ 	!RRCrtcPendingProperties (crtc) &&
+ 	!RRCrtcPendingTransform (crtc))
+     {
++	recompute = FALSE;
+ 	ret = TRUE;
+     }
+     else
+@@ -381,6 +471,10 @@ RRCrtcSet (RRCrtcPtr    crtc,
+ 		RRPostPendingProperties (outputs[o]);
+ 	}
+     }
++
++    if (recompute)
++       RRComputeContiguity(pScreen);
++
+     return ret;
+ }
+ 
+@@ -1349,3 +1443,64 @@ ProcRRGetCrtcTransform (ClientPtr client)
+     free(reply);
+     return Success;
+ }
++
++void
++RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, int *y)
++{
++    rrScrPriv (pScreen);
++    int i;
++
++    /* intentional dead space -> let it float */
++    if (pScrPriv->discontiguous)
++       return;
++
++    /* if we're moving inside a crtc, we're fine */
++    for (i = 0; i < pScrPriv->numCrtcs; i++) {
++       RRCrtcPtr crtc = pScrPriv->crtcs[i];
++
++       int left, right, top, bottom;
++
++       if (!crtc->mode)
++           continue;
++
++       crtc_bounds(crtc, &left, &right, &top, &bottom);
++
++       if ((*x >= left) && (*x <= right) && (*y >= top) && (*y <= bottom))
++           return;
++    }
++
++    /* if we're trying to escape, clamp to the CRTC we're coming from */
++    for (i = 0; i < pScrPriv->numCrtcs; i++) {
++       RRCrtcPtr crtc = pScrPriv->crtcs[i];
++       int nx, ny;
++       int left, right, top, bottom;
++
++       if (!crtc->mode)
++           continue;
++
++       crtc_bounds(crtc, &left, &right, &top, &bottom);
++       miPointerGetPosition(pDev, &nx, &ny);
++
++       if ((nx >= left) && (nx <= right) && (ny >= top) && (ny <= bottom)) {
++           if ((*x <= left) || (*x >= right)) {
++               int dx = *x - nx;
++
++               if (dx > 0)
++                   *x = right;
++               else if (dx < 0)
++                   *x = left;
++           }
++
++           if ((*y <= top) || (*y >= bottom)) {
++               int dy = *y - ny;
++
++               if (dy > 0)
++                   *y = bottom;
++               else if (dy < 0)
++                   *y = top;
++           }
++
++           return;
++       }
++    }
++}
+diff --git a/test/Makefile.am b/test/Makefile.am
+index 456221e..ccdb859 100644
+--- a/test/Makefile.am
++++ b/test/Makefile.am
+@@ -1,6 +1,6 @@
+ if UNITTESTS
+ SUBDIRS= . xi2
+-check_PROGRAMS = xkb input xtest
++check_PROGRAMS = xkb input xtest list fixes
+ check_LTLIBRARIES = libxservertest.la
+ 
+ TESTS=$(check_PROGRAMS)
+@@ -16,6 +16,8 @@ endif
+ xkb_LDADD=$(TEST_LDADD)
+ input_LDADD=$(TEST_LDADD)
+ xtest_LDADD=$(TEST_LDADD)
++list_LDADD=$(TEST_LDADD)
++fixes_LDADD=$(TEST_LDADD)
+ 
+ libxservertest_la_LIBADD = \
+             $(XSERVER_LIBS) \
+diff --git a/xfixes/cursor.c b/xfixes/cursor.c
+index fb608f6..5c55c95 100644
+--- a/xfixes/cursor.c
++++ b/xfixes/cursor.c
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright 2010 Red Hat, Inc.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the "Software"),
+@@ -50,13 +51,16 @@
+ #include "cursorstr.h"
+ #include "dixevents.h"
+ #include "servermd.h"
++#include "mipointer.h"
+ #include "inputstr.h"
+ #include "windowstr.h"
+ #include "xace.h"
++#include "list.h"
+ 
+ static RESTYPE		CursorClientType;
+ static RESTYPE		CursorHideCountType;
+ static RESTYPE		CursorWindowType;
++RESTYPE			PointerBarrierType;
+ static CursorPtr	CursorCurrent[MAXDEVICES];
+ 
+ static DevPrivateKeyRec CursorScreenPrivateKeyRec;
+@@ -107,6 +111,14 @@ typedef struct _CursorHideCountRec {
+     XID			 resource;
+ } CursorHideCountRec;
+ 
++typedef struct PointerBarrierClient *PointerBarrierClientPtr;
++
++struct PointerBarrierClient {
++    ScreenPtr screen;
++    struct PointerBarrier barrier;
++    struct list entry;
++};
++
+ /*
+  * Wrap DisplayCursor to catch cursor change events
+  */
+@@ -114,7 +126,9 @@ typedef struct _CursorHideCountRec {
+ typedef struct _CursorScreen {
+     DisplayCursorProcPtr	DisplayCursor;
+     CloseScreenProcPtr		CloseScreen;
++    ConstrainCursorHarderProcPtr ConstrainCursorHarder;
+     CursorHideCountPtr          pCursorHideCounts;
++    struct list                 barriers;
+ } CursorScreenRec, *CursorScreenPtr;
+ 
+ #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
+@@ -184,9 +198,11 @@ CursorCloseScreen (int index, ScreenPtr pScreen)
+     Bool		ret;
+     CloseScreenProcPtr	close_proc;
+     DisplayCursorProcPtr display_proc;
++    ConstrainCursorHarderProcPtr constrain_proc;
+ 
+     Unwrap (cs, pScreen, CloseScreen, close_proc);
+     Unwrap (cs, pScreen, DisplayCursor, display_proc);
++    Unwrap (cs, pScreen, ConstrainCursorHarder, constrain_proc);
+     deleteCursorHideCountsForScreen(pScreen);
+     ret = (*pScreen->CloseScreen) (index, pScreen);
+     free(cs);
+@@ -1029,6 +1045,391 @@ CursorFreeWindow (pointer data, XID id)
+     return 1;
+ }
+ 
++static BOOL
++barrier_is_horizontal(const struct PointerBarrier *barrier)
++{
++    return barrier->y1 == barrier->y2;
++}
++
++static BOOL
++barrier_is_vertical(const struct PointerBarrier *barrier)
++{
++    return barrier->x1 == barrier->x2;
++}
++
++/**
++ * @return The set of barrier movement directions the movement vector
++ * x1/y1 → x2/y2 represents.
++ */
++int
++barrier_get_direction(int x1, int y1, int x2, int y2)
++{
++    int direction = 0;
++
++    /* which way are we trying to go */
++    if (x2 > x1)
++	direction |= BarrierPositiveX;
++    if (x2 < x1)
++	direction |= BarrierNegativeX;
++    if (y2 > y1)
++	direction |= BarrierPositiveY;
++    if (y2 < y1)
++	direction |= BarrierNegativeY;
++
++    return direction;
++}
++
++/**
++ * Test if the barrier may block movement in the direction defined by
++ * x1/y1 → x2/y2. This function only tests whether the directions could be
++ * blocked, it does not test if the barrier actually blocks the movement.
++ *
++ * @return TRUE if the barrier blocks the direction of movement or FALSE
++ * otherwise.
++ */
++BOOL
++barrier_is_blocking_direction(const struct PointerBarrier *barrier, int direction)
++{
++    /* Barriers define which way is ok, not which way is blocking */
++    return (barrier->directions & direction) != direction;
++}
++
++/**
++ * Test if the movement vector x1/y1 → x2/y2 is intersecting with the
++ * barrier. A movement vector with the startpoint or endpoint on the barrier
++ * itself counts as intersecting.
++ *
++ * @param x1 X start coordinate of movement vector
++ * @param y1 Y start coordinate of movement vector
++ * @param x2 X end coordinate of movement vector
++ * @param y2 Y end coordinate of movement vector
++ * @param[out] distance The distance between the start point and the
++ * intersection with the barrier (if applicable).
++ * @return TRUE if the barrier intersects with the given vector
++ */
++BOOL
++barrier_is_blocking(const struct PointerBarrier *barrier,
++		    int x1, int y1, int x2, int y2,
++		    double *distance)
++{
++    BOOL rc = FALSE;
++    float ua, ub, ud;
++    int dir = barrier_get_direction(x1, y1, x2, y2);
++
++    /* Algorithm below doesn't handle edge cases well, hence the extra
++     * checks. */
++    if (barrier_is_vertical(barrier)) {
++	/* handle immediate barrier adjacency, moving away */
++	if (dir & BarrierPositiveX && x1 == barrier->x1)
++	    return FALSE;
++	if (dir & BarrierNegativeX && x1 == (barrier->x1 - 1))
++	    return FALSE;
++	/* startpoint on barrier */
++	if (x1 == barrier->x1 && y1 >= barrier->y1 && y1 <= barrier->y2) {
++	    *distance = 0;
++	    return TRUE;
++	}
++	/* endpoint on barrier */
++	if (x2 == barrier->x1 && y2 >= barrier->y1 && y2 <= barrier->y2) {
++	    *distance = abs(x2 - x1);
++	    return TRUE;
++        }
++    } else {
++	/* handle immediate barrier adjacency, moving away */
++	if (dir & BarrierPositiveY && y1 == barrier->y1)
++	    return FALSE;
++	if (dir & BarrierNegativeY && y1 == (barrier->y1 - 1))
++	    return FALSE;
++	/* startpoint on barrier */
++	if (y1 == barrier->y1 && x1 >= barrier->x1 && x1 <= barrier->x2) {
++	    *distance = 0;
++	    return TRUE;
++        }
++	/* endpoint on barrier */
++	if (y2 == barrier->y1 && x2 >= barrier->x1 && x2 <= barrier->x2) {
++	    *distance = abs(y2 - y1);
++	    return TRUE;
++        }
++    }
++
++    /* not an edge case, compute distance */
++    ua = 0;
++    ud = (barrier->y2 - barrier->y1) * (x2 - x1) - (barrier->x2 - barrier->x1) * (y2 - y1);
++    if (ud != 0) {
++	ua = ((barrier->x2 - barrier->x1) * (y1 - barrier->y1) -
++	     (barrier->y2 - barrier->y1) * (x1 - barrier->x1)) / ud;
++	ub = ((x2 - x1) * (y1 - barrier->y1) -
++	     (y2 - y1) * (x1 - barrier->x1)) / ud;
++	if (ua < 0 || ua > 1 || ub < 0 || ub > 1)
++	    ua = 0;
++    }
++
++    if (ua > 0 && ua <= 1)
++    {
++	double ix = barrier->x1 + ua * (barrier->x2 - barrier->x1);
++	double iy = barrier->y1 + ua * (barrier->y2 - barrier->y1);
++
++	*distance = sqrt(pow(x1 - ix, 2) + pow(y1 - iy, 2));
++	rc = TRUE;
++    }
++
++    return rc;
++}
++
++/**
++ * Find the nearest barrier that is blocking movement from x1/y1 to x2/y2.
++ *
++ * @param dir Only barriers blocking movement in direction dir are checked
++ * @param x1 X start coordinate of movement vector
++ * @param y1 Y start coordinate of movement vector
++ * @param x2 X end coordinate of movement vector
++ * @param y2 Y end coordinate of movement vector
++ * @return The barrier nearest to the movement origin that blocks this movement.
++ */
++static struct PointerBarrier*
++barrier_find_nearest(CursorScreenPtr cs, int dir,
++		     int x1, int y1, int x2, int y2)
++{
++    struct PointerBarrierClient *c;
++    struct PointerBarrier *nearest = NULL;
++    double min_distance = INT_MAX; /* can't get higher than that in X anyway */
++
++    list_for_each_entry(c, &cs->barriers, entry) {
++	struct PointerBarrier *b = &c->barrier;
++	double distance;
++
++	if (!barrier_is_blocking_direction(b, dir))
++	    continue;
++
++	if (barrier_is_blocking(b, x1, y1, x2, y2, &distance))
++	{
++	    if (min_distance > distance)
++	    {
++		min_distance = distance;
++		nearest = b;
++	    }
++	}
++    }
++
++    return nearest;
++}
++
++/**
++ * Clamp to the given barrier given the movement direction specified in dir.
++ *
++ * @param barrier The barrier to clamp to
++ * @param dir The movement direction
++ * @param[out] x The clamped x coordinate.
++ * @param[out] y The clamped x coordinate.
++ */
++void
++barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y)
++{
++    if (barrier_is_vertical(barrier)) {
++	if ((dir & BarrierNegativeX) & ~barrier->directions)
++	    *x = barrier->x1;
++	if ((dir & BarrierPositiveX) & ~barrier->directions)
++	    *x = barrier->x1 - 1;
++    }
++    if (barrier_is_horizontal(barrier))
++    {
++	if ((dir & BarrierNegativeY) & ~barrier->directions)
++	    *y = barrier->y1;
++	if ((dir & BarrierPositiveY) & ~barrier->directions)
++	    *y = barrier->y1 - 1;
++    }
++}
++
++static void
++CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
++{
++    CursorScreenPtr cs = GetCursorScreen(screen);
++
++    if (!list_is_empty(&cs->barriers) && !IsFloating(dev) && mode == Relative) {
++	int ox, oy;
++	int dir;
++	struct PointerBarrier *nearest = NULL;
++
++	/* where are we coming from */
++	miPointerGetPosition(dev, &ox, &oy);
++
++	/* How this works:
++	 * Given the origin and the movement vector, get the nearest barrier
++	 * to the origin that is blocking the movement.
++	 * Clamp to that barrier.
++	 * Then, check from the clamped position to the original
++	 * destination, again finding the nearest barrier and clamping.
++	 */
++	dir = barrier_get_direction(ox, oy, *x, *y);
++
++	nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y);
++	if (nearest) {
++	    barrier_clamp_to_barrier(nearest, dir, x, y);
++
++	    if (barrier_is_vertical(nearest)) {
++		dir &= ~(BarrierNegativeX | BarrierPositiveX);
++		ox = *x;
++	    } else if (barrier_is_horizontal(nearest)) {
++		dir &= ~(BarrierNegativeY | BarrierPositiveY);
++		oy = *y;
++	    }
++
++	    nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y);
++	    if (nearest) {
++		barrier_clamp_to_barrier(nearest, dir, x, y);
++	    }
++	}
++    }
++
++    if (cs->ConstrainCursorHarder) {
++	screen->ConstrainCursorHarder = cs->ConstrainCursorHarder;
++	screen->ConstrainCursorHarder(dev, screen, mode, x, y);
++	screen->ConstrainCursorHarder = CursorConstrainCursorHarder;
++    }
++}
++
++static struct PointerBarrierClient *
++CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client,
++			   xXFixesCreatePointerBarrierReq *stuff)
++{
++    CursorScreenPtr cs = GetCursorScreen(screen);
++    struct PointerBarrierClient *ret = malloc(sizeof(*ret));
++
++    if (ret) {
++	ret->screen = screen;
++	ret->barrier.x1 = min(stuff->x1, stuff->x2);
++	ret->barrier.x2 = max(stuff->x1, stuff->x2);
++	ret->barrier.y1 = min(stuff->y1, stuff->y2);
++	ret->barrier.y2 = max(stuff->y1, stuff->y2);
++	ret->barrier.directions = stuff->directions & 0x0f;
++	if (barrier_is_horizontal(&ret->barrier))
++	    ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
++	if (barrier_is_vertical(&ret->barrier))
++	    ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY);
++	list_add(&ret->entry, &cs->barriers);
++    }
++
++    return ret;
++}
++
++int
++ProcXFixesCreatePointerBarrier (ClientPtr client)
++{
++    int err;
++    WindowPtr pWin;
++    struct PointerBarrierClient *barrier;
++    struct PointerBarrier b;
++    REQUEST (xXFixesCreatePointerBarrierReq);
++
++    REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
++    LEGAL_NEW_RESOURCE(stuff->barrier, client);
++
++    err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
++    if (err != Success) {
++	client->errorValue = stuff->window;
++	return err;
++    }
++
++    /* This sure does need fixing. */
++    if (stuff->num_devices)
++	return BadImplementation;
++
++    b.x1 = stuff->x1;
++    b.x2 = stuff->x2;
++    b.y1 = stuff->y1;
++    b.y2 = stuff->y2;
++
++    if (!barrier_is_horizontal(&b) && !barrier_is_vertical(&b))
++	return BadValue;
++
++    /* no 0-sized barriers */
++    if (barrier_is_horizontal(&b) && barrier_is_vertical(&b))
++	return BadValue;
++
++    if (!(barrier = CreatePointerBarrierClient(pWin->drawable.pScreen,
++					       client, stuff)))
++	return BadAlloc;
++
++    if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier))
++	return BadAlloc;
++
++    return Success;
++}
++
++int
++SProcXFixesCreatePointerBarrier (ClientPtr client)
++{
++    int n;
++    REQUEST(xXFixesCreatePointerBarrierReq);
++
++    swaps(&stuff->length, n);
++    REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
++    swapl(&stuff->barrier, n);
++    swapl(&stuff->window, n);
++    swaps(&stuff->x1, n);
++    swaps(&stuff->y1, n);
++    swaps(&stuff->x2, n);
++    swaps(&stuff->y2, n);
++    swapl(&stuff->directions, n);
++    return ProcXFixesVector[stuff->xfixesReqType](client);
++}
++
++static int
++CursorFreeBarrier(void *data, XID id)
++{
++    struct PointerBarrierClient *b = NULL, *barrier;
++    ScreenPtr screen;
++    CursorScreenPtr cs;
++
++    barrier = container_of(data, struct PointerBarrierClient, barrier);
++    screen = barrier->screen;
++    cs = GetCursorScreen(screen);
++
++    /* find and unlink from the screen private */
++    list_for_each_entry(b, &cs->barriers, entry) {
++	if (b == barrier) {
++	    list_del(&b->entry);
++	    break;
++	}
++    }
++
++    free(barrier);
++    return Success;
++}
++
++int
++ProcXFixesDestroyPointerBarrier (ClientPtr client)
++{
++    int err;
++    void *barrier;
++    REQUEST (xXFixesDestroyPointerBarrierReq);
++
++    REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
++
++    err = dixLookupResourceByType((void **)&barrier, stuff->barrier,
++				  PointerBarrierType, client,
++				  DixDestroyAccess);
++    if (err != Success) {
++	client->errorValue = stuff->barrier;
++	return err;
++    }
++
++    FreeResource(stuff->barrier, RT_NONE);
++    return Success;
++}
++
++int
++SProcXFixesDestroyPointerBarrier (ClientPtr client)
++{
++    int n;
++    REQUEST(xXFixesDestroyPointerBarrierReq);
++
++    swaps(&stuff->length, n);
++    REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
++    swapl(&stuff->barrier, n);
++    return ProcXFixesVector[stuff->xfixesReqType](client);
++}
++
+ Bool
+ XFixesCursorInit (void)
+ {
+@@ -1048,8 +1449,10 @@ XFixesCursorInit (void)
+ 	cs = (CursorScreenPtr) calloc(1, sizeof (CursorScreenRec));
+ 	if (!cs)
+ 	    return FALSE;
++	list_init(&cs->barriers);
+ 	Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
+ 	Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
++	Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
+ 	cs->pCursorHideCounts = NULL;
+ 	SetCursorScreen (pScreen, cs);
+     }
+@@ -1059,7 +1462,10 @@ XFixesCursorInit (void)
+ 						"XFixesCursorHideCount");
+     CursorWindowType = CreateNewResourceType(CursorFreeWindow,
+ 					     "XFixesCursorWindow");
++    PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
++					      "XFixesPointerBarrier");
+ 
+-    return CursorClientType && CursorHideCountType && CursorWindowType;
++    return CursorClientType && CursorHideCountType && CursorWindowType &&
++	   PointerBarrierType;
+ }
+ 
+diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c
+index e8c7bf1..a57884b 100644
+--- a/xfixes/xfixes.c
++++ b/xfixes/xfixes.c
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright 2010 Red Hat, Inc.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the "Software"),
+@@ -47,10 +48,6 @@
+ 
+ #include "xfixesint.h"
+ #include "protocol-versions.h"
+-/*
+- * Must use these instead of the constants from xfixeswire.h.  They advertise
+- * what we implement, not what the protocol headers define.
+- */
+ 
+ static unsigned char	XFixesReqCode;
+ int		XFixesEventBase;
+@@ -97,11 +94,12 @@ ProcXFixesQueryVersion(ClientPtr client)
+ 
+ /* Major version controls available requests */
+ static const int version_requests[] = {
+-    X_XFixesQueryVersion,	/* before client sends QueryVersion */
+-    X_XFixesGetCursorImage,	/* Version 1 */
+-    X_XFixesChangeCursorByName,	/* Version 2 */
+-    X_XFixesExpandRegion,	/* Version 3 */
+-    X_XFixesShowCursor,	        /* Version 4 */
++    X_XFixesQueryVersion,	    /* before client sends QueryVersion */
++    X_XFixesGetCursorImage,	    /* Version 1 */
++    X_XFixesChangeCursorByName,	    /* Version 2 */
++    X_XFixesExpandRegion,	    /* Version 3 */
++    X_XFixesShowCursor,		    /* Version 4 */
++    X_XFixesCreatePointerBarrier,   /* Version 5 */
+ };
+ 
+ #define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0]))
+@@ -142,6 +140,9 @@ int	(*ProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
+ /*************** Version 4 ****************/
+     ProcXFixesHideCursor,
+     ProcXFixesShowCursor,
++/*************** Version 5 ****************/
++    ProcXFixesCreatePointerBarrier,
++    ProcXFixesDestroyPointerBarrier,
+ };
+ 
+ static int
+@@ -205,6 +206,9 @@ static int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
+ /*************** Version 4 ****************/
+     SProcXFixesHideCursor,
+     SProcXFixesShowCursor,
++/*************** Version 5 ****************/
++    SProcXFixesCreatePointerBarrier,
++    SProcXFixesDestroyPointerBarrier,
+ };
+ 
+ static int
+@@ -260,6 +264,8 @@ XFixesExtensionInit(void)
+ 	EventSwapVector[XFixesEventBase + XFixesCursorNotify] =
+ 	    (EventSwapPtr) SXFixesCursorNotifyEvent;
+ 	SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion);
++	SetResourceTypeErrorValue(PointerBarrierType,
++				  XFixesErrorBase + BadBarrier);
+     }
+ }
+ 
+diff --git a/xfixes/xfixes.h b/xfixes/xfixes.h
+index 1638350..5765e64 100644
+--- a/xfixes/xfixes.h
++++ b/xfixes/xfixes.h
+@@ -30,6 +30,7 @@
+ #include "resource.h"
+ 
+ extern _X_EXPORT RESTYPE RegionResType;
++extern _X_EXPORT RESTYPE PointerBarrierType;
+ extern _X_EXPORT int XFixesErrorBase;
+ 
+ #define VERIFY_REGION(pRegion, rid, client, mode)			\
+@@ -51,5 +52,21 @@ extern _X_EXPORT int XFixesErrorBase;
+ extern _X_EXPORT RegionPtr
+ XFixesRegionCopy (RegionPtr pRegion);
+ 
++struct PointerBarrier {
++    CARD16 x1, x2, y1, y2;
++    CARD32 directions;
++};
++
++
++extern int
++barrier_get_direction(int, int, int, int);
++extern BOOL
++barrier_is_blocking(const struct PointerBarrier*, int, int, int, int, double*);
++extern BOOL
++barrier_is_blocking_direction(const struct PointerBarrier*, int);
++extern void
++barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y);
++
++
+ 
+ #endif /* _XFIXES_H_ */
+diff --git a/xfixes/xfixesint.h b/xfixes/xfixesint.h
+index d005369..6ba276e 100644
+--- a/xfixes/xfixesint.h
++++ b/xfixes/xfixesint.h
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright 2010 Red Hat, Inc.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the "Software"),
+@@ -278,6 +279,21 @@ ProcXFixesShowCursor (ClientPtr client);
+ int 
+ SProcXFixesShowCursor (ClientPtr client);
+ 
++/* Version 5 */
++
++int
++ProcXFixesCreatePointerBarrier (ClientPtr client);
++
++int
++SProcXFixesCreatePointerBarrier (ClientPtr client);
++
++int
++ProcXFixesDestroyPointerBarrier (ClientPtr client);
++
++int
++SProcXFixesDestroyPointerBarrier (ClientPtr client);
++
++/* Xinerama */
+ extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr);
+ void PanoramiXFixesInit (void);
+ void PanoramiXFixesReset (void);
+-- 
+1.7.4
+
diff --git a/xserver-1.10-vbe-malloc.patch b/xserver-1.10-vbe-malloc.patch
new file mode 100644
index 0000000..5231983
--- /dev/null
+++ b/xserver-1.10-vbe-malloc.patch
@@ -0,0 +1,43 @@
+From 0ab680f08208afe51ad6ddc1018b7d6f8b851840 Mon Sep 17 00:00:00 2001
+From: Adam Jackson <ajax at redhat.com>
+Date: Thu, 24 Feb 2011 16:06:34 -0500
+Subject: [PATCH] vbe: Fix malloc size bug
+
+v2: Slightly more obvious sizing math.
+
+==14882== Invalid write of size 2
+==14882==    at 0x6750267: VBEGetVBEInfo (vbe.c:400)
+==14882==    by 0x6142064: ??? (in /usr/lib64/xorg/modules/drivers/vesa_drv.so)
+==14882==    by 0x471895: InitOutput (xf86Init.c:519)
+==14882==    by 0x422778: main (main.c:205)
+==14882==  Address 0x4f32fa8 is 72 bytes inside a block of size 73 alloc'd
+==14882==    at 0x4A0640D: malloc (vg_replace_malloc.c:236)
+==14882==    by 0x675024B: VBEGetVBEInfo (vbe.c:398)
+==14882==    by 0x6142064: ??? (in /usr/lib64/xorg/modules/drivers/vesa_drv.so)
+==14882==    by 0x471895: InitOutput (xf86Init.c:519)
+==14882==    by 0x422778: main (main.c:205)
+
+Reviewed-by: Mark Kettenis <kettenis at openbsd.org>
+Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>
+Signed-off-by: Adam Jackson <ajax at redhat.com>
+(cherry picked from commit d8caa782009abf4dc17b945e325e83fda299a534)
+---
+ hw/xfree86/vbe/vbe.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/hw/xfree86/vbe/vbe.c b/hw/xfree86/vbe/vbe.c
+index bcda5ec..04132d9 100644
+--- a/hw/xfree86/vbe/vbe.c
++++ b/hw/xfree86/vbe/vbe.c
+@@ -395,7 +395,7 @@ VBEGetVBEInfo(vbeInfoPtr pVbe)
+     i = 0;
+     while (modes[i] != 0xffff)
+ 	i++;
+-    block->VideoModePtr = malloc(sizeof(CARD16) * i + 1);
++    block->VideoModePtr = malloc(sizeof(CARD16) * (i + 1));
+     memcpy(block->VideoModePtr, modes, sizeof(CARD16) * i);
+     block->VideoModePtr[i] = 0xffff;
+ 
+-- 
+1.7.4
+


More information about the scm-commits mailing list