[SCM] PostGIS branch stable-3.5 updated. 3.5.5-22-g396dc1bcc

git at osgeo.org git at osgeo.org
Mon Apr 13 15:04:33 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.5 has been updated
       via  396dc1bcc320bb69d15ff2ad74a5eeb4418e2ae2 (commit)
       via  dc05b0e0fb056784f3a3d400eb54861bc78d6d5a (commit)
       via  dd7d5280d5e294a1fb6e0a915ef1cfff0345fcd2 (commit)
       via  c646c8e8e6c54ef1e201716507237b851e92cd3b (commit)
       via  728235fd0c3df1c74117a63a0defd1b995dfd0d1 (commit)
       via  4c77c0fe93dc70f71d1949c4da04b188e272ca37 (commit)
       via  bcd6d8b43280afc28e3662c5665ffd7fd894d210 (commit)
       via  c07c4cae465d376e2e70f9f80f6216ab8b0f14f5 (commit)
      from  66fcfd047860ee8c675738fe0a40356b7a42ec32 (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 396dc1bcc320bb69d15ff2ad74a5eeb4418e2ae2
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 d0bfd0981..77774839d 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 dc05b0e0fb056784f3a3d400eb54861bc78d6d5a
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 3adfeb055..5bea73a24 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 dd7d5280d5e294a1fb6e0a915ef1cfff0345fcd2
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 57b29ffe2..bc3e6d063 100644
--- a/liblwgeom/measures3d.c
+++ b/liblwgeom/measures3d.c
@@ -1579,6 +1579,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 c646c8e8e6c54ef1e201716507237b851e92cd3b
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 2369bff18..15bf792e7 100644
--- a/liblwgeom/ptarray.c
+++ b/liblwgeom/ptarray.c
@@ -1036,10 +1036,13 @@ ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int chec
 	const POINT2D *seg1, *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 728235fd0c3df1c74117a63a0defd1b995dfd0d1
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 ee9b7d8c0..43a53bb6c 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1360,7 +1360,6 @@ extern uint32_t lwcompound_num_curves(const LWCOMPOUND *compound);
 extern const LWGEOM *lwcollection_getsubcurve(const LWCOMPOUND *compound, uint32_t gnum);
 
 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 LWPOINT* lwpoint_project_lwpoint(const LWPOINT* lwpoint1, const LWPOINT* lwpoint2, double distance);
 extern LWPOINT* lwpoint_project(const LWPOINT* lwpoint1, double distance, double azimuth);
diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h
index 0063b135a..43dc59220 100644
--- a/liblwgeom/liblwgeom_internal.h
+++ b/liblwgeom/liblwgeom_internal.h
@@ -448,7 +448,6 @@ int lw_arc_is_pt(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3);
 int lw_pt_on_segment(const POINT2D* p1, const POINT2D* p2, const POINT2D* p);
 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 56ce3e5ba..010a88e56 100644
--- a/liblwgeom/lwalgorithm.c
+++ b/liblwgeom/lwalgorithm.c
@@ -293,62 +293,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 4c77c0fe93dc70f71d1949c4da04b188e272ca37
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 770acdc6b..f33b0f729 100644
--- a/liblwgeom/lwcompound.c
+++ b/liblwgeom/lwcompound.c
@@ -168,6 +168,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 bcd6d8b43280afc28e3662c5665ffd7fd894d210
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 ca3cdddea..d0bfd0981 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 c07c4cae465d376e2e70f9f80f6216ab8b0f14f5
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 1e0d5c2ee..770acdc6b 100644
--- a/liblwgeom/lwcompound.c
+++ b/liblwgeom/lwcompound.c
@@ -47,31 +47,40 @@ lwcollection_getsubcurve(const LWCOMPOUND *compound, uint32_t curvenum)
 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;
 
-	for (uint32_t i = 0; i < compound->ngeoms; i++)
+	/* 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)
 	{
-		uint32_t i_end = i == 0 ? compound->ngeoms - 1 : i - 1;
-		const LWLINE *geom_start = (LWLINE *)(compound->geoms[i]);
-		const LWLINE *geom_end = (LWLINE *)(compound->geoms[i_end]);
-		const POINTARRAY *pa_start = geom_start->points;
-		const POINTARRAY *pa_end = geom_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;
-		}
+		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;
@@ -84,12 +93,24 @@ lwcompound_is_valid(const LWCOMPOUND *compound)
 	if (lwgeom_is_empty(lwcompound_as_lwgeom(compound)))
 		return LW_TRUE;
 
+	/* Only one component, do not need to test connectivity */
+	if (compound->ngeoms == 1)
+		return LW_TRUE;
+
+	/* Check internal connectivity between components */
 	for (uint32_t i = 1; i < compound->ngeoms; i++)
 	{
-		const LWLINE *geom_start = (LWLINE *)(compound->geoms[i]);
-		const LWLINE *geom_end = (LWLINE *)(compound->geoms[i-1]);
-		const POINTARRAY *pa_start = geom_start->points;
-		const POINTARRAY *pa_end = geom_end->points;
+		const POINTARRAY *pa_start, *pa_end;
+		const LWLINE *line_start = (LWLINE *)(compound->geoms[i]);
+		const LWLINE *line_end = (LWLINE *)(compound->geoms[i-1]);
+
+		/* 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);

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

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


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list