[SCM] PostGIS branch master updated. 3.4.0rc1-923-g5560fb5cd

git at osgeo.org git at osgeo.org
Fri Feb 9 09:35:01 PST 2024


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, master has been updated
       via  5560fb5cd14162a2d170a464f9e2b13e8998b1f7 (commit)
       via  8d0df58cd89fd652bd4b50ec7eed12af22f431f1 (commit)
       via  0412f69ac4b2999cb9e33cb0a7884be74511ecd5 (commit)
       via  14d904bb63cabfadc5465fbcb1a1d211d5c84dad (commit)
       via  b26d7ebd81a1d8cfeecd2cf95e2634f0f8968652 (commit)
       via  8efa9b214e72d52188518a9f46859cfb98b4c612 (commit)
       via  4bac13b03d659fb59db1432b23c56b9e0fa604f3 (commit)
       via  915d308448b39bafc73b66786701aa27cac722d5 (commit)
       via  4ecb7100c90ec3ef23a5249bfa52a3e20f2f3542 (commit)
      from  7038255354da9e2402db3612090953d9af8424a9 (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 5560fb5cd14162a2d170a464f9e2b13e8998b1f7
Merge: 703825535 8d0df58cd
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Feb 9 09:34:53 2024 -0800

    Merge branch 'rouault-codeql'


commit 8d0df58cd89fd652bd4b50ec7eed12af22f431f1
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Thu Feb 8 12:07:24 2024 -0800

    const correctness in XML patch

diff --git a/postgis/lwgeom_in_gml.c b/postgis/lwgeom_in_gml.c
index 6bdb81998..f1eafb572 100644
--- a/postgis/lwgeom_in_gml.c
+++ b/postgis/lwgeom_in_gml.c
@@ -126,8 +126,8 @@ Datum geom_from_gml(PG_FUNCTION_ARGS)
 static inline bool
 is_gml_element(xmlNodePtr xn, const char *gml_name)
 {
-	char *colon_pos;
-	char *node_name;
+	const char *colon_pos;
+	const char *node_name;
 
 	/* Not an element node, can't do anything */
 	if (!xn || xn->type != XML_ELEMENT_NODE)
@@ -136,7 +136,7 @@ is_gml_element(xmlNodePtr xn, const char *gml_name)
 	/* If there's a colon in the element name, */
 	/* move past it before checking for equality with */
 	/* the element name we are looking for */
-	node_name = (char*)xn->name;
+	node_name = (const char*)xn->name;
 	colon_pos = strchr(node_name, ':');
 	if (colon_pos)
 		node_name = colon_pos + 1;
diff --git a/postgis/lwgeom_in_kml.c b/postgis/lwgeom_in_kml.c
index 0185587a3..38f3f5c59 100644
--- a/postgis/lwgeom_in_kml.c
+++ b/postgis/lwgeom_in_kml.c
@@ -67,8 +67,8 @@ static LWGEOM* parse_kml(xmlNodePtr xnode, bool *hasz);
 static inline bool
 is_kml_element(xmlNodePtr xn, const char *kml_name)
 {
-	char *colon_pos;
-	char *node_name;
+	const char *colon_pos;
+	const char *node_name;
 
 	/* Not an element node, can't do anything */
 	if (!xn || xn->type != XML_ELEMENT_NODE)
@@ -77,7 +77,7 @@ is_kml_element(xmlNodePtr xn, const char *kml_name)
 	/* If there's a colon in the element name, */
 	/* move past it before checking for equality with */
 	/* the element name we are looking for */
-	node_name = (char*)xn->name;
+	node_name = (const char*)xn->name;
 	colon_pos = strchr(node_name, ':');
 	if (colon_pos)
 		node_name = colon_pos + 1;
@@ -111,7 +111,6 @@ Datum geom_from_kml(PG_FUNCTION_ARGS)
 	/* Begin to Parse XML doc */
 	xmlInitParser();
 	xmldoc = xmlReadMemory(xml, xml_size, NULL, NULL, 0);
-	// xmldoc = xmlReadMemory(xml, xml_size, NULL, NULL, XML_PARSE_SAX1);
 	if (!xmldoc || (xmlroot = xmlDocGetRootElement(xmldoc)) == NULL)
 	{
 		xmlFreeDoc(xmldoc);
diff --git a/postgis/lwgeom_in_marc21.c b/postgis/lwgeom_in_marc21.c
index 282db4d56..8b4974fc4 100644
--- a/postgis/lwgeom_in_marc21.c
+++ b/postgis/lwgeom_in_marc21.c
@@ -94,7 +94,8 @@ Datum ST_GeomFromMARC21(PG_FUNCTION_ARGS) {
 static inline bool
 is_xml_element(xmlNodePtr xn, const char *xml_name)
 {
-	char *colon_pos, *node_name;
+	const char *colon_pos;
+	const char *node_name;
 
 	/* Not an element node, can't do anything */
 	if (!xn || xn->type != XML_ELEMENT_NODE)
@@ -103,7 +104,7 @@ is_xml_element(xmlNodePtr xn, const char *xml_name)
 	/* If there's a colon in the element name, */
 	/* move past it before checking for equality with */
 	/* the element name we are looking for */
-	node_name = (char*)xn->name;
+	node_name = (const char*)xn->name;
 	colon_pos = strchr(node_name, ':');
 	if (colon_pos)
 		node_name = colon_pos + 1;

commit 0412f69ac4b2999cb9e33cb0a7884be74511ecd5
Author: Sandro Santilli <strk at kbt.io>
Date:   Wed Feb 7 23:18:04 2024 +0100

    Improve error message for bogus argument to --with-gdalconfig

diff --git a/configure.ac b/configure.ac
index 74808d679..15f821673 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1585,9 +1585,15 @@ if test "x$with_raster" != "xno"; then
 	AC_ARG_WITH(
 		[gdalconfig],
 		AS_HELP_STRING([--with-gdalconfig=@<:@ARG@:>@],[specify location of gdal-config (ARG=path).  Only used with --with-raster]),
-		[GDAL_CONFIG="$withval"],
+		[
+			if test -f "$withval"; then
+				GDAL_CONFIG="$withval"
+			else
+				AC_MSG_ERROR([the user-specified gdal-config file $withval does not exist])
+			fi
+		],
 		[AC_PATH_PROG([GDAL_CONFIG], [gdal-config], [])]
-  )
+	)
 
 	AC_MSG_CHECKING([GDAL version])
 

commit 14d904bb63cabfadc5465fbcb1a1d211d5c84dad
Author: Even Rouault <even.rouault at spatialys.com>
Date:   Wed Feb 7 19:41:27 2024 +0100

    Better check for sscanf() return

diff --git a/postgis/lwgeom_spheroid.c b/postgis/lwgeom_spheroid.c
index 3b6f0b2bb..ca50126eb 100644
--- a/postgis/lwgeom_spheroid.c
+++ b/postgis/lwgeom_spheroid.c
@@ -96,7 +96,7 @@ Datum ellipsoid_in(PG_FUNCTION_ARGS)
 	nitems = sscanf(str,"SPHEROID[\"%19[^\"]\",%lf,%lf]",
 	                sphere->name, &sphere->a, &rf);
 
-	if ( nitems==0)
+	if (nitems != 3)
 		nitems = sscanf(str,"SPHEROID(\"%19[^\"]\",%lf,%lf)",
 		                sphere->name, &sphere->a, &rf);
 

commit b26d7ebd81a1d8cfeecd2cf95e2634f0f8968652
Author: Even Rouault <even.rouault at spatialys.com>
Date:   Wed Feb 7 19:40:10 2024 +0100

    Fix various CodeQL' 'Comparison of narrow type with wide type in loop condition' warnings

diff --git a/postgis/gserialized_estimate.c b/postgis/gserialized_estimate.c
index 4790b3373..d182d79dc 100644
--- a/postgis/gserialized_estimate.c
+++ b/postgis/gserialized_estimate.c
@@ -2492,7 +2492,7 @@ spatial_index_read_extent(Oid idx_oid, int key_type, int att_num)
 	Relation idx_rel;
 	Buffer buffer;
 	Page page;
-	OffsetNumber offset;
+	unsigned long offset;
 	unsigned long offset_max;
 
 	if (!idx_oid)
diff --git a/postgis/gserialized_gist_2d.c b/postgis/gserialized_gist_2d.c
index a474060d9..6e2c28e5e 100644
--- a/postgis/gserialized_gist_2d.c
+++ b/postgis/gserialized_gist_2d.c
@@ -2069,7 +2069,7 @@ Datum gserialized_gist_picksplit_2d(PG_FUNCTION_ARGS)
 		 * Calculate delta between penalties of join "common entries" to
 		 * different groups.
 		 */
-		for (i = 0; i < commonEntriesCount; i++)
+		for (i = 0; i < (OffsetNumber)commonEntriesCount; i++)
 		{
 			box = (BOX2DF *) DatumGetPointer(entryvec->vector[
 												commonEntries[i].index].key);
@@ -2086,7 +2086,7 @@ Datum gserialized_gist_picksplit_2d(PG_FUNCTION_ARGS)
 		/*
 		 * Distribute "common entries" between groups.
 		 */
-		for (i = 0; i < commonEntriesCount; i++)
+		for (i = 0; i < (OffsetNumber)commonEntriesCount; i++)
 		{
 			float right_penalty, left_penalty;
 			bool place_right = true;
diff --git a/postgis/gserialized_spgist_2d.c b/postgis/gserialized_spgist_2d.c
index 098224a58..069dfedc3 100644
--- a/postgis/gserialized_spgist_2d.c
+++ b/postgis/gserialized_spgist_2d.c
@@ -449,7 +449,7 @@ PGDLLEXPORT Datum gserialized_spgist_inner_consistent_2d(PG_FUNCTION_ARGS)
 	 */
 	old_ctx = MemoryContextSwitchTo(in->traversalMemoryContext);
 
-	for (quadrant = 0; quadrant < in->nNodes; quadrant++)
+	for (quadrant = 0; quadrant < (uint8)in->nNodes; quadrant++)
 	{
 		RectBox *next_rect_box = nextRectBox(rect_box, centroid, quadrant);
 		bool flag = true;
diff --git a/postgis/gserialized_spgist_3d.c b/postgis/gserialized_spgist_3d.c
index 886338a8c..48d49459d 100644
--- a/postgis/gserialized_spgist_3d.c
+++ b/postgis/gserialized_spgist_3d.c
@@ -550,7 +550,7 @@ PGDLLEXPORT Datum gserialized_spgist_inner_consistent_3d(PG_FUNCTION_ARGS)
 	 */
 	old_ctx = MemoryContextSwitchTo(in->traversalMemoryContext);
 
-	for (octant = 0; octant < in->nNodes; octant++)
+	for (octant = 0; octant < (uint8)in->nNodes; octant++)
 	{
 		CubeBox3D *next_cube_box = nextCubeBox3D(cube_box, centroid, octant);
 		bool flag = true;

commit 8efa9b214e72d52188518a9f46859cfb98b4c612
Author: Even Rouault <even.rouault at spatialys.com>
Date:   Wed Feb 7 19:35:33 2024 +0100

    Fix various CodeQL' 'Multiplication result converted to larger type' warnings

diff --git a/liblwgeom/gserialized1.c b/liblwgeom/gserialized1.c
index 1a87ccf52..dab925a51 100644
--- a/liblwgeom/gserialized1.c
+++ b/liblwgeom/gserialized1.c
@@ -592,7 +592,7 @@ static size_t gserialized1_from_lwpoint_size(const LWPOINT *point)
 	assert(point);
 
 	size += 4; /* Number of points (one or zero (empty)). */
-	size += point->point->npoints * FLAGS_NDIMS(point->flags) * sizeof(double);
+	size += sizeof(double) * point->point->npoints * FLAGS_NDIMS(point->flags);
 
 	LWDEBUGF(3, "point size = %d", size);
 
@@ -606,7 +606,7 @@ static size_t gserialized1_from_lwline_size(const LWLINE *line)
 	assert(line);
 
 	size += 4; /* Number of points (zero => empty). */
-	size += line->points->npoints * FLAGS_NDIMS(line->flags) * sizeof(double);
+	size += sizeof(double) * line->points->npoints * FLAGS_NDIMS(line->flags);
 
 	LWDEBUGF(3, "linestring size = %d", size);
 
@@ -620,7 +620,7 @@ static size_t gserialized1_from_lwtriangle_size(const LWTRIANGLE *triangle)
 	assert(triangle);
 
 	size += 4; /* Number of points (zero => empty). */
-	size += triangle->points->npoints * FLAGS_NDIMS(triangle->flags) * sizeof(double);
+	size += sizeof(double) * triangle->points->npoints * FLAGS_NDIMS(triangle->flags);
 
 	LWDEBUGF(3, "triangle size = %d", size);
 
@@ -641,7 +641,7 @@ static size_t gserialized1_from_lwpoly_size(const LWPOLY *poly)
 	for ( i = 0; i < poly->nrings; i++ )
 	{
 		size += 4; /* Number of points in ring. */
-		size += poly->rings[i]->npoints * FLAGS_NDIMS(poly->flags) * sizeof(double);
+		size += sizeof(double) * poly->rings[i]->npoints * FLAGS_NDIMS(poly->flags);
 	}
 
 	LWDEBUGF(3, "polygon size = %d", size);
@@ -656,7 +656,7 @@ static size_t gserialized1_from_lwcircstring_size(const LWCIRCSTRING *curve)
 	assert(curve);
 
 	size += 4; /* Number of points (zero => empty). */
-	size += curve->points->npoints * FLAGS_NDIMS(curve->flags) * sizeof(double);
+	size += sizeof(double) * curve->points->npoints * FLAGS_NDIMS(curve->flags);
 
 	LWDEBUGF(3, "circstring size = %d", size);
 
@@ -806,7 +806,7 @@ static size_t gserialized1_from_lwline(const LWLINE *line, uint8_t *buf)
 	/* Copy in the ordinates. */
 	if ( line->points->npoints > 0 )
 	{
-		size = line->points->npoints * ptsize;
+		size = (size_t)line->points->npoints * ptsize;
 		memcpy(loc, getPoint_internal(line->points, 0), size);
 		loc += size;
 	}
@@ -861,7 +861,7 @@ static size_t gserialized1_from_lwpoly(const LWPOLY *poly, uint8_t *buf)
 		if ( FLAGS_GET_ZM(poly->flags) != FLAGS_GET_ZM(pa->flags) )
 			lwerror("Dimensions mismatch in lwpoly");
 
-		pasize = pa->npoints * ptsize;
+		pasize = (size_t)pa->npoints * ptsize;
 		if ( pa->npoints > 0 )
 			memcpy(loc, getPoint_internal(pa, 0), pasize);
 		loc += pasize;
@@ -901,7 +901,7 @@ static size_t gserialized1_from_lwtriangle(const LWTRIANGLE *triangle, uint8_t *
 	/* Copy in the ordinates. */
 	if ( triangle->points->npoints > 0 )
 	{
-		size = triangle->points->npoints * ptsize;
+		size = (size_t)triangle->points->npoints * ptsize;
 		memcpy(loc, getPoint_internal(triangle->points, 0), size);
 		loc += size;
 	}
@@ -938,7 +938,7 @@ static size_t gserialized1_from_lwcircstring(const LWCIRCSTRING *curve, uint8_t
 	/* Copy in the ordinates. */
 	if ( curve->points->npoints > 0 )
 	{
-		size = curve->points->npoints * ptsize;
+		size = (size_t)curve->points->npoints * ptsize;
 		memcpy(loc, getPoint_internal(curve->points, 0), size);
 		loc += size;
 	}
@@ -1184,7 +1184,7 @@ static LWPOINT* lwpoint_from_gserialized1_buffer(uint8_t *data_ptr, lwflags_t lw
 	else
 		point->point = ptarray_construct(FLAGS_GET_Z(lwflags), FLAGS_GET_M(lwflags), 0); /* Empty point */
 
-	data_ptr += npoints * FLAGS_NDIMS(lwflags) * sizeof(double);
+	data_ptr += sizeof(double) * npoints * FLAGS_NDIMS(lwflags);
 
 	if ( size )
 		*size = data_ptr - start_ptr;
@@ -1216,7 +1216,7 @@ static LWLINE* lwline_from_gserialized1_buffer(uint8_t *data_ptr, lwflags_t lwfl
 	else
 		line->points = ptarray_construct(FLAGS_GET_Z(lwflags), FLAGS_GET_M(lwflags), 0); /* Empty linestring */
 
-	data_ptr += FLAGS_NDIMS(lwflags) * npoints * sizeof(double);
+	data_ptr += sizeof(double) * FLAGS_NDIMS(lwflags) * npoints;
 
 	if ( size )
 		*size = data_ptr - start_ptr;
@@ -1304,7 +1304,7 @@ static LWTRIANGLE* lwtriangle_from_gserialized1_buffer(uint8_t *data_ptr, lwflag
 	else
 		triangle->points = ptarray_construct(FLAGS_GET_Z(lwflags), FLAGS_GET_M(lwflags), 0); /* Empty triangle */
 
-	data_ptr += FLAGS_NDIMS(lwflags) * npoints * sizeof(double);
+	data_ptr += sizeof(double) * FLAGS_NDIMS(lwflags) * npoints;
 
 	if ( size )
 		*size = data_ptr - start_ptr;
@@ -1335,7 +1335,7 @@ static LWCIRCSTRING* lwcircstring_from_gserialized1_buffer(uint8_t *data_ptr, lw
 	else
 		circstring->points = ptarray_construct(FLAGS_GET_Z(lwflags), FLAGS_GET_M(lwflags), 0); /* Empty circularstring */
 
-	data_ptr += FLAGS_NDIMS(lwflags) * npoints * sizeof(double);
+	data_ptr += sizeof(double) * FLAGS_NDIMS(lwflags) * npoints;
 
 	if ( size )
 		*size = data_ptr - start_ptr;
diff --git a/liblwgeom/gserialized2.c b/liblwgeom/gserialized2.c
index e9dc77bb5..dfa6c0ad2 100644
--- a/liblwgeom/gserialized2.c
+++ b/liblwgeom/gserialized2.c
@@ -645,7 +645,7 @@ static size_t gserialized2_from_lwpoint_size(const LWPOINT *point)
 	assert(point);
 
 	size += 4; /* Number of points (one or zero (empty)). */
-	size += point->point->npoints * FLAGS_NDIMS(point->flags) * sizeof(double);
+	size += sizeof(double) * point->point->npoints * FLAGS_NDIMS(point->flags);
 
 	LWDEBUGF(3, "point size = %d", size);
 
@@ -659,7 +659,7 @@ static size_t gserialized2_from_lwline_size(const LWLINE *line)
 	assert(line);
 
 	size += 4; /* Number of points (zero => empty). */
-	size += line->points->npoints * FLAGS_NDIMS(line->flags) * sizeof(double);
+	size += sizeof(double) * line->points->npoints * FLAGS_NDIMS(line->flags);
 
 	LWDEBUGF(3, "linestring size = %d", size);
 
@@ -673,7 +673,7 @@ static size_t gserialized2_from_lwtriangle_size(const LWTRIANGLE *triangle)
 	assert(triangle);
 
 	size += 4; /* Number of points (zero => empty). */
-	size += triangle->points->npoints * FLAGS_NDIMS(triangle->flags) * sizeof(double);
+	size += sizeof(double)* triangle->points->npoints * FLAGS_NDIMS(triangle->flags);
 
 	LWDEBUGF(3, "triangle size = %d", size);
 
@@ -710,7 +710,7 @@ static size_t gserialized2_from_lwcircstring_size(const LWCIRCSTRING *curve)
 	assert(curve);
 
 	size += 4; /* Number of points (zero => empty). */
-	size += curve->points->npoints * FLAGS_NDIMS(curve->flags) * sizeof(double);
+	size += sizeof(double) * curve->points->npoints * FLAGS_NDIMS(curve->flags);
 
 	LWDEBUGF(3, "circstring size = %d", size);
 
@@ -865,7 +865,7 @@ static size_t gserialized2_from_lwline(const LWLINE *line, uint8_t *buf)
 	/* Copy in the ordinates. */
 	if (line->points->npoints > 0)
 	{
-		size = line->points->npoints * ptsize;
+		size = (size_t)line->points->npoints * ptsize;
 		memcpy(loc, getPoint_internal(line->points, 0), size);
 		loc += size;
 	}
@@ -920,7 +920,7 @@ static size_t gserialized2_from_lwpoly(const LWPOLY *poly, uint8_t *buf)
 		if (FLAGS_GET_ZM(poly->flags) != FLAGS_GET_ZM(pa->flags))
 			lwerror("Dimensions mismatch in lwpoly");
 
-		pasize = pa->npoints * ptsize;
+		pasize = (size_t)pa->npoints * ptsize;
 		if ( pa->npoints > 0 )
 			memcpy(loc, getPoint_internal(pa, 0), pasize);
 		loc += pasize;
@@ -960,7 +960,7 @@ static size_t gserialized2_from_lwtriangle(const LWTRIANGLE *triangle, uint8_t *
 	/* Copy in the ordinates. */
 	if (triangle->points->npoints > 0)
 	{
-		size = triangle->points->npoints * ptsize;
+		size = (size_t)triangle->points->npoints * ptsize;
 		memcpy(loc, getPoint_internal(triangle->points, 0), size);
 		loc += size;
 	}
@@ -997,7 +997,7 @@ static size_t gserialized2_from_lwcircstring(const LWCIRCSTRING *curve, uint8_t
 	/* Copy in the ordinates. */
 	if (curve->points->npoints > 0)
 	{
-		size = curve->points->npoints * ptsize;
+		size = (size_t)curve->points->npoints * ptsize;
 		memcpy(loc, getPoint_internal(curve->points, 0), size);
 		loc += size;
 	}
@@ -1231,7 +1231,7 @@ lwpoint_from_gserialized2_buffer(uint8_t *data_ptr, lwflags_t lwflags, size_t *s
 	else
 		point->point = ptarray_construct(FLAGS_GET_Z(lwflags), FLAGS_GET_M(lwflags), 0); /* Empty point */
 
-	data_ptr += npoints * FLAGS_NDIMS(lwflags) * sizeof(double);
+	data_ptr += sizeof(double) * npoints * FLAGS_NDIMS(lwflags);
 
 	if (size)
 		*size = data_ptr - start_ptr;
@@ -1264,7 +1264,7 @@ lwline_from_gserialized2_buffer(uint8_t *data_ptr, lwflags_t lwflags, size_t *si
 	else
 		line->points = ptarray_construct(FLAGS_GET_Z(lwflags), FLAGS_GET_M(lwflags), 0); /* Empty linestring */
 
-	data_ptr += FLAGS_NDIMS(lwflags) * npoints * sizeof(double);
+	data_ptr += sizeof(double) * FLAGS_NDIMS(lwflags) * npoints;
 
 	if (size)
 		*size = data_ptr - start_ptr;
@@ -1354,7 +1354,7 @@ lwtriangle_from_gserialized2_buffer(uint8_t *data_ptr, lwflags_t lwflags, size_t
 	else
 		triangle->points = ptarray_construct(FLAGS_GET_Z(lwflags), FLAGS_GET_M(lwflags), 0); /* Empty triangle */
 
-	data_ptr += FLAGS_NDIMS(lwflags) * npoints * sizeof(double);
+	data_ptr += sizeof(double) * FLAGS_NDIMS(lwflags) * npoints;
 
 	if (size)
 		*size = data_ptr - start_ptr;
@@ -1386,7 +1386,7 @@ lwcircstring_from_gserialized2_buffer(uint8_t *data_ptr, lwflags_t lwflags, size
 	else
 		circstring->points = ptarray_construct(FLAGS_GET_Z(lwflags), FLAGS_GET_M(lwflags), 0); /* Empty circularstring */
 
-	data_ptr += FLAGS_NDIMS(lwflags) * npoints * sizeof(double);
+	data_ptr += sizeof(double) * FLAGS_NDIMS(lwflags) * npoints;
 
 	if (size)
 		*size = data_ptr - start_ptr;
diff --git a/liblwgeom/lwin_wkb.c b/liblwgeom/lwin_wkb.c
index 979be17f9..9b6e24fcd 100644
--- a/liblwgeom/lwin_wkb.c
+++ b/liblwgeom/lwin_wkb.c
@@ -368,7 +368,7 @@ static POINTARRAY* ptarray_from_wkb_state(wkb_parse_state *s)
 
 	if( s->has_z ) ndims++;
 	if( s->has_m ) ndims++;
-	pa_size = npoints * ndims * WKB_DOUBLE_SIZE;
+	pa_size = (size_t)npoints * ndims * WKB_DOUBLE_SIZE;
 
 	/* Empty! */
 	if( npoints == 0 )
diff --git a/liblwgeom/lwout_twkb.c b/liblwgeom/lwout_twkb.c
index 6d099f6a6..b49809300 100644
--- a/liblwgeom/lwout_twkb.c
+++ b/liblwgeom/lwout_twkb.c
@@ -134,7 +134,7 @@ static int ptarray_to_twkb_buf(const POINTARRAY *pa, TWKB_GLOBALS *globals, TWKB
 	{
 		/* Independent buffer to hold the coordinates, so we can put the npoints */
 		/* into the stream once we know how many points we actually have */
-		bytebuffer_init_with_size(&b, 3 * ndims * pa->npoints);
+		bytebuffer_init_with_size(&b, (size_t)3 * ndims * pa->npoints);
 		b_p = &b;
 	}
 	else
diff --git a/liblwgeom/lwout_wkb.c b/liblwgeom/lwout_wkb.c
index 3de8b5b5e..147c948c1 100644
--- a/liblwgeom/lwout_wkb.c
+++ b/liblwgeom/lwout_wkb.c
@@ -390,7 +390,7 @@ static size_t ptarray_to_wkb_size(const POINTARRAY *pa, uint8_t variant)
 		size += WKB_INT_SIZE;
 
 	/* size of the double list */
-	size += pa->npoints * dims * WKB_DOUBLE_SIZE;
+	size += (size_t)pa->npoints * dims * WKB_DOUBLE_SIZE;
 
 	return size;
 }
@@ -414,7 +414,7 @@ static uint8_t* ptarray_to_wkb_buf(const POINTARRAY *pa, uint8_t *buf, uint8_t v
 	/* is not hex, and output endian matches internal endian. */
 	if ( pa->npoints && (dims == pa_dims) && ! wkb_swap_bytes(variant) && ! (variant & WKB_HEX)  )
 	{
-		size_t size = pa->npoints * dims * WKB_DOUBLE_SIZE;
+		size_t size = (size_t)pa->npoints * dims * WKB_DOUBLE_SIZE;
 		memcpy(buf, getPoint_internal(pa, 0), size);
 		buf += size;
 	}
diff --git a/liblwgeom/ptarray.c b/liblwgeom/ptarray.c
index e4bb380ce..7d9c8c0cd 100644
--- a/liblwgeom/ptarray.c
+++ b/liblwgeom/ptarray.c
@@ -232,11 +232,11 @@ ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance)
 	{
 		pa1->maxpoints = ncap > pa1->maxpoints*2 ?
 		                 ncap : pa1->maxpoints*2;
-		pa1->serialized_pointlist = lwrealloc(pa1->serialized_pointlist, ptsize * pa1->maxpoints);
+		pa1->serialized_pointlist = lwrealloc(pa1->serialized_pointlist, (size_t)ptsize * pa1->maxpoints);
 	}
 
 	memcpy(getPoint_internal(pa1, pa1->npoints),
-	       getPoint_internal(pa2, poff), ptsize * npoints);
+	       getPoint_internal(pa2, poff), (size_t)ptsize * npoints);
 
 	pa1->npoints = ncap;
 
@@ -2215,12 +2215,12 @@ ptarray_scroll_in_place(POINTARRAY *pa, const POINT4D *pt)
 	/* TODO: reduce allocations */
 	tmp = ptarray_construct(FLAGS_GET_Z(pa->flags), FLAGS_GET_M(pa->flags), pa->npoints);
 
-	bzero(getPoint_internal(tmp, 0), ptsize * pa->npoints);
+	bzero(getPoint_internal(tmp, 0), (size_t)ptsize * pa->npoints);
 	/* Copy the block from found point to last point into the output array */
 	memcpy(
 		getPoint_internal(tmp, 0),
 		getPoint_internal(pa, it),
-		ptsize * ( pa->npoints - it )
+		(size_t)ptsize * ( pa->npoints - it )
 	);
 
 	/* Copy the block from second point to the found point into the last portion of the
@@ -2228,14 +2228,14 @@ ptarray_scroll_in_place(POINTARRAY *pa, const POINT4D *pt)
 	memcpy(
 		getPoint_internal(tmp, pa->npoints - it),
 		getPoint_internal(pa, 1),
-		ptsize * ( it )
+		(size_t)ptsize * ( it )
 	);
 
 	/* Copy the resulting pointarray back to source one */
 	memcpy(
 		getPoint_internal(pa, 0),
 		getPoint_internal(tmp, 0),
-		ptsize * ( pa->npoints )
+		(size_t)ptsize * ( pa->npoints )
 	);
 
 	ptarray_free(tmp);
diff --git a/postgis/geobuf.c b/postgis/geobuf.c
index 485902c9f..da2bd3ff0 100644
--- a/postgis/geobuf.c
+++ b/postgis/geobuf.c
@@ -200,7 +200,7 @@ static Data__Geometry *encode_point(struct geobuf_agg_context *ctx,
 	if (npoints == 0)
 		return geometry;
 
-	geometry->n_coords = npoints * ctx->dimensions;
+	geometry->n_coords = (size_t)npoints * ctx->dimensions;
 	geometry->coords = encode_coords(ctx, pa, NULL, 1, 0);
 
 	return geometry;
@@ -228,7 +228,7 @@ static Data__Geometry *encode_mpoint(struct geobuf_agg_context *ctx,
 		ptarray_append_point(pa, &pt, 0);
 	}
 
-	geometry->n_coords = ngeoms * ctx->dimensions;
+	geometry->n_coords = (size_t)ngeoms * ctx->dimensions;
 	geometry->coords = encode_coords(ctx, pa, NULL, ngeoms, 0);
 
 	return geometry;
@@ -247,7 +247,7 @@ static Data__Geometry *encode_line(struct geobuf_agg_context *ctx,
 	if (pa->npoints == 0)
 		return geometry;
 
-	geometry->n_coords = pa->npoints * ctx->dimensions;
+	geometry->n_coords = (size_t)pa->npoints * ctx->dimensions;
 	geometry->coords = encode_coords(ctx, pa, NULL, pa->npoints, 0);
 
 	return geometry;
@@ -264,7 +264,7 @@ encode_triangle(struct geobuf_agg_context *ctx, LWTRIANGLE *lwtri)
 		return geometry;
 
 	len = pa->npoints - 1;
-	geometry->n_coords = len * ctx->dimensions;
+	geometry->n_coords = (size_t)len * ctx->dimensions;
 	geometry->coords = encode_coords(ctx, pa, NULL, len, 0);
 
 	return geometry;
diff --git a/postgis/gserialized_estimate.c b/postgis/gserialized_estimate.c
index 73992adc1..4790b3373 100644
--- a/postgis/gserialized_estimate.c
+++ b/postgis/gserialized_estimate.c
@@ -1083,8 +1083,8 @@ estimate_join_selectivity(const ND_STATS *s1, const ND_STATS *s2)
 
 	/* Q: What's the largest possible join size these relations can create? */
 	/* A: The product of the # of non-null rows in each relation. */
-	ntuples_not_null1 = s1->table_features * (s1->not_null_features / s1->sample_features);
-	ntuples_not_null2 = s2->table_features * (s2->not_null_features / s2->sample_features);
+	ntuples_not_null1 = s1->table_features * ((double)s1->not_null_features / s1->sample_features);
+	ntuples_not_null2 = s2->table_features * ((double)s2->not_null_features / s2->sample_features);
 	ntuples_max = ntuples_not_null1 * ntuples_not_null2;
 
 	/* Get the ndims as ints */
@@ -1663,7 +1663,7 @@ compute_gserialized_stats_mode(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfu
 				 * then take the appropriate root to get the estimated number of cells
 				 * on this axis (eg, pow(0.5) for 2d, pow(0.333) for 3d, pow(0.25) for 4d)
 				*/
-				histo_size[d] = (int)pow(histo_cells_target * histo_ndims * edge_ratio, 1/(double)histo_ndims);
+				histo_size[d] = (int)pow((double)histo_cells_target * histo_ndims * edge_ratio, 1/(double)histo_ndims);
 				/* If something goes awry, just give this dim one slot */
 				if ( ! histo_size[d] )
 					histo_size[d] = 1;
@@ -2028,7 +2028,7 @@ estimate_selectivity(const GBOX *box, const ND_STATS *nd_stats, int mode)
 		cell_count = nd_stats->value[nd_stats_value_index(nd_stats, at)];
 
 		/* Add the pro-rated count for this cell to the overall total */
-		total_count += cell_count * ratio;
+		total_count += (double)cell_count * ratio;
 		POSTGIS_DEBUGF(4, " cell (%d,%d), cell value %.6f, ratio %.6f", at[0], at[1], cell_count, ratio);
 	}
 	while ( nd_increment(&nd_ibox, nd_stats->ndims, at) );
diff --git a/raster/loader/raster2pgsql.c b/raster/loader/raster2pgsql.c
index 7e7a70589..c2a8a8b83 100644
--- a/raster/loader/raster2pgsql.c
+++ b/raster/loader/raster2pgsql.c
@@ -158,7 +158,7 @@ strreplace(
 	while ((tmp = strstr(tmp, oldstr)) != NULL && found != limit)
 		found++, tmp += oldlen;
 
-	length = strlen(str) + found * (newlen - oldlen);
+	length = (int)strlen(str) + found * (newlen - oldlen);
 	if ((result = (char *) rtalloc(length + 1)) == NULL) {
 		rterror(_("strreplace: Not enough memory"));
 		found = -1;
diff --git a/raster/rt_core/rt_band.c b/raster/rt_core/rt_band.c
index 66aa19431..89de82605 100644
--- a/raster/rt_core/rt_band.c
+++ b/raster/rt_core/rt_band.c
@@ -301,12 +301,12 @@ rt_band_duplicate(rt_band band) {
 	/* online */
 	else {
 		uint8_t *data = NULL;
-		data = rtalloc(rt_pixtype_size(band->pixtype) * band->width * band->height);
+		data = rtalloc((size_t)rt_pixtype_size(band->pixtype) * band->width * band->height);
 		if (data == NULL) {
 			rterror("rt_band_duplicate: Out of memory allocating online band data");
 			return NULL;
 		}
-		memcpy(data, band->data.mem, rt_pixtype_size(band->pixtype) * band->width * band->height);
+		memcpy(data, band->data.mem, (size_t)rt_pixtype_size(band->pixtype) * band->width * band->height);
 
 		rtn = rt_band_new_inline(
 			band->width, band->height,
@@ -899,43 +899,43 @@ rt_band_set_pixel_line(
 		case PT_8BSI: {
 			uint8_t *ptr = data;
 			ptr += offset;
-			memcpy(ptr, vals, size * len);
+			memcpy(ptr, vals, (size_t)size * len);
 			break;
 		}
 		case PT_16BUI: {
 			uint16_t *ptr = (uint16_t *) data;
 			ptr += offset;
-			memcpy(ptr, vals, size * len);
+			memcpy(ptr, vals, (size_t)size * len);
 			break;
 		}
 		case PT_16BSI: {
 			int16_t *ptr = (int16_t *) data;
 			ptr += offset;
-			memcpy(ptr, vals, size * len);
+			memcpy(ptr, vals, (size_t)size * len);
 			break;
 		}
 		case PT_32BUI: {
 			uint32_t *ptr = (uint32_t *) data;
 			ptr += offset;
-			memcpy(ptr, vals, size * len);
+			memcpy(ptr, vals, (size_t)size * len);
 			break;
 		}
 		case PT_32BSI: {
 			int32_t *ptr = (int32_t *) data;
 			ptr += offset;
-			memcpy(ptr, vals, size * len);
+			memcpy(ptr, vals, (size_t)size * len);
 			break;
 		}
 		case PT_32BF: {
 			float *ptr = (float *) data;
 			ptr += offset;
-			memcpy(ptr, vals, size * len);
+			memcpy(ptr, vals, (size_t)size * len);
 			break;
 		}
 		case PT_64BF: {
 			double *ptr = (double *) data;
 			ptr += offset;
-			memcpy(ptr, vals, size * len);
+			memcpy(ptr, vals, (size_t)size * len);
 			break;
 		}
 		default: {
@@ -1188,16 +1188,16 @@ rt_errorstate rt_band_get_pixel_line(
 	}
 	RASTER_DEBUGF(4, "_nvals = %d", _nvals);
 
-	ptr = data + (offset * pixsize);
+	ptr = data + ((size_t)offset * pixsize);
 
-	_vals = rtalloc(_nvals * pixsize);
+	_vals = rtalloc((size_t)_nvals * pixsize);
 	if (_vals == NULL) {
 		rterror("rt_band_get_pixel_line: Could not allocate memory for pixel values");
 		return ES_ERROR;
 	}
 
 	/* copy pixels */
-	memcpy(_vals, ptr, _nvals * pixsize);
+	memcpy(_vals, ptr, (size_t)_nvals * pixsize);
 
 	*vals = _vals;
 	*nvals = _nvals;
diff --git a/raster/rt_core/rt_raster.c b/raster/rt_core/rt_raster.c
index 38a821d39..d93a2f8f8 100644
--- a/raster/rt_core/rt_raster.c
+++ b/raster/rt_core/rt_raster.c
@@ -3368,14 +3368,14 @@ rt_raster_gdal_rasterize(
 			rt_band_get_nodata(oldband, &nodataval);
 
 		/* allocate data */
-		data = rtalloc(rt_pixtype_size(arg->pixtype[i]) * _width * _height);
+		data = rtalloc((size_t)rt_pixtype_size(arg->pixtype[i]) * _width * _height);
 		if (data == NULL) {
 			rterror("rt_raster_gdal_rasterize: Could not allocate memory for band data");
 			_rti_rasterize_arg_destroy(arg);
 			rt_raster_destroy(rast);
 			return NULL;
 		}
-		memset(data, 0, rt_pixtype_size(arg->pixtype[i]) * _width * _height);
+		memset(data, 0, (size_t)rt_pixtype_size(arg->pixtype[i]) * _width * _height);
 
 		/* create new band of correct type */
 		band = rt_band_new_inline(
diff --git a/raster/rt_core/rt_wkb.c b/raster/rt_core/rt_wkb.c
index d7dd6e918..9113274f7 100644
--- a/raster/rt_core/rt_wkb.c
+++ b/raster/rt_core/rt_wkb.c
@@ -41,8 +41,8 @@ rt_band_from_wkb(
 	rt_band band = NULL;
 	int pixbytes = 0;
 	uint8_t type = 0;
-	unsigned long sz = 0;
-	uint32_t v = 0;
+	size_t sz = 0;
+	size_t v = 0;
 
 	assert(NULL != ptr);
 	assert(NULL != end);
@@ -195,7 +195,7 @@ rt_band_from_wkb(
 	}
 
 	/* This is an on-disk band */
-	sz = width * height * pixbytes;
+	sz = (size_t)width * height * pixbytes;
 	if (((*ptr) + sz) > end) {
 		rterror("rt_band_from_wkb: Premature end of WKB on band data reading (%s:%d)",
 			__FILE__, __LINE__);
@@ -234,7 +234,7 @@ rt_band_from_wkb(
 			}
 
 			flipme = band->data.mem;
-			sz = width * height;
+			sz = (size_t)width * height;
 			for (v = 0; v < sz; ++v) {
 				flipper(flipme);
 				flipme += pixbytes;
@@ -250,7 +250,7 @@ rt_band_from_wkb(
 		uint8_t maxVal = band->pixtype == PT_1BB ? 1 : (band->pixtype == PT_2BUI ? 3 : 15);
 		uint8_t val;
 
-		sz = width*height;
+		sz = (size_t)width*height;
 		for (v = 0; v < sz; ++v) {
 			val = ((uint8_t*) band->data.mem)[v];
 			if (val > maxVal) {
diff --git a/raster/rt_pg/rtpg_mapalgebra.c b/raster/rt_pg/rtpg_mapalgebra.c
index 98c4eab26..7ccfec8cf 100644
--- a/raster/rt_pg/rtpg_mapalgebra.c
+++ b/raster/rt_pg/rtpg_mapalgebra.c
@@ -5967,8 +5967,8 @@ Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
             width, height);
 
     /* Allocate room for the neighborhood. */
-    neighborData = (Datum *)palloc(winwidth * winheight * sizeof(Datum));
-    neighborNulls = (bool *)palloc(winwidth * winheight * sizeof(bool));
+    neighborData = (Datum *)palloc(sizeof(Datum) * winwidth * winheight);
+    neighborNulls = (bool *)palloc(sizeof(bool) * winwidth * winheight);
 
     /* The dimensions of the neighborhood array, for creating a multi-dimensional array. */
     neighborDims[0] = winwidth;

commit 4bac13b03d659fb59db1432b23c56b9e0fa604f3
Author: Even Rouault <even.rouault at spatialys.com>
Date:   Wed Feb 7 19:18:45 2024 +0100

    lwproj_lookup(): previously always returned TRUE, even if AddToPROJSRSCache() would have failed (found by CodeQL)

diff --git a/libpgcommon/lwgeom_transform.c b/libpgcommon/lwgeom_transform.c
index 95394bddb..c2b22085a 100644
--- a/libpgcommon/lwgeom_transform.c
+++ b/libpgcommon/lwgeom_transform.c
@@ -498,7 +498,7 @@ lwproj_lookup(int32_t srid_from, int32_t srid_to, LWPROJ **pj)
 		*pj = AddToPROJSRSCache(proj_cache, srid_from, srid_to);
 	}
 
-	return pj != NULL;
+	return *pj != NULL;
 }
 
 int

commit 915d308448b39bafc73b66786701aa27cac722d5
Author: Even Rouault <even.rouault at spatialys.com>
Date:   Wed Feb 7 19:14:14 2024 +0100

    lwgeom_out_marc21.c: is_format_valid(): fix potential off-by-one write in int_part[] if format starts with a ':' (found by CodeQL)

diff --git a/postgis/lwgeom_out_marc21.c b/postgis/lwgeom_out_marc21.c
index 9470d4e11..c04288379 100644
--- a/postgis/lwgeom_out_marc21.c
+++ b/postgis/lwgeom_out_marc21.c
@@ -197,8 +197,7 @@ lwgeom_to_marc21(const LWGEOM *geom, const char* format) {
 
 static int is_format_valid(const char* format){
 
-	char *int_part;
-	char *dec_part = strchr(format, '.');
+	const char *dec_part = strchr(format, '.');
 	if(!dec_part) dec_part = strchr(format, ',');
 
 	if(!dec_part) {
@@ -210,12 +209,14 @@ static int is_format_valid(const char* format){
 		}
 
 	} else {
+		char* int_part;
+		const size_t dec_part_len = strlen(dec_part);
+		const size_t int_part_len = (size_t)(dec_part - format);
+		if(int_part_len == 0 || dec_part_len<2)	return LW_FALSE;
 
-		if(strlen(dec_part)<2)	return LW_FALSE;
-
-		int_part = palloc(sizeof(char)*strlen(format));
-		memcpy(int_part, &format[0], strlen(format) - strlen(dec_part));
-		int_part[strlen(format) - strlen(dec_part)]='\0';
+		int_part = palloc(int_part_len + 1);
+		memcpy(int_part, &format[0], int_part_len);
+		int_part[int_part_len]='\0';
 
 		if (strcmp(int_part,"hddd") && strcmp(int_part,"ddd") &&
 			strcmp(int_part,"hdddmm") && strcmp(int_part,"dddmm") &&
@@ -226,9 +227,9 @@ static int is_format_valid(const char* format){
 
 		}
 
-		for (size_t i = 1; i < strlen(dec_part); i++) {
+		for (size_t i = 1; i < dec_part_len; i++) {
 
-			if(dec_part[i]!=int_part[strlen(int_part)-1]) {
+			if(dec_part[i]!=int_part[int_part_len-1]) {
 
 				pfree(int_part);
 				return LW_FALSE;

commit 4ecb7100c90ec3ef23a5249bfa52a3e20f2f3542
Author: Even Rouault <even.rouault at spatialys.com>
Date:   Wed Feb 7 18:47:59 2024 +0100

    CI: add CodeQL

diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000..2d290d1a6
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,67 @@
+name: "CodeQL"
+
+on:
+  push:
+  pull_request:
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
+  cancel-in-progress: true
+
+permissions:
+  contents: read
+
+jobs:
+  analyze:
+    name: Analyze
+    # Runner size impacts CodeQL analysis time. To learn more, please see:
+    #   - https://gh.io/recommended-hardware-resources-for-running-codeql
+    #   - https://gh.io/supported-runners-and-hardware-resources
+    #   - https://gh.io/using-larger-runners
+    # Consider using larger runners for possible analysis time improvements.
+    runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+    timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
+    permissions:
+      actions: read
+      contents: read
+      security-events: write
+
+    strategy:
+      fail-fast: false
+      matrix:
+        language: [ 'c-cpp' ]
+        # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
+        # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
+        # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout at v4
+
+    # Initializes the CodeQL tools for scanning.
+    - name: Initialize CodeQL
+      uses: github/codeql-action/init at v3
+      with:
+        languages: ${{ matrix.language }}
+        # If you wish to specify custom queries, you can do so here or in a config file.
+        # By default, queries listed here will override any specified in a config file.
+        # Prefix the list here with "+" to use these queries and those in the config file.
+
+        # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+        # queries: security-extended,security-and-quality
+
+    - name: Install dependencies
+      run: |
+          sudo apt-get install -y g++ autoconf automake libgeos-dev libproj-dev libgdal-dev libjson-c-dev gettext libxml2-dev postgresql-server-dev-14 postgresql-client-14 libprotobuf-c-dev libprotoc-dev protobuf-c-compiler
+
+    - name: Build
+      run: |
+          ./autogen.sh
+          ./configure
+          make -j$(nproc)
+
+    - name: Perform CodeQL Analysis
+      uses: github/codeql-action/analyze at v3
+      with:
+        category: "/language:${{matrix.language}}"

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

Summary of changes:
 .github/workflows/codeql.yml    | 67 +++++++++++++++++++++++++++++++++++++++++
 liblwgeom/gserialized1.c        | 26 ++++++++--------
 liblwgeom/gserialized2.c        | 24 +++++++--------
 liblwgeom/lwin_wkb.c            |  2 +-
 liblwgeom/lwout_twkb.c          |  2 +-
 liblwgeom/lwout_wkb.c           |  4 +--
 liblwgeom/ptarray.c             | 12 ++++----
 libpgcommon/lwgeom_transform.c  |  2 +-
 postgis/geobuf.c                |  8 ++---
 postgis/gserialized_estimate.c  | 10 +++---
 postgis/gserialized_gist_2d.c   |  4 +--
 postgis/gserialized_spgist_2d.c |  2 +-
 postgis/gserialized_spgist_3d.c |  2 +-
 postgis/lwgeom_out_marc21.c     | 19 ++++++------
 postgis/lwgeom_spheroid.c       |  2 +-
 raster/loader/raster2pgsql.c    |  2 +-
 raster/rt_core/rt_band.c        | 24 +++++++--------
 raster/rt_core/rt_raster.c      |  4 +--
 raster/rt_core/rt_wkb.c         | 10 +++---
 raster/rt_pg/rtpg_mapalgebra.c  |  4 +--
 20 files changed, 149 insertions(+), 81 deletions(-)
 create mode 100644 .github/workflows/codeql.yml


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list