[SCM] PostGIS branch stable-3.2 updated. 3.2.9-16-gb4ea0262f

git at osgeo.org git at osgeo.org
Mon Apr 13 15:04:21 PDT 2026


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, stable-3.2 has been updated
       via  b4ea0262f3fc1bcf4abaf49c3cd4f4d6d5eb802d (commit)
       via  786b763f08b5fa69fed1783c2c6073a254e1113b (commit)
       via  34e5211f8c0816e13fe81035e8a5587ab798d5ee (commit)
       via  c6da4cf2426b4ee04e8504f22bf18f41f20c5edc (commit)
       via  07a47d8b663472d35a52e601f0967073fb578f0b (commit)
       via  078ff5c64fe11a0aadbd1141d7e9c342a284c15f (commit)
       via  76c1645c281b62be8220a2b2dfd38de388483df8 (commit)
       via  7435e5a94dc11027b933ce023606c5ed431a23df (commit)
      from  4c42e775cf77ea08e3a5999c561f1e8ebcd03ddb (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b4ea0262f3fc1bcf4abaf49c3cd4f4d6d5eb802d
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Apr 10 16:33:36 2026 -0700

    Remove potential null dereference in ptarray_calc_areas()

diff --git a/liblwgeom/effectivearea.c b/liblwgeom/effectivearea.c
index 3c038c5f5..c22bde282 100644
--- a/liblwgeom/effectivearea.c
+++ b/liblwgeom/effectivearea.c
@@ -358,6 +358,9 @@ void ptarray_calc_areas(EFFECTIVE_AREAS *ea, int avoid_collaps, int set_area, do
 	const double *P2;
 	const double *P3;
 
+	if (npoints < 2)
+		lwerror("%s: not enough points provided", __func__);
+
 	P1 = (double*)getPoint_internal(ea->inpts, 0);
 	P2 = (double*)getPoint_internal(ea->inpts, 1);
 

commit 786b763f08b5fa69fed1783c2c6073a254e1113b
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Apr 10 16:33:16 2026 -0700

    Remove potential null dereference in lwcircstring_linearize()

diff --git a/liblwgeom/lwstroke.c b/liblwgeom/lwstroke.c
index ff025ffde..06ef95c78 100644
--- a/liblwgeom/lwstroke.c
+++ b/liblwgeom/lwstroke.c
@@ -565,8 +565,11 @@ lwcircstring_linearize(const LWCIRCSTRING *icurve, double tol,
 			return NULL;
 		}
 	}
-	getPoint4d_p(icurve->points, icurve->points->npoints-1, &p1);
-	ptarray_append_point(ptarray, &p1, LW_FALSE);
+	if (icurve->points->npoints > 0)
+	{
+		getPoint4d_p(icurve->points, icurve->points->npoints-1, &p1);
+		ptarray_append_point(ptarray, &p1, LW_FALSE);
+	}
 
 	oline = lwline_construct(icurve->srid, NULL, ptarray);
 	return oline;

commit 34e5211f8c0816e13fe81035e8a5587ab798d5ee
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Apr 10 15:55:18 2026 -0700

    Remove potential null dereference in pt_in_ring_3d()

diff --git a/liblwgeom/measures3d.c b/liblwgeom/measures3d.c
index 49889bf31..ab9b2387e 100644
--- a/liblwgeom/measures3d.c
+++ b/liblwgeom/measures3d.c
@@ -1580,6 +1580,9 @@ pt_in_ring_3d(const POINT3DZ *p, const POINTARRAY *ring, PLANE3D *plane)
 
 	POINT3DZ first, last;
 
+	if ( !ring || ring->npoints == 0 )
+		lwerror("%s called on empty pointarray", __func__);
+
 	getPoint3dz_p(ring, 0, &first);
 	getPoint3dz_p(ring, ring->npoints - 1, &last);
 	if (memcmp(&first, &last, sizeof(POINT3DZ)))

commit c6da4cf2426b4ee04e8504f22bf18f41f20c5edc
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Apr 10 15:36:05 2026 -0700

    Remove potential null dereference from ptarray_contains_point_partial()

diff --git a/liblwgeom/ptarray.c b/liblwgeom/ptarray.c
index e106d2372..45cdb25b3 100644
--- a/liblwgeom/ptarray.c
+++ b/liblwgeom/ptarray.c
@@ -1023,10 +1023,14 @@ ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int chec
 	const POINT2D *seg2;
 	double ymin, ymax;
 
+	if ( !pa || !pa->npoints )
+		lwerror("%s called on empty pointarray", __func__);
+
 	seg1 = getPoint2d_cp(pa, 0);
 	seg2 = getPoint2d_cp(pa, pa->npoints-1);
+
 	if ( check_closed && ! p2d_same(seg1, seg2) )
-		lwerror("ptarray_contains_point called on unclosed ring");
+		lwerror("%s called on unclosed ring", __func__);
 
 	for ( i=1; i < pa->npoints; i++ )
 	{

commit 07a47d8b663472d35a52e601f0967073fb578f0b
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Apr 10 15:31:16 2026 -0700

    Remove unused function pt_in_ring_2d()

diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index bc74527bf..8b9e556ae 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1351,7 +1351,6 @@ extern LWPOINT* lwcompound_get_endpoint(const LWCOMPOUND *lwcmp);
 extern LWPOINT* lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where);
 
 extern double ptarray_length_2d(const POINTARRAY *pts);
-extern int pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring);
 extern int azimuth_pt_pt(const POINT2D *p1, const POINT2D *p2, double *ret);
 extern int lwpoint_inside_circle(const LWPOINT *p, double cx, double cy, double rad);
 
diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h
index 769822058..1c8249e9e 100644
--- a/liblwgeom/liblwgeom_internal.h
+++ b/liblwgeom/liblwgeom_internal.h
@@ -429,7 +429,6 @@ int lw_pt_in_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const P
 int lw_arc_is_pt(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3);
 double lw_seg_length(const POINT2D *A1, const POINT2D *A2);
 double lw_arc_length(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3);
-int pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring);
 int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt);
 int ptarrayarc_contains_point(const POINTARRAY *pa, const POINT2D *pt);
 int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number);
diff --git a/liblwgeom/lwalgorithm.c b/liblwgeom/lwalgorithm.c
index 3cf3a7d33..1697320c1 100644
--- a/liblwgeom/lwalgorithm.c
+++ b/liblwgeom/lwalgorithm.c
@@ -285,62 +285,6 @@ lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *
 	return cr;
 }
 
-int
-pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring)
-{
-	int cn = 0;    /* the crossing number counter */
-	uint32_t i;
-	const POINT2D *v1, *v2;
-	const POINT2D *first, *last;
-
-	first = getPoint2d_cp(ring, 0);
-	last = getPoint2d_cp(ring, ring->npoints-1);
-	if ( memcmp(first, last, sizeof(POINT2D)) )
-	{
-		lwerror("pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
-		        first->x, first->y, last->x, last->y);
-		return LW_FALSE;
-
-	}
-
-	LWDEBUGF(2, "pt_in_ring_2d called with point: %g %g", p->x, p->y);
-	/* printPA(ring); */
-
-	/* loop through all edges of the polygon */
-	v1 = getPoint2d_cp(ring, 0);
-	for (i=0; i<ring->npoints-1; i++)
-	{
-		double vt;
-		v2 = getPoint2d_cp(ring, i+1);
-
-		/* edge from vertex i to vertex i+1 */
-		if
-		(
-		    /* an upward crossing */
-		    ((v1->y <= p->y) && (v2->y > p->y))
-		    /* a downward crossing */
-		    || ((v1->y > p->y) && (v2->y <= p->y))
-		)
-		{
-
-			vt = (double)(p->y - v1->y) / (v2->y - v1->y);
-
-			/* P->x <intersect */
-			if (p->x < v1->x + vt * (v2->x - v1->x))
-			{
-				/* a valid crossing of y=p->y right of p->x */
-				++cn;
-			}
-		}
-		v1 = v2;
-	}
-
-	LWDEBUGF(3, "pt_in_ring_2d returning %d", cn&1);
-
-	return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
-}
-
-
 static int
 lw_seg_interact(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2)
 {

commit 078ff5c64fe11a0aadbd1141d7e9c342a284c15f
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Apr 10 15:29:19 2026 -0700

    Remove reported crash in lwcompound_add_lwgeom()

diff --git a/liblwgeom/lwcompound.c b/liblwgeom/lwcompound.c
index 78c7db0c2..9368c1c89 100644
--- a/liblwgeom/lwcompound.c
+++ b/liblwgeom/lwcompound.c
@@ -155,6 +155,9 @@ int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom)
 		/* Last point of the previous component */
 		LWLINE *prevline = (LWLINE*)(col->geoms[col->ngeoms-1]);
 
+		if (lwline_is_empty(prevline))
+			return LW_FAILURE;
+
 		getPoint4d_p(newline->points, 0, &first);
 		getPoint4d_p(prevline->points, prevline->points->npoints-1, &last);
 

commit 76c1645c281b62be8220a2b2dfd38de388483df8
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Apr 10 13:56:41 2026 -0700

    Remove reported crash in lwline_set_effective_area()

diff --git a/liblwgeom/effectivearea.c b/liblwgeom/effectivearea.c
index e9859218d..3c038c5f5 100644
--- a/liblwgeom/effectivearea.c
+++ b/liblwgeom/effectivearea.c
@@ -464,7 +464,8 @@ static LWLINE* lwline_set_effective_area(const LWLINE *iline,int set_area, doubl
 
 	LWLINE *oline = lwline_construct_empty(iline->srid, FLAGS_GET_Z(iline->flags), set_m);
 
-
+	if (iline->points->npoints < 2)
+		return oline;
 
 	oline = lwline_construct(iline->srid, NULL, ptarray_set_effective_area(iline->points,2,set_area,trshld));
 
@@ -491,7 +492,12 @@ static LWPOLY* lwpoly_set_effective_area(const LWPOLY *ipoly,int set_area, doubl
 
 	for (i = 0; i < ipoly->nrings; i++)
 	{
-		POINTARRAY *pa = ptarray_set_effective_area(ipoly->rings[i],avoid_collapse,set_area,trshld);
+		POINTARRAY *pa;
+
+		if (ipoly->rings[i]->npoints < 4)
+			continue;
+
+		pa = ptarray_set_effective_area(ipoly->rings[i],avoid_collapse,set_area,trshld);
 		/* Add ring to simplified polygon */
 		if(pa->npoints>=4)
 		{

commit 7435e5a94dc11027b933ce023606c5ed431a23df
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Apr 10 14:56:21 2026 -0700

    Remove reported crash in lwcompound_is_closed()

diff --git a/liblwgeom/lwcompound.c b/liblwgeom/lwcompound.c
index f7363d069..78c7db0c2 100644
--- a/liblwgeom/lwcompound.c
+++ b/liblwgeom/lwcompound.c
@@ -29,43 +29,94 @@
 #include "liblwgeom_internal.h"
 #include "lwgeom_log.h"
 
-
-
-int
-lwcompound_is_closed(const LWCOMPOUND *compound)
+static int
+lwcompound_is_valid(const LWCOMPOUND *compound)
 {
-	size_t size;
-	int npoints=0;
+	int hasz = lwgeom_has_z(lwcompound_as_lwgeom(compound));
+	if (lwgeom_is_empty(lwcompound_as_lwgeom(compound)))
+		return LW_TRUE;
 
-	if ( lwgeom_has_z((LWGEOM*)compound) )
-	{
-		size = sizeof(POINT3D);
-	}
-	else
-	{
-		size = sizeof(POINT2D);
-	}
+	/* Only one component, do not need to test connectivity */
+	if (compound->ngeoms == 1)
+		return LW_TRUE;
 
-	if ( compound->geoms[compound->ngeoms - 1]->type == CIRCSTRINGTYPE )
+	/* Check internal connectivity between components */
+	for (uint32_t i = 1; i < compound->ngeoms; i++)
 	{
-		npoints = ((LWCIRCSTRING *)compound->geoms[compound->ngeoms - 1])->points->npoints;
-	}
-	else if (compound->geoms[compound->ngeoms - 1]->type == LINETYPE)
-	{
-		npoints = ((LWLINE *)compound->geoms[compound->ngeoms - 1])->points->npoints;
-	}
+		const POINTARRAY *pa_start, *pa_end;
+		const LWLINE *line_start = (LWLINE *)(compound->geoms[i]);
+		const LWLINE *line_end = (LWLINE *)(compound->geoms[i-1]);
 
-	if ( memcmp(getPoint_internal( (POINTARRAY *)compound->geoms[0]->data, 0),
-	            getPoint_internal( (POINTARRAY *)compound->geoms[compound->ngeoms - 1]->data,
-	                               npoints - 1),
-	            size) )
-	{
-		return LW_FALSE;
+		/* Empty cannot be a compound component, because it joins nothing */
+		if (lwline_is_empty(line_start) || (lwline_is_empty(line_end)))
+			return LW_FALSE;
+
+		pa_start = line_start->points;
+		pa_end = line_end->points;
+
+		if (hasz)
+		{
+			const POINT3D *pt_start = getPoint3d_cp(pa_start, 0);
+			const POINT3D *pt_end = getPoint3d_cp(pa_end, pa_end->npoints-1);
+			if (!p3d_same(pt_start, pt_end))
+				return LW_FALSE;
+		}
+		else
+		{
+			const POINT2D *pt_start = getPoint2d_cp(pa_start, 0);
+			const POINT2D *pt_end = getPoint2d_cp(pa_end, pa_end->npoints-1);
+			if (!p2d_same(pt_start, pt_end))
+				return LW_FALSE;
+		}
 	}
 
 	return LW_TRUE;
 }
 
+int
+lwcompound_is_closed(const LWCOMPOUND *compound)
+{
+	const LWLINE *line_start, *line_end;
+	const POINTARRAY *pa_start, *pa_end;
+
+	int hasz = lwgeom_has_z(lwcompound_as_lwgeom(compound));
+	if (lwgeom_is_empty(lwcompound_as_lwgeom(compound)))
+		return LW_FALSE;
+
+	/* Single entry, closes on itself */
+	if (compound->ngeoms == 1 && lwline_is_closed((LWLINE *)(compound->geoms[0])))
+			return LW_TRUE;
+
+	/* If internal connectivity is lacking, so is closure */
+	if (!lwcompound_is_valid(compound))
+		return LW_FALSE;
+
+	/* Internal connection is good, what about start/end points? */
+	line_start = (LWLINE *)(compound->geoms[0]);
+	line_end = (LWLINE *)(compound->geoms[compound->ngeoms-1]);
+	pa_start = line_start->points;
+	pa_end = line_end->points;
+
+	if (hasz)
+	{
+		const POINT3D *pt_start = getPoint3d_cp(pa_start, 0);
+		const POINT3D *pt_end = getPoint3d_cp(pa_end, pa_end->npoints-1);
+		if (!p3d_same(pt_start, pt_end))
+			return LW_FALSE;
+	}
+	else
+	{
+		const POINT2D *pt_start = getPoint2d_cp(pa_start, 0);
+		const POINT2D *pt_end = getPoint2d_cp(pa_end, pa_end->npoints-1);
+		if (!p2d_same(pt_start, pt_end))
+			return LW_FALSE;
+	}
+
+	return LW_TRUE;
+}
+
+
+
 double lwcompound_length(const LWCOMPOUND *comp)
 {
 	return lwcompound_length_2d(comp);

-----------------------------------------------------------------------

Summary of changes:
 liblwgeom/effectivearea.c      | 13 +++++-
 liblwgeom/liblwgeom.h.in       |  1 -
 liblwgeom/liblwgeom_internal.h |  1 -
 liblwgeom/lwalgorithm.c        | 56 ------------------------
 liblwgeom/lwcompound.c         | 98 ++++++++++++++++++++++++++++++++----------
 liblwgeom/lwstroke.c           |  7 ++-
 liblwgeom/measures3d.c         |  3 ++
 liblwgeom/ptarray.c            |  6 ++-
 8 files changed, 100 insertions(+), 85 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list