[cairo] [PATCH] stroker: Check for scaling overflow in computing half line widths
Chris Wilson
chris at chris-wilson.co.uk
Fri Mar 24 16:24:08 UTC 2017
On Fri, Mar 24, 2017 at 04:55:54PM +0100, Uli Schlachter wrote:
> On 24.03.2017 13:36, Chris Wilson wrote:
> > Given a combination of a large scaling matrix and a large line, we can
> > easily generate a half line width that is unrepresentable in our 24.8
> > fixed-point. This leads to spurious errors later, such as generating
> > negative height boxes, and so asking pixman to fill to infinity. To
> > avoid this, we can check for overflow in calculating the half line with,
> > though we still lack adequate range checking on the final stroke path.
> >
> > References: https://bugs.webkit.org/show_bug.cgi?id=16793
>
> Are you sure that URL is the right one? That one has been closed as
> invalid 9 years ago.
+2 http://bugs.webkit.org/show_bug.cgi?id=167932
Actually looks like https://bugs.freedesktop.org/show_bug.cgi?id=90120
For which I wrote a different validation patch, which we should also
investigate. There is likely merit in combining/using both the
validation of the stroker ctm and also double checking against the
overflow in fixed-point conversion.
>
> > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> > Cc: magomez at igalia.com
> > ---
> > src/cairo-fixed-private.h | 13 +++++++++++++
> > src/cairo-path-stroke-boxes.c | 25 ++++++++++++++++++++-----
> > src/cairo-path-stroke-polygon.c | 1 +
> > src/cairo-path-stroke-traps.c | 1 +
> > src/cairo-path-stroke.c | 1 +
> > 5 files changed, 36 insertions(+), 5 deletions(-)
> >
> > diff --git a/src/cairo-fixed-private.h b/src/cairo-fixed-private.h
> > index 9ff8f7503..8ee895b92 100644
> > --- a/src/cairo-fixed-private.h
> > +++ b/src/cairo-fixed-private.h
> > @@ -53,6 +53,9 @@
> > #define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS))
> > #define CAIRO_FIXED_EPSILON ((cairo_fixed_t)(1))
> >
> > +#define CAIRO_FIXED_MAX (~0u >> (CAIRO_FIXED_FRAC_BITS + 1))
> > +#define CAIRO_FIXED_MIN (-(int)CAIRO_FIXED_MAX)
> > +
>
> So... the above is basically (int)_cairo_fixed_to_double(0x7fffffffu),
> right? "~0u >> 1" is supposed to be INT32_MAX (maximum fixed value) and
> this value is then converted to an integer via >> CAIRO_FIXED_FRAC_BITS.
>
> How about replacing "~0u" with this constant, so that systems with
> sizeof(unsigned int) != 4 will also work fine?
>
> Also, I do not like the name. CAIRO_FIXED_ONE is the number 1 as a fixed
> number, while CAIRO_FIXED_MAX is the maximum value as an integer. Could
> you name it CAIRO_FIXED_MAX_INT? (and same for MIN)
>
> Oh and: This is not really the maximum value, since you shifted off some
> bits. Don't you need something like MAX =
> _cairo_fixed_to_double((cairo_fixed_t)(~0u >> 1))
That's exactly equivalent to the above, prior to the (double) cast.
> _cairo_fixed_to_double((cairo_fixed_t)(~0u)) (the later assuming
> two-complement's arithmetic and ignoring that signed overflow is
> undefined behaviour).
> I guess this difference is not all that important in practice. How about
> mentioning it in a comment next to the definition? "These are not the
> real limits, but just the closest whole numbers"
Yes, we could add one to upper and use >= (and vice version for the
lower).
CAIRO_FIXED_INT_UPPER_BOUND
CAIRO_FIXED_INT_LOWER_BOUND
?
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
More information about the cairo
mailing list