pkgsrc-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[pkgsrc/trunk]: pkgsrc/graphics/cairo cairo: fix segfault in quartz backend (...



details:   https://anonhg.NetBSD.org/pkgsrc/rev/d4fb299639f0
branches:  trunk
changeset: 379188:d4fb299639f0
user:      tnn <tnn%pkgsrc.org@localhost>
date:      Thu May 12 17:13:55 2022 +0000

description:
cairo: fix segfault in quartz backend (via upstream)

diffstat:

 graphics/cairo/Makefile                                       |    4 +-
 graphics/cairo/distinfo                                       |    4 +-
 graphics/cairo/patches/patch-src_cairo-quartz-image-surface.c |  110 ++++++
 graphics/cairo/patches/patch-src_cairo-quartz-surface.c       |  175 ++++++++++
 4 files changed, 290 insertions(+), 3 deletions(-)

diffs (truncated from 324 to 300 lines):

diff -r 65597659357d -r d4fb299639f0 graphics/cairo/Makefile
--- a/graphics/cairo/Makefile   Thu May 12 15:45:54 2022 +0000
+++ b/graphics/cairo/Makefile   Thu May 12 17:13:55 2022 +0000
@@ -1,8 +1,8 @@
-# $NetBSD: Makefile,v 1.150 2022/04/05 10:06:41 riastradh Exp $
+# $NetBSD: Makefile,v 1.151 2022/05/12 17:13:55 tnn Exp $
 
 .include "../../graphics/cairo/Makefile.common"
 
-PKGREVISION=   5
+PKGREVISION=   6
 
 TEST_TARGET=                   check
 
diff -r 65597659357d -r d4fb299639f0 graphics/cairo/distinfo
--- a/graphics/cairo/distinfo   Thu May 12 15:45:54 2022 +0000
+++ b/graphics/cairo/distinfo   Thu May 12 17:13:55 2022 +0000
@@ -1,4 +1,4 @@
-$NetBSD: distinfo,v 1.94 2022/04/07 10:57:57 riastradh Exp $
+$NetBSD: distinfo,v 1.95 2022/05/12 17:13:55 tnn Exp $
 
 BLAKE2s (cairo-1.16.0.tar.xz) = fba95926f57ad97d9c0c197c355ef646fd3cf9d17d1eb3270d343eef5d7bfa40
 SHA512 (cairo-1.16.0.tar.xz) = 9eb27c4cf01c0b8b56f2e15e651f6d4e52c99d0005875546405b64f1132aed12fbf84727273f493d84056a13105e065009d89e94a8bfaf2be2649e232b82377f
@@ -13,5 +13,7 @@
 SHA1 (patch-perf_cairo-perf-trace.c) = 0f8cb89493a202b58b22e6244fe1c1bcc0a34b88
 SHA1 (patch-src_cairo-ft-font.c) = 97288d79380473869f1049c1d8955a2f6fa3d178
 SHA1 (patch-src_cairo-image-compositor.c) = 83337d8211083d77b061c43b69da2b61080776d9
+SHA1 (patch-src_cairo-quartz-image-surface.c) = f3963afb665d70189c18de02b943313b7f7b6dcd
+SHA1 (patch-src_cairo-quartz-surface.c) = 870ff264a0046adad5a3c93e76da4684d6a365eb
 SHA1 (patch-src_cairo-type1-subset.c) = 741de4ec29cc4805aa51cbb4d89947a58dca0646
 SHA1 (patch-util_cairo-trace_trace.c) = 0979e99a2aeaeb711a9b7636a0e6ba5048f26077
diff -r 65597659357d -r d4fb299639f0 graphics/cairo/patches/patch-src_cairo-quartz-image-surface.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/cairo/patches/patch-src_cairo-quartz-image-surface.c     Thu May 12 17:13:55 2022 +0000
@@ -0,0 +1,110 @@
+$NetBSD: patch-src_cairo-quartz-image-surface.c,v 1.1 2022/05/12 17:13:55 tnn Exp $
+
+Ref and destroy the cairo surface handed off to CoreGraphics.
+https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/52
+
+--- src/cairo-quartz-image-surface.c.orig      2018-08-17 01:10:53.000000000 +0000
++++ src/cairo-quartz-image-surface.c
+@@ -50,10 +50,9 @@
+ #define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
+ 
+ static void
+-DataProviderReleaseCallback (void *info, const void *data, size_t size)
++DataProviderReleaseCallback (void *image_info, const void *data, size_t size)
+ {
+-    cairo_surface_t *surface = (cairo_surface_t *) info;
+-    cairo_surface_destroy (surface);
++    free (image_info);
+ }
+ 
+ static cairo_surface_t *
+@@ -88,9 +87,8 @@ _cairo_quartz_image_surface_finish (void
+ {
+     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
+ 
+-    /* the imageSurface will be destroyed by the data provider's release callback */
+     CGImageRelease (surface->image);
+-
++    cairo_surface_destroy (surface->imageSurface);
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+@@ -147,24 +145,29 @@ _cairo_quartz_image_surface_flush (void 
+     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
+     CGImageRef oldImage = surface->image;
+     CGImageRef newImage = NULL;
+-
++    void *image_data;
++    const unsigned int size = surface->imageSurface->height * surface->imageSurface->stride;
+     if (flags)
+       return CAIRO_STATUS_SUCCESS;
+ 
+     /* XXX only flush if the image has been modified. */
+ 
+-    /* To be released by the ReleaseCallback */
+-    cairo_surface_reference ((cairo_surface_t*) surface->imageSurface);
++    image_data = _cairo_malloc_ab ( surface->imageSurface->height,
++                                  surface->imageSurface->stride);
++    if (unlikely (!image_data))
++      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ 
++    memcpy (image_data, surface->imageSurface->data,
++          surface->imageSurface->height * surface->imageSurface->stride);
+     newImage = CairoQuartzCreateCGImage (surface->imageSurface->format,
+                                        surface->imageSurface->width,
+                                        surface->imageSurface->height,
+                                        surface->imageSurface->stride,
+-                                       surface->imageSurface->data,
++                                       image_data,
+                                        TRUE,
+                                        NULL,
+                                        DataProviderReleaseCallback,
+-                                       surface->imageSurface);
++                                       image_data);
+ 
+     surface->image = newImage;
+     CGImageRelease (oldImage);
+@@ -308,7 +311,7 @@ cairo_quartz_image_surface_create (cairo
+     cairo_image_surface_t *image_surface;
+     int width, height, stride;
+     cairo_format_t format;
+-    unsigned char *data;
++    void *image_data;
+ 
+     if (surface->status)
+       return surface;
+@@ -321,7 +324,6 @@ cairo_quartz_image_surface_create (cairo
+     height = image_surface->height;
+     stride = image_surface->stride;
+     format = image_surface->format;
+-    data = image_surface->data;
+ 
+     if (!_cairo_quartz_verify_surface_size(width, height))
+       return SURFACE_ERROR_INVALID_SIZE;
+@@ -338,20 +340,19 @@ cairo_quartz_image_surface_create (cairo
+ 
+     memset (qisurf, 0, sizeof(cairo_quartz_image_surface_t));
+ 
+-    /* In case the create_cgimage fails, this ref will
+-     * be released via the callback (which will be called in
+-     * case of failure.)
+-     */
+-    cairo_surface_reference (surface);
++    image_data = _cairo_malloc_ab (height, stride);
++    if (unlikely (!image_data))
++      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ 
++    memcpy (image_data, image_surface->data, height * stride);
+     image = CairoQuartzCreateCGImage (format,
+                                     width, height,
+                                     stride,
+-                                    data,
++                                    image_data,
+                                     TRUE,
+                                     NULL,
+                                     DataProviderReleaseCallback,
+-                                    image_surface);
++                                    image_data);
+ 
+     if (!image) {
+       free (qisurf);
diff -r 65597659357d -r d4fb299639f0 graphics/cairo/patches/patch-src_cairo-quartz-surface.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/cairo/patches/patch-src_cairo-quartz-surface.c   Thu May 12 17:13:55 2022 +0000
@@ -0,0 +1,175 @@
+$NetBSD: patch-src_cairo-quartz-surface.c,v 1.1 2022/05/12 17:13:55 tnn Exp $
+
+Ref and destroy the cairo surface handed off to CoreGraphics.
+https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/52
+
+--- src/cairo-quartz-surface.c.orig    2018-08-17 01:10:53.000000000 +0000
++++ src/cairo-quartz-surface.c
+@@ -778,20 +778,10 @@ CairoQuartzCreateGradientFunction (const
+                            &gradient_callbacks);
+ }
+ 
+-/* Obtain a CGImageRef from a #cairo_surface_t * */
+-
+-typedef struct {
+-    cairo_surface_t *surface;
+-    cairo_image_surface_t *image_out;
+-    void *image_extra;
+-} quartz_source_image_t;
+-
+ static void
+ DataProviderReleaseCallback (void *info, const void *data, size_t size)
+ {
+-    quartz_source_image_t *source_img = info;
+-    _cairo_surface_release_source_image (source_img->surface, source_img->image_out, source_img->image_extra);
+-    free (source_img);
++    free (info);
+ }
+ 
+ static cairo_status_t
+@@ -803,8 +793,9 @@ _cairo_surface_to_cgimage (cairo_surface
+                          CGImageRef            *image_out)
+ {
+     cairo_status_t status;
+-    quartz_source_image_t *source_img;
+     cairo_image_surface_t *image_surface;
++    void *image_data, *image_extra;
++    cairo_bool_t acquired = FALSE;
+ 
+     if (source->backend && source->backend->type == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) {
+       cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) source;
+@@ -826,19 +817,12 @@ _cairo_surface_to_cgimage (cairo_surface
+       }
+     }
+ 
+-    source_img = _cairo_malloc (sizeof (quartz_source_image_t));
+-    if (unlikely (source_img == NULL))
+-      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+-
+-    source_img->surface = source;
+-
+     if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
+       image_surface = (cairo_image_surface_t *)
+           cairo_image_surface_create (format, extents->width, extents->height);
+       if (unlikely (image_surface->base.status)) {
+           status = image_surface->base.status;
+           cairo_surface_destroy (&image_surface->base);
+-          free (source_img);
+           return status;
+       }
+ 
+@@ -848,46 +832,61 @@ _cairo_surface_to_cgimage (cairo_surface
+                                                           NULL);
+       if (unlikely (status)) {
+           cairo_surface_destroy (&image_surface->base);
+-          free (source_img);
+           return status;
+       }
+ 
+-      source_img->image_out = image_surface;
+-      source_img->image_extra = NULL;
+-
+       cairo_matrix_init_identity (matrix);
+     }
+     else {
+-      status = _cairo_surface_acquire_source_image (source_img->surface,
+-                                                    &source_img->image_out,
+-                                                    &source_img->image_extra);
+-      if (unlikely (status)) {
+-          free (source_img);
++      status = _cairo_surface_acquire_source_image (source, &image_surface,
++                                                    &image_extra);
++      if (unlikely (status))
+           return status;
+-      }
++      acquired = TRUE;
+     }
+ 
+-    if (source_img->image_out->width == 0 || source_img->image_out->height == 0) {
++    if (image_surface->width == 0 || image_surface->height == 0) {
+       *image_out = NULL;
+-      DataProviderReleaseCallback (source_img,
+-                                   source_img->image_out->data,
+-                                   source_img->image_out->height * source_img->image_out->stride);
+-    } else {
+-      *image_out = CairoQuartzCreateCGImage (source_img->image_out->format,
+-                                             source_img->image_out->width,
+-                                             source_img->image_out->height,
+-                                             source_img->image_out->stride,
+-                                             source_img->image_out->data,
+-                                             TRUE,
+-                                             NULL,
+-                                             DataProviderReleaseCallback,
+-                                             source_img);
+-
+-      /* TODO: differentiate memory error and unsupported surface type */
+-      if (unlikely (*image_out == NULL))
+-          status = CAIRO_INT_STATUS_UNSUPPORTED;
++      if (acquired)
++          _cairo_surface_release_source_image (source, image_surface, image_extra);
++      else
++          cairo_surface_destroy (&image_surface->base);
++
++      return status;
+     }
+ 
++    image_data = _cairo_malloc_ab (image_surface->height, image_surface->stride);
++    if (unlikely (!image_data))
++    {
++      if (acquired)
++          _cairo_surface_release_source_image (source, image_surface, image_extra);
++      else
++          cairo_surface_destroy (&image_surface->base);
++
++      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
++    }
++
++    memcpy (image_data, image_surface->data,
++          image_surface->height * image_surface->stride);
++    *image_out = CairoQuartzCreateCGImage (image_surface->format,
++                                         image_surface->width,
++                                         image_surface->height,
++                                         image_surface->stride,
++                                         image_data,
++                                         TRUE,
++                                         NULL,
++                                         DataProviderReleaseCallback,
++                                         image_data);
++
++    /* TODO: differentiate memory error and unsupported surface type */
++    if (unlikely (*image_out == NULL))
++      status = CAIRO_INT_STATUS_UNSUPPORTED;
++
++    if (acquired)
++      _cairo_surface_release_source_image (source, image_surface, image_extra);
++    else
++      cairo_surface_destroy (&image_surface->base);
++
+     return status;
+ }
+ 
+@@ -2273,11 +2272,13 @@ _cairo_quartz_surface_create_internal (C



Home | Main Index | Thread Index | Old Index