فهرست منبع

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

Brenton Partridge 3 سال پیش
والد
کامیت
19fb838803

+ 1 - 3
django/contrib/gis/geos/collections.py

@@ -2,8 +2,6 @@
  This module houses the Geometry Collection objects:
  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.geometry import GEOSGeometry, LinearGeometryMixin
 from django.contrib.gis.geos.libgeos import GEOM_PTR
@@ -53,7 +51,7 @@ class GeometryCollection(GEOSGeometry):
             # allow GEOSGeometry types (python wrappers) or pointer types
             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):
         return capi.get_geomn(self.ptr, index)

+ 2 - 5
django/contrib/gis/geos/polygon.py

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

+ 11 - 6
django/contrib/gis/geos/prototypes/geom.py

@@ -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.prototypes.errcheck import (
@@ -57,11 +57,16 @@ create_point = GeomOutput('GEOSGeom_createPoint', argtypes=[CS_PTR])
 create_linestring = GeomOutput('GEOSGeom_createLineString', argtypes=[CS_PTR])
 create_linearring = GeomOutput('GEOSGeom_createLinearRing', argtypes=[CS_PTR])
 
-# Polygon and collection creation routines are special and will not
-# have their argument types defined.
-create_polygon = GeomOutput('GEOSGeom_createPolygon')
-create_empty_polygon = GeomOutput('GEOSGeom_createEmptyPolygon')
-create_collection = GeomOutput('GEOSGeom_createCollection')
+# Polygon and collection creation routines need argument types defined
+# for compatibility with some platforms, e.g. macOS ARM64. With argtypes
+# defined, arrays are automatically cast and byref() calls are not needed.
+create_polygon = GeomOutput(
+    '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
 get_extring = GeomOutput('GEOSGetExteriorRing', argtypes=[GEOM_PTR])

+ 2 - 0
docs/ref/contrib/gis/geos.txt

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

+ 5 - 0
docs/releases/4.0.1.txt

@@ -23,3 +23,8 @@ Bugfixes
 * Fixed a regression in Django 4.0 that caused creating bogus migrations for
   models that reference swappable models such as ``auth.User``
   (: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`).