Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLee Culver <leculver@microsoft.com>2019-05-24 13:22:51 +0300
committerMarek Safar <marek.safar@gmail.com>2019-05-24 13:22:51 +0300
commitef9d54d151ea245a6fe07a3dbb9320c4a3b1daf9 (patch)
tree14164b5d3aa62ec235988259a795b95c3bd05497 /mcs/class/Mono.Cairo
parent8f6a7b34eec09b7304e5966f0f1b45ec858f6a1a (diff)
Throw ObjectDisposedException instead of crashing when Cairo.Context handle == IntPtr.Zero (#14323)
* Throw ObjectDisposedException instead of crashing when Cairo.Context.handle == IntPtr.Zero We are seeing instances where VS for Mac is crashing with a SIGSEGV when calling into certain Cairo.Context functions. Looking at the code, it's clear that it's possible to have Context.handle == IntPtr.Zero after disposing the object. From research, it looks like passing a nullptr to raw cairo functions can result in a SIGSEGV: https://bugs.launchpad.net/ubuntu/+source/compiz/+bug/93807 This change adds check to see if Conext.handle == IntPtr.Zero in Context painting, font, and path methods. This will turn uncatchable SIGSEGVs into ObjectDisposedException. * Update Context.cs * Ensure SetTarget results in a valid handle
Diffstat (limited to 'mcs/class/Mono.Cairo')
-rw-r--r--mcs/class/Mono.Cairo/Mono.Cairo/Context.cs55
1 files changed, 53 insertions, 2 deletions
diff --git a/mcs/class/Mono.Cairo/Mono.Cairo/Context.cs b/mcs/class/Mono.Cairo/Mono.Cairo/Context.cs
index 7ca0dee45dd..09e2d5f0341 100644
--- a/mcs/class/Mono.Cairo/Mono.Cairo/Context.cs
+++ b/mcs/class/Mono.Cairo/Mono.Cairo/Context.cs
@@ -49,7 +49,7 @@ namespace Cairo {
public class Context : IDisposable
{
- IntPtr handle = IntPtr.Zero;
+ IntPtr handle;
static int native_glyph_size, c_compiler_long_size;
@@ -105,6 +105,12 @@ namespace Cairo {
Dispose (false);
}
+ private void ThrowIfDisposed()
+ {
+ if (handle == IntPtr.Zero)
+ throw new ObjectDisposedException("Cairo.Context");
+ }
+
public void Dispose ()
{
Dispose (true);
@@ -307,9 +313,14 @@ namespace Cairo {
public void SetTarget (Surface target)
{
+ IntPtr newHandle = NativeMethods.cairo_create (target.Handle);
+ if (newHandle == IntPtr.Zero)
+ throw new InvalidOperationException ("Surface had an invalid handle.");
+
if (handle != IntPtr.Zero)
NativeMethods.cairo_destroy (handle);
- handle = NativeMethods.cairo_create (target.Handle);
+
+ handle = newHandle;
}
[Obsolete("Use GetScaledFont/SetScaledFont")]
@@ -325,11 +336,13 @@ namespace Cairo {
public ScaledFont GetScaledFont ()
{
+ ThrowIfDisposed();
return new ScaledFont (NativeMethods.cairo_get_scaled_font (handle), false);
}
public void SetScaledFont (ScaledFont font)
{
+ ThrowIfDisposed();
NativeMethods.cairo_set_scaled_font (handle, font.Handle);
}
@@ -339,32 +352,38 @@ namespace Cairo {
public void SetSourceColor (Color color)
{
+ ThrowIfDisposed();
NativeMethods.cairo_set_source_rgba (handle, color.R, color.G, color.B, color.A);
}
public void SetSourceRGB (double r, double g, double b)
{
+ ThrowIfDisposed();
NativeMethods.cairo_set_source_rgb (handle, r, g, b);
}
public void SetSourceRGBA (double r, double g, double b, double a)
{
+ ThrowIfDisposed();
NativeMethods.cairo_set_source_rgba (handle, r, g, b, a);
}
//[Obsolete ("Use SetSource method (with double parameters)")]
public void SetSourceSurface (Surface source, int x, int y)
{
+ ThrowIfDisposed();
NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y);
}
public void SetSource (Surface source, double x, double y)
{
+ ThrowIfDisposed();
NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y);
}
public void SetSource (Surface source)
{
+ ThrowIfDisposed();
NativeMethods.cairo_set_source_surface (handle, source.Handle, 0, 0);
}
@@ -372,116 +391,139 @@ namespace Cairo {
public void NewPath ()
{
+ ThrowIfDisposed();
NativeMethods.cairo_new_path (handle);
}
public void NewSubPath ()
{
+ ThrowIfDisposed();
NativeMethods.cairo_new_sub_path (handle);
}
public void MoveTo (PointD p)
{
+ ThrowIfDisposed();
MoveTo (p.X, p.Y);
}
public void MoveTo (double x, double y)
{
+ ThrowIfDisposed();
NativeMethods.cairo_move_to (handle, x, y);
}
public void LineTo (PointD p)
{
+ ThrowIfDisposed();
LineTo (p.X, p.Y);
}
public void LineTo (double x, double y)
{
+ ThrowIfDisposed();
NativeMethods.cairo_line_to (handle, x, y);
}
public void CurveTo (PointD p1, PointD p2, PointD p3)
{
+ ThrowIfDisposed();
CurveTo (p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y);
}
public void CurveTo (double x1, double y1, double x2, double y2, double x3, double y3)
{
+ ThrowIfDisposed();
NativeMethods.cairo_curve_to (handle, x1, y1, x2, y2, x3, y3);
}
public void RelMoveTo (Distance d)
{
+ ThrowIfDisposed();
RelMoveTo (d.Dx, d.Dy);
}
public void RelMoveTo (double dx, double dy)
{
+ ThrowIfDisposed();
NativeMethods.cairo_rel_move_to (handle, dx, dy);
}
public void RelLineTo (Distance d)
{
+ ThrowIfDisposed();
RelLineTo (d.Dx, d.Dy);
}
public void RelLineTo (double dx, double dy)
{
+ ThrowIfDisposed();
NativeMethods.cairo_rel_line_to (handle, dx, dy);
}
public void RelCurveTo (Distance d1, Distance d2, Distance d3)
{
+ ThrowIfDisposed();
RelCurveTo (d1.Dx, d1.Dy, d2.Dx, d2.Dy, d3.Dx, d3.Dy);
}
public void RelCurveTo (double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
{
+ ThrowIfDisposed();
NativeMethods.cairo_rel_curve_to (handle, dx1, dy1, dx2, dy2, dx3, dy3);
}
public void Arc (double xc, double yc, double radius, double angle1, double angle2)
{
+ ThrowIfDisposed();
NativeMethods.cairo_arc (handle, xc, yc, radius, angle1, angle2);
}
public void ArcNegative (double xc, double yc, double radius, double angle1, double angle2)
{
+ ThrowIfDisposed();
NativeMethods.cairo_arc_negative (handle, xc, yc, radius, angle1, angle2);
}
public void Rectangle (Rectangle rectangle)
{
+ ThrowIfDisposed();
Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
}
public void Rectangle (PointD p, double width, double height)
{
+ ThrowIfDisposed();
Rectangle (p.X, p.Y, width, height);
}
public void Rectangle (double x, double y, double width, double height)
{
+ ThrowIfDisposed();
NativeMethods.cairo_rectangle (handle, x, y, width, height);
}
public void ClosePath ()
{
+ ThrowIfDisposed();
NativeMethods.cairo_close_path (handle);
}
public Path CopyPath ()
{
+ ThrowIfDisposed();
return new Path (NativeMethods.cairo_copy_path (handle));
}
public Path CopyPathFlat ()
{
+ ThrowIfDisposed();
return new Path (NativeMethods.cairo_copy_path_flat (handle));
}
public void AppendPath (Path path)
{
+ ThrowIfDisposed();
NativeMethods.cairo_append_path (handle, path.Handle);
}
@@ -490,36 +532,43 @@ namespace Cairo {
#region Painting Methods
public void Paint ()
{
+ ThrowIfDisposed();
NativeMethods.cairo_paint (handle);
}
public void PaintWithAlpha (double alpha)
{
+ ThrowIfDisposed();
NativeMethods.cairo_paint_with_alpha (handle, alpha);
}
public void Mask (Pattern pattern)
{
+ ThrowIfDisposed();
NativeMethods.cairo_mask (handle, pattern.Handle);
}
public void MaskSurface (Surface surface, double surface_x, double surface_y)
{
+ ThrowIfDisposed();
NativeMethods.cairo_mask_surface (handle, surface.Handle, surface_x, surface_y);
}
public void Stroke ()
{
+ ThrowIfDisposed();
NativeMethods.cairo_stroke (handle);
}
public void StrokePreserve ()
{
+ ThrowIfDisposed();
NativeMethods.cairo_stroke_preserve (handle);
}
public Rectangle StrokeExtents ()
{
+ ThrowIfDisposed();
double x1, y1, x2, y2;
NativeMethods.cairo_stroke_extents (handle, out x1, out y1, out x2, out y2);
return new Rectangle (x1, y1, x2 - x1, y2 - y1);
@@ -527,6 +576,7 @@ namespace Cairo {
public void Fill ()
{
+ ThrowIfDisposed();
NativeMethods.cairo_fill (handle);
}
@@ -539,6 +589,7 @@ namespace Cairo {
public void FillPreserve ()
{
+ ThrowIfDisposed();
NativeMethods.cairo_fill_preserve (handle);
}