Fixed #32600 -- Fixed Geometry collections and Polygon segmentation fault on macOS ARM64.

This commit is contained in:
Brenton Partridge 2021-12-19 01:15:09 -05:00 committed by Mariusz Felisiak
parent e95e6425ac
commit 19fb838803
5 changed files with 21 additions and 14 deletions

View File

@ -2,8 +2,6 @@
This module houses the Geometry Collection objects: This module houses the Geometry Collection objects:
GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon
""" """
from ctypes import byref, c_int, c_uint
from django.contrib.gis.geos import prototypes as capi from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin
from django.contrib.gis.geos.libgeos import GEOM_PTR from django.contrib.gis.geos.libgeos import GEOM_PTR
@ -53,7 +51,7 @@ class GeometryCollection(GEOSGeometry):
# allow GEOSGeometry types (python wrappers) or pointer types # allow GEOSGeometry types (python wrappers) or pointer types
capi.geom_clone(getattr(g, 'ptr', g)) for g in items capi.geom_clone(getattr(g, 'ptr', g)) for g in items
]) ])
return capi.create_collection(c_int(self._typeid), byref(geoms), c_uint(length)) return capi.create_collection(self._typeid, geoms, length)
def _get_single_internal(self, index): def _get_single_internal(self, index):
return capi.get_geomn(self.ptr, index) return capi.get_geomn(self.ptr, index)

View File

@ -1,5 +1,3 @@
from ctypes import byref, c_uint
from django.contrib.gis.geos import prototypes as capi from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.geometry import GEOSGeometry from django.contrib.gis.geos.geometry import GEOSGeometry
from django.contrib.gis.geos.libgeos import GEOM_PTR from django.contrib.gis.geos.libgeos import GEOM_PTR
@ -85,12 +83,11 @@ class Polygon(GEOSGeometry):
n_holes = length - 1 n_holes = length - 1
if n_holes: if n_holes:
holes = (GEOM_PTR * n_holes)(*[self._clone(r) for r in rings]) holes_param = (GEOM_PTR * n_holes)(*[self._clone(r) for r in rings])
holes_param = byref(holes)
else: else:
holes_param = None holes_param = None
return capi.create_polygon(shell, holes_param, c_uint(n_holes)) return capi.create_polygon(shell, holes_param, n_holes)
def _clone(self, g): def _clone(self, g):
if isinstance(g, GEOM_PTR): if isinstance(g, GEOM_PTR):

View File

@ -1,4 +1,4 @@
from ctypes import POINTER, c_char_p, c_int, c_ubyte from ctypes import POINTER, c_char_p, c_int, c_ubyte, c_uint
from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, GEOSFuncFactory from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, GEOSFuncFactory
from django.contrib.gis.geos.prototypes.errcheck import ( from django.contrib.gis.geos.prototypes.errcheck import (
@ -57,11 +57,16 @@ create_point = GeomOutput('GEOSGeom_createPoint', argtypes=[CS_PTR])
create_linestring = GeomOutput('GEOSGeom_createLineString', argtypes=[CS_PTR]) create_linestring = GeomOutput('GEOSGeom_createLineString', argtypes=[CS_PTR])
create_linearring = GeomOutput('GEOSGeom_createLinearRing', argtypes=[CS_PTR]) create_linearring = GeomOutput('GEOSGeom_createLinearRing', argtypes=[CS_PTR])
# Polygon and collection creation routines are special and will not # Polygon and collection creation routines need argument types defined
# have their argument types defined. # for compatibility with some platforms, e.g. macOS ARM64. With argtypes
create_polygon = GeomOutput('GEOSGeom_createPolygon') # defined, arrays are automatically cast and byref() calls are not needed.
create_empty_polygon = GeomOutput('GEOSGeom_createEmptyPolygon') create_polygon = GeomOutput(
create_collection = GeomOutput('GEOSGeom_createCollection') 'GEOSGeom_createPolygon', argtypes=[GEOM_PTR, POINTER(GEOM_PTR), c_uint],
)
create_empty_polygon = GeomOutput('GEOSGeom_createEmptyPolygon', argtypes=[])
create_collection = GeomOutput(
'GEOSGeom_createCollection', argtypes=[c_int, POINTER(GEOM_PTR), c_uint],
)
# Ring routines # Ring routines
get_extring = GeomOutput('GEOSGetExteriorRing', argtypes=[GEOM_PTR]) get_extring = GeomOutput('GEOSGetExteriorRing', argtypes=[GEOM_PTR])

View File

@ -776,6 +776,8 @@ Other Properties & Methods
>>> if poly_1.area > poly_2.area: >>> if poly_1.area > poly_2.area:
>>> pass >>> pass
.. _geos-geometry-collections:
Geometry Collections Geometry Collections
==================== ====================

View File

@ -23,3 +23,8 @@ Bugfixes
* Fixed a regression in Django 4.0 that caused creating bogus migrations for * Fixed a regression in Django 4.0 that caused creating bogus migrations for
models that reference swappable models such as ``auth.User`` models that reference swappable models such as ``auth.User``
(:ticket:`33366`). (:ticket:`33366`).
* Fixed a long standing bug in :ref:`geos-geometry-collections` and
:class:`~django.contrib.gis.geos.Polygon` that caused a crash on some
platforms (reported on macOS based on the ``ARM64`` architecture)
(:ticket:`32600`).