[SCM] PostGIS branch stable-3.3 updated. 3.3.9-22-g102a01e17

git at osgeo.org git at osgeo.org
Mon Apr 13 15:04:28 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.3 has been updated
       via  102a01e1772da6bab7f00e10d3ba59bb4ad14257 (commit)
       via  115776de970e993965e3f9c5dc65ff0aae844f31 (commit)
       via  6d1c0b91486a5c2b96cf84453b159788374981ec (commit)
       via  a3c90cfa25317ad6af5c3f974e0176b2994b6558 (commit)
       via  febb2a5b161cac21fd0fb94089e1af86f265ffbb (commit)
       via  fea8ca4f0b605d4b67e96171889e26f47959b9e9 (commit)
       via  e06b93f22b628f49cc2697144f826dadf2925da5 (commit)
       via  9f00e91bf9217b6d744209e03240b40a9f21624c (commit)
      from  273382ac81dd25af5236f69c36d6414e28928fa1 (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 102a01e1772da6bab7f00e10d3ba59bb4ad14257
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 115776de970e993965e3f9c5dc65ff0aae844f31
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 6d1c0b91486a5c2b96cf84453b159788374981ec
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 a3c90cfa25317ad6af5c3f974e0176b2994b6558
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 febb2a5b161cac21fd0fb94089e1af86f265ffbb
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 9a042f586..91f97076e 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1352,7 +1352,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 cb3565c71..8604ee756 100644
--- a/liblwgeom/liblwgeom_internal.h
+++ b/liblwgeom/liblwgeom_internal.h
@@ -438,7 +438,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 fea8ca4f0b605d4b67e96171889e26f47959b9e9
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 e06b93f22b628f49cc2697144f826dadf2925da5
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 9f00e91bf9217b6d744209e03240b40a9f21624c
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