[SCM] PostGIS branch stable-3.6 updated. 3.6.4-122-g918f1c9cd8
git at osgeo.org
git at osgeo.org
Sun Aug 9 13:12:41 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.6 has been updated
via 918f1c9cd870e0a7fde02ade51be65d2164955a4 (commit)
via c01443760cbc487739d8b64b8960339df2086643 (commit)
via c8677f904889021d5ed0f2a441a8558daa12c488 (commit)
via 46044876bb11efb0be0195c21217974fac4e368b (commit)
via 38fca895d715a6f13ff266bfd4049a51579e1b81 (commit)
via a567d313130af7e06419685e2d1eda685dbab393 (commit)
via 2c67755a162b0ab5d4de9ef19c8b4bd0ec7bd5df (commit)
via f96466a2824bd7c97eec51ab189518525769f32d (commit)
from 5bb68300a0a27073915dafef28fb6d116d7689aa (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 918f1c9cd870e0a7fde02ade51be65d2164955a4
Merge: 5bb68300a0 c01443760c
Author: Darafei Praliaskouski <komzpa at gmail.com>
Date: Sun Aug 9 13:12:40 2026 -0700
Merge pull request 'Backport correctness and input-safety fixes to stable-3.6' (!684) from Komzpa/postgis:fix/stable-3.6-backpatch-sweep-20260810 into stable-3.6
Malformed encoded polylines can end in a truncated varint. This backport bounds every varint byte read in `lwgeom_from_encoded_polyline`, so malformed input is rejected instead of being read past its end.
It also frees the temporary geometries created by the stable `ST_DWithin` implementation after its brute-force distance calculation, and stops generated extension upgrade scripts from running `ANALYZE` inside their transaction, where it can deadlock with autovacuum.
`geometry_columns` can retain a stale relation row after a relation is dropped or SELECT privilege is revoked. This adds the visibility-safe re-resolution and focused regression from [Trac ticket 6038](https://trac.osgeo.org/postgis/ticket/6038).
The FlatGeobuf size-prefixed-buffer validation is already in the `stable-3.6` base, so this branch deliberately does not duplicate it.
`ST_Normalize` now uses the LWGEOM fallback for TIN and PolyhedralSurface inputs, preserving TRIANGLE children instead of letting GEOS conversion change their type.
Sources:
- https://gitea.osgeo.org/postgis/postgis/commit/491813e413afff546779b988e79ad7eb20559c46
- https://gitea.osgeo.org/postgis/postgis/commit/94cc593de819c917edc0d0a49c9c2ee76a5f88ce
- https://gitea.osgeo.org/postgis/postgis/commit/248b014b9805911792e2fcc097ce7c0cde422308
- https://gitea.osgeo.org/postgis/postgis/commit/6f11ffd051915508ef244399043b484a2de46295
- https://gitea.osgeo.org/postgis/postgis/commit/1f6aabb0f4fb5845d31b38d0afc69ea6e466fcef
- https://gitea.osgeo.org/postgis/postgis/commit/80a8dcabf7d9f0b19abae1d853571473cbd9c075
The encoded-polyline and upgrade commits retain upstream authorship. The `ST_DWithin` cleanup is a faithful small port because this stable line uses an earlier source location.
Validation: `git diff --check`; built and staged against PostgreSQL 15; focused `regress/core/regress_management` and `regress/core/normalize` passed the create and upgrade paths with 0 failures.
Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/684
commit c01443760cbc487739d8b64b8960339df2086643
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Sun Aug 9 22:58:41 2026 +0400
Fix ST_Normalize TIN child normalization
Squashed manual backport of the surface-normalization fallback and its TIN child correction; excludes unrelated example-test changes.\n\nPorted-from: 1f6aabb0f4fb5845d31b38d0afc69ea6e466fcef\nPorted-from: 80a8dcabf7d9f0b19abae1d853571473cbd9c075
diff --git a/NEWS b/NEWS
index d43518587d..3bb6bd1515 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PostGIS 3.6.5
* Fixes *
+ - GT-675, Preserve TRIANGLE children while normalizing malformed TINs
+ (Darafei Praliaskouski)
- #6038, Avoid stale geometry_columns relation lookups after relations are
dropped or SELECT privilege is revoked (Darafei Praliaskouski)
- Stop the extension upgrade script running ANALYZE inside its transaction,
diff --git a/liblwgeom/lwgeom_geos.c b/liblwgeom/lwgeom_geos.c
index 102ed604dc..98db684702 100644
--- a/liblwgeom/lwgeom_geos.c
+++ b/liblwgeom/lwgeom_geos.c
@@ -32,6 +32,7 @@
#include <stdarg.h>
#include <stdlib.h>
+#include <string.h>
LWTIN* lwtin_from_geos(const GEOSGeometry* geom, uint8_t want3d);
@@ -524,6 +525,7 @@ LWGEOM2GEOS(const LWGEOM* lwgeom, uint8_t autofix)
case MULTILINETYPE:
case MULTIPOLYGONTYPE:
case TINTYPE:
+ case POLYHEDRALSURFACETYPE:
case COLLECTIONTYPE:
{
int geostype;
@@ -657,6 +659,89 @@ get_result_srid(size_t count, const char* funcname, ...)
return srid;
}
+static int
+lwgeom_geos_normalize_unsupported_type(uint8_t type)
+{
+ return type == POLYHEDRALSURFACETYPE || type == TINTYPE;
+}
+
+static int
+lwgeom_geos_normalize_needs_lwgeom(const LWGEOM *geom)
+{
+ uint32_t i;
+ LWCOLLECTION *col;
+
+ if (lwgeom_geos_normalize_unsupported_type(geom->type))
+ return LW_TRUE;
+ if (!lwtype_is_collection(geom->type))
+ return LW_FALSE;
+ col = (LWCOLLECTION *)geom;
+ for (i = 0; i < col->ngeoms; i++)
+ if (lwgeom_geos_normalize_needs_lwgeom(col->geoms[i]))
+ return LW_TRUE;
+ return LW_FALSE;
+}
+
+static int
+lwgeom_compare_by_xdr_ewkb(const void *a, const void *b)
+{
+ const LWGEOM *ga = *(const LWGEOM *const *)a;
+ const LWGEOM *gb = *(const LWGEOM *const *)b;
+ char *wa = lwgeom_to_hexwkb_buffer(ga, WKB_EXTENDED | WKB_XDR);
+ char *wb = lwgeom_to_hexwkb_buffer(gb, WKB_EXTENDED | WKB_XDR);
+ int cmp = strcmp(wa, wb);
+ lwfree(wa);
+ lwfree(wb);
+ return cmp;
+}
+
+static LWGEOM *
+lwgeom_normalized_triangle_or_clone(const LWGEOM *triangle_in, LWGEOM *normalized)
+{
+ LWPOLY *poly;
+ LWTRIANGLE *triangle;
+ POINTARRAY *points;
+ if (normalized && normalized->type == TRIANGLETYPE)
+ return normalized;
+ if (!normalized || normalized->type != POLYGONTYPE)
+ {
+ lwgeom_free(normalized);
+ return lwgeom_clone_deep(triangle_in);
+ }
+ poly = lwgeom_as_lwpoly(normalized);
+ if (poly->nrings != 1 || !poly->rings[0])
+ {
+ lwgeom_free(normalized);
+ return lwgeom_clone_deep(triangle_in);
+ }
+ points = ptarray_clone_deep(poly->rings[0]);
+ triangle = lwtriangle_construct(poly->srid, NULL, points);
+ lwgeom_free(normalized);
+ return lwtriangle_as_lwgeom(triangle);
+}
+
+static LWGEOM *
+lwgeom_normalize_lwgeom(const LWGEOM *geom)
+{
+ uint32_t i;
+ LWCOLLECTION *col;
+ if (!lwtype_is_collection(geom->type))
+ return lwgeom_clone_deep(geom);
+ col = lwcollection_clone_deep((LWCOLLECTION *)geom);
+ for (i = 0; i < col->ngeoms; i++)
+ {
+ LWGEOM *normalized = lwgeom_normalize(col->geoms[i]);
+ if (col->type == TINTYPE && col->geoms[i]->type == TRIANGLETYPE)
+ normalized = lwgeom_normalized_triangle_or_clone(col->geoms[i], normalized);
+ lwgeom_free(col->geoms[i]);
+ col->geoms[i] = normalized;
+ }
+ if (col->ngeoms > 1)
+ qsort(col->geoms, col->ngeoms, sizeof(LWGEOM *), lwgeom_compare_by_xdr_ewkb);
+ lwgeom_drop_bbox((LWGEOM *)col);
+ return (LWGEOM *)col;
+}
+
LWGEOM*
lwgeom_normalize(const LWGEOM* geom)
{
@@ -666,6 +751,8 @@ lwgeom_normalize(const LWGEOM* geom)
GEOSGeometry* g;
if (srid == SRID_INVALID) return NULL;
+ if (lwgeom_geos_normalize_needs_lwgeom(geom))
+ return lwgeom_normalize_lwgeom(geom);
initGEOS(lwnotice, lwgeom_geos_error);
diff --git a/regress/core/normalize.sql b/regress/core/normalize.sql
index 02aac6518b..547b353a44 100644
--- a/regress/core/normalize.sql
+++ b/regress/core/normalize.sql
@@ -5,3 +5,11 @@ select 1, ST_AsText(ST_Normalize(
select 2, ST_AsText(ST_Normalize(
'POLYGON((0 10,0 0,10 0,10 10,0 10),(4 2,2 2,2 4,4 4,4 2),(6 8,8 8,8 6,6 6,6 8))'
::geometry));
+
+select 3, GeometryType(ST_Normalize('POLYHEDRALSURFACE(((0 0,2 0,0 2,0 0)),((10 10,11 10,10 11,10 10)))'::geometry));
+select 4, GeometryType(ST_Normalize('TIN(((0 0,2 0,0 2,0 0)),((10 10,11 10,10 11,10 10)))'::geometry));
+select 5, GeometryType(ST_GeometryN(ST_Normalize('GEOMETRYCOLLECTION(POLYHEDRALSURFACE(((0 0,2 0,0 2,0 0))))'::geometry), 1));
+with normalized as (
+ select ST_Normalize(ST_GeomFromWKB(decode('0110000000010000000111000000010000000500000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000000','hex'))) as geom
+)
+select 6, GeometryType(normalized.geom), GeometryType((dumped).geom) from normalized cross join lateral ST_Dump(normalized.geom) as dumped;
diff --git a/regress/core/normalize_expected b/regress/core/normalize_expected
index 36d32a2f7c..c42004281b 100644
--- a/regress/core/normalize_expected
+++ b/regress/core/normalize_expected
@@ -1,2 +1,6 @@
1|GEOMETRYCOLLECTION(MULTILINESTRING((2 2,3 3),(0 0,1 1)),POINT(2 3))
2|POLYGON((0 0,0 10,10 10,10 0,0 0),(6 6,8 6,8 8,6 8,6 6),(2 2,4 2,4 4,2 4,2 2))
+3|POLYHEDRALSURFACE
+4|TIN
+5|POLYHEDRALSURFACE
+6|TIN|TRIANGLE
commit c8677f904889021d5ed0f2a441a8558daa12c488
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Sun Aug 9 22:36:12 2026 +0400
NEWS: remove FlatGeobuf pseudo-tag
diff --git a/NEWS b/NEWS
index c2694b49bc..d43518587d 100644
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,7 @@ PostGIS 3.6.5
- OSSFuzz 5877056525893632, reject truncated encoded polyline input
(Darafei Praliaskouski)
- GT-677, Fix temporary geometry leaks in ST_DWithin (Darafei Praliaskouski)
-- GT-674, [flatgeobuf] Validate size-prefixed buffers and variable-length property
+- GT-674, Validate size-prefixed buffers and variable-length property
values before decoding
(reported by Mehmet Ince;
reported by Sarath Kumar, IITM Pravartak Security Team;
commit 46044876bb11efb0be0195c21217974fac4e368b
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Fri Jun 19 23:42:36 2026 +0400
postgis: avoid stale geometry_columns relation lookups
Filter stale pg_class rows from geometry_columns by re-resolving visible schema-qualified names before exposing metadata, while keeping inaccessible schemas on OID-based privilege checks that do not resolve hidden names. Require the current SELECT privilege result in both visible and hidden paths so stale snapshots do not keep exposing metadata after relation drops or SELECT revokes.
Closes #6038
Closes https://github.com/postgis/postgis/pull/915
(cherry picked from commit 6f11ffd051915508ef244399043b484a2de46295)
diff --git a/NEWS b/NEWS
index 36123695bf..c2694b49bc 100644
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,9 @@ PostGIS 3.6.5
* Fixes *
-- Stop the extension upgrade script running ANALYZE inside its transaction,
+ - #6038, Avoid stale geometry_columns relation lookups after relations are
+ dropped or SELECT privilege is revoked (Darafei Praliaskouski)
+ - Stop the extension upgrade script running ANALYZE inside its transaction,
where it can deadlock with autovacuum (Darafei Praliaskouski)
- OSSFuzz 5877056525893632, reject truncated encoded polyline input
(Darafei Praliaskouski)
diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in
index 710c24e425..98718667fa 100644
--- a/postgis/postgis.sql.in
+++ b/postgis/postgis.sql.in
@@ -6425,7 +6425,40 @@ SELECT current_database()::character varying(256) AS f_table_catalog,
) sr ON sr.connamespace = n.oid AND sr.conrelid = c.oid AND (a.attnum = ANY (sr.conkey))
WHERE (c.relkind = ANY (ARRAY['r'::"char", 'v'::"char", 'm'::"char", 'f'::"char", 'p'::"char"]))
AND NOT c.relname = 'raster_columns'::name AND t.typname = 'geometry'::name
- AND NOT pg_is_other_temp_schema(c.relnamespace) AND has_table_privilege(c.oid, 'SELECT'::text);
+ AND NOT pg_is_other_temp_schema(c.relnamespace)
+ -- A stale MVCC snapshot can still see a dropped pg_class row (#6038).
+ -- Re-resolve the qualified relation name only when the schema is visible,
+ -- because to_regclass reports permission errors for inaccessible schemas.
+ -- Without schema visibility, keep the old OID-based privilege semantics.
+ -- Keep the visible-schema SELECT check in the same CASE branch as the
+ -- re-resolution guard so PostgreSQL cannot evaluate it for a stale OID.
+ AND CASE WHEN has_schema_privilege(c.relnamespace, 'USAGE'::text)
+ THEN CASE WHEN pg_catalog.to_regclass(pg_catalog.format('%I.%I', n.nspname, c.relname)) = c.oid
+ THEN pg_catalog.has_table_privilege(c.oid, 'SELECT')
+ ELSE false
+ END
+ ELSE pg_catalog.has_table_privilege(c.oid, 'SELECT')
+ END
+ AND (
+ EXISTS (
+ SELECT 1
+ FROM pg_roles
+ WHERE rolname = current_user
+ AND rolsuper
+ )
+ OR EXISTS (
+ SELECT 1
+ FROM pg_roles
+ WHERE rolname = 'pg_read_all_data'
+ AND pg_has_role(current_user, oid, 'USAGE')
+ )
+ OR EXISTS (
+ SELECT 1
+ FROM aclexplode(COALESCE(c.relacl, acldefault('r', c.relowner))) AS acl
+ WHERE acl.privilege_type = 'SELECT'
+ AND (acl.grantee = 0 OR pg_has_role(acl.grantee, 'USAGE'))
+ )
+ );
-- TODO: support RETURNING and raise a WARNING
CREATE OR REPLACE RULE geometry_columns_insert AS
diff --git a/regress/core/regress_management.sql b/regress/core/regress_management.sql
index c92b7aad0a..2b5027bd4e 100644
--- a/regress/core/regress_management.sql
+++ b/regress/core/regress_management.sql
@@ -4,5 +4,65 @@ SET client_min_messages TO warning;
CREATE TABLE test_pt(gid SERIAL PRIMARY KEY, geom geometry);
INSERT INTO test_pt(geom) VALUES(ST_GeomFromEWKT('SRID=4326;POINT M(1 2 3)'));
SELECT populate_geometry_columns('test_pt'::regclass);
+SELECT '#6038.before', srid FROM geometry_columns WHERE f_table_schema = 'public' AND f_table_name = 'test_pt' AND f_geometry_column = 'geom';
SELECT 'The result: ' || DropGeometryTable('test_pt');
+SELECT '#6038.after', count(*) FROM geometry_columns WHERE f_table_schema = 'public' AND f_table_name = 'test_pt' AND f_geometry_column = 'geom';
+DO $$
+DECLARE
+ can_switch_role boolean;
+BEGIN
+ SELECT rolsuper INTO can_switch_role
+ FROM pg_roles
+ WHERE rolname = current_user;
+
+ IF can_switch_role THEN
+ DROP SCHEMA IF EXISTS test6038_private CASCADE;
+ DROP TABLE IF EXISTS public.test6038_visible_geom;
+ DROP ROLE IF EXISTS test6038_invisible;
+ DROP ROLE IF EXISTS test6038_visible;
+ CREATE ROLE test6038_invisible;
+ CREATE ROLE test6038_visible;
+ GRANT test6038_invisible TO CURRENT_USER;
+ GRANT test6038_visible TO CURRENT_USER;
+ CREATE TABLE public.test6038_visible_geom(geom geometry(Point, 4326));
+ GRANT SELECT ON public.test6038_visible_geom TO test6038_visible;
+ CREATE SCHEMA test6038_private;
+ CREATE TABLE test6038_private.hidden_geom(geom geometry(Point, 4326));
+ REVOKE ALL ON SCHEMA test6038_private FROM PUBLIC;
+ GRANT SELECT ON test6038_private.hidden_geom TO test6038_invisible;
+
+ EXECUTE 'SET LOCAL ROLE test6038_visible';
+ IF 1 != (SELECT count(*) FROM geometry_columns WHERE f_table_schema = 'public' AND f_table_name = 'test6038_visible_geom') THEN
+ RAISE EXCEPTION 'geometry_columns did not expose currently selectable table in visible schema';
+ END IF;
+ EXECUTE 'RESET ROLE';
+
+ REVOKE SELECT ON public.test6038_visible_geom FROM test6038_visible;
+ EXECUTE 'SET LOCAL ROLE test6038_visible';
+ IF 0 != (SELECT count(*) FROM geometry_columns WHERE f_table_schema = 'public' AND f_table_name = 'test6038_visible_geom') THEN
+ RAISE EXCEPTION 'geometry_columns exposed metadata after SELECT was revoked in visible schema';
+ END IF;
+ EXECUTE 'RESET ROLE';
+
+ -- The view must not resolve names inside schemas hidden from the caller.
+ EXECUTE 'SET LOCAL ROLE test6038_invisible';
+ IF 1 != (SELECT count(*) FROM geometry_columns WHERE f_table_schema = 'test6038_private') THEN
+ RAISE EXCEPTION 'geometry_columns did not preserve OID-based SELECT visibility in hidden schema';
+ END IF;
+ EXECUTE 'RESET ROLE';
+
+ REVOKE SELECT ON test6038_private.hidden_geom FROM test6038_invisible;
+ EXECUTE 'SET LOCAL ROLE test6038_invisible';
+ IF 0 != (SELECT count(*) FROM geometry_columns WHERE f_table_schema = 'test6038_private') THEN
+ RAISE EXCEPTION 'geometry_columns exposed hidden-schema metadata after SELECT was revoked';
+ END IF;
+ EXECUTE 'RESET ROLE';
+
+ DROP SCHEMA test6038_private CASCADE;
+ DROP TABLE public.test6038_visible_geom;
+ DROP ROLE test6038_invisible;
+ DROP ROLE test6038_visible;
+ END IF;
+END
+$$;
SELECT 'Unexistant: ' || DropGeometryTable('unexistent'); -- see ticket #861
diff --git a/regress/core/regress_management_expected b/regress/core/regress_management_expected
index e27f7f0ef5..ac137e244f 100644
--- a/regress/core/regress_management_expected
+++ b/regress/core/regress_management_expected
@@ -1,3 +1,5 @@
1
+#6038.before|4326
The result: public.test_pt dropped.
+#6038.after|0
Unexistant: public.unexistent dropped.
commit 38fca895d715a6f13ff266bfd4049a51579e1b81
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Sun Aug 9 22:23:44 2026 +0400
NEWS: reference backported issue numbers
diff --git a/NEWS b/NEWS
index c3abf8787e..36123695bf 100644
--- a/NEWS
+++ b/NEWS
@@ -7,7 +7,7 @@ PostGIS 3.6.5
where it can deadlock with autovacuum (Darafei Praliaskouski)
- OSSFuzz 5877056525893632, reject truncated encoded polyline input
(Darafei Praliaskouski)
-- Fix temporary geometry leaks in ST_DWithin (Darafei Praliaskouski)
+- GT-677, Fix temporary geometry leaks in ST_DWithin (Darafei Praliaskouski)
- GT-674, [flatgeobuf] Validate size-prefixed buffers and variable-length property
values before decoding
(reported by Mehmet Ince;
commit a567d313130af7e06419685e2d1eda685dbab393
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Sun Aug 2 20:03:01 2026 +0400
Do not ANALYZE inside the extension upgrade transaction
spatial_ref_sys.sql ends with
ON CONFLICT (srid) DO NOTHING;
COMMIT;
ANALYZE "spatial_ref_sys";
The ANALYZE sits after COMMIT on purpose: run standalone it refreshes the
statistics of a table that just gained thousands of rows, outside any
transaction. The extension build strips BEGIN and COMMIT because those are
not allowed in extension scripts, and left the ANALYZE behind — so it ends up
*inside* the upgrade's transaction, takes ShareUpdateExclusiveLock on
spatial_ref_sys, and can deadlock against autovacuum analysing the same table:
ERROR: deadlock detected
DETAIL: Process A waits for ShareUpdateExclusiveLock on relation ...;
blocked by process B. Process B waits for ShareLock on
transaction ...; blocked by process A.
CONTEXT: SQL statement "ANALYZE "spatial_ref_sys""
extension script file "postgis--ANY--3.7.0dev.sql"
That aborts ALTER EXTENSION postgis UPDATE, so a user upgrading a busy
database can simply lose the upgrade. It also accounts for three of the
eleven most recent Woodpecker pipeline failures, in regress/test-install and
regress/test-upgrades, on ordinary amd64 rows rather than emulated ones.
Strip the ANALYZE along with the transaction control it was written to follow.
The standalone spatial_ref_sys.sql keeps it; autovacuum analyses the table on
its own schedule, so the extension script does not need to.
(cherry picked from commit 248b014b9805911792e2fcc097ce7c0cde422308)
diff --git a/NEWS b/NEWS
index 48149d09eb..c3abf8787e 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PostGIS 3.6.5
* Fixes *
+- Stop the extension upgrade script running ANALYZE inside its transaction,
+ where it can deadlock with autovacuum (Darafei Praliaskouski)
- OSSFuzz 5877056525893632, reject truncated encoded polyline input
(Darafei Praliaskouski)
- Fix temporary geometry leaks in ST_DWithin (Darafei Praliaskouski)
diff --git a/extensions/postgis/Makefile.in b/extensions/postgis/Makefile.in
index 88ef35afdf..fbf3bd09aa 100644
--- a/extensions/postgis/Makefile.in
+++ b/extensions/postgis/Makefile.in
@@ -104,9 +104,21 @@ sql/$(EXTENSION)--unpackaged.sql: Makefile | sql
sql:
mkdir -p $@
-#strip BEGIN/COMMIT since these are not allowed in extensions
+# Strip BEGIN/COMMIT since these are not allowed in extensions, and the trailing
+# ANALYZE with them. In spatial_ref_sys.sql that ANALYZE deliberately sits *after*
+# COMMIT, so run standalone it refreshes statistics outside any transaction. Removing
+# only the COMMIT moves it inside the extension's transaction, where it takes
+# ShareUpdateExclusiveLock on spatial_ref_sys and can deadlock against autovacuum
+# doing the same work:
+#
+# ERROR: deadlock detected
+# CONTEXT: SQL statement "ANALYZE "spatial_ref_sys""
+# extension script file "postgis--ANY--<version>.sql"
+#
+# That aborts ALTER EXTENSION postgis UPDATE on any busy database. Autovacuum will
+# analyse the table on its own schedule, so the extension script does not need to.
sql/spatial_ref_sys.sql: ../../spatial_ref_sys.sql | sql
- $(PERL) -pe 's/BEGIN\;//g ; s/COMMIT\;//g' $< > $@
+ $(PERL) -pe 's/BEGIN\;//g ; s/COMMIT\;//g ; s/^ANALYZE "spatial_ref_sys";\s*$$//g' $< > $@
sql/spatial_ref_sys_config_dump.sql: ../../spatial_ref_sys.sql ../../utils/create_spatial_ref_sys_config_dump.pl | sql
$(PERL) @top_srcdir@/utils/create_spatial_ref_sys_config_dump.pl $< > $@
commit 2c67755a162b0ab5d4de9ef19c8b4bd0ec7bd5df
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Sat Aug 8 12:22:14 2026 +0400
fix(liblwgeom): reject truncated encoded polylines
(cherry picked from commit 491813e413afff546779b988e79ad7eb20559c46)
diff --git a/NEWS b/NEWS
index dd7d758765..48149d09eb 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PostGIS 3.6.5
* Fixes *
+- OSSFuzz 5877056525893632, reject truncated encoded polyline input
+ (Darafei Praliaskouski)
- Fix temporary geometry leaks in ST_DWithin (Darafei Praliaskouski)
- GT-674, [flatgeobuf] Validate size-prefixed buffers and variable-length property
values before decoding
diff --git a/liblwgeom/cunit/cu_in_encoded_polyline.c b/liblwgeom/cunit/cu_in_encoded_polyline.c
index 6af16b9a23..9cd4a7e1fe 100644
--- a/liblwgeom/cunit/cu_in_encoded_polyline.c
+++ b/liblwgeom/cunit/cu_in_encoded_polyline.c
@@ -62,6 +62,13 @@ static void in_encoded_polyline_test_close_points(void)
"SRID=4326;LINESTRING(38.903876 55.336448,38.903875 55.336448)");
}
+static void in_encoded_polyline_test_truncated_input(void)
+{
+ /* A latitude without a longitude and an unterminated latitude varint. */
+ CU_ASSERT_PTR_NULL(lwgeom_from_encoded_polyline("A", 5));
+ CU_ASSERT_PTR_NULL(lwgeom_from_encoded_polyline("`", 5));
+}
+
/*
** Used by test harness to register the tests in this file.
*/
@@ -72,4 +79,5 @@ void in_encoded_polyline_suite_setup(void)
PG_ADD_TEST(suite, in_encoded_polyline_test_geoms);
PG_ADD_TEST(suite, in_encoded_polyline_test_precision);
PG_ADD_TEST(suite, in_encoded_polyline_test_close_points);
+ PG_ADD_TEST(suite, in_encoded_polyline_test_truncated_input);
}
diff --git a/liblwgeom/lwin_encoded_polyline.c b/liblwgeom/lwin_encoded_polyline.c
index 2bb9f73417..d1af103eab 100644
--- a/liblwgeom/lwin_encoded_polyline.c
+++ b/liblwgeom/lwin_encoded_polyline.c
@@ -29,6 +29,7 @@
#include <stdint.h>
#include "liblwgeom.h"
+#include "lwgeom_log.h"
#include "../postgis_config.h"
LWGEOM*
@@ -52,6 +53,11 @@ lwgeom_from_encoded_polyline(const char *encodedpolyline, int precision)
int res = 0;
char shift = 0;
do {
+ if (idx >= length) {
+ lwerror("lwgeom_from_encoded_polyline: input is truncated");
+ ptarray_free(pa);
+ return NULL;
+ }
byte = encodedpolyline[idx++] - 63;
res |= (byte & 0x1F) << shift;
shift += 5;
@@ -62,6 +68,11 @@ lwgeom_from_encoded_polyline(const char *encodedpolyline, int precision)
shift = 0;
res = 0;
do {
+ if (idx >= length) {
+ lwerror("lwgeom_from_encoded_polyline: input is truncated");
+ ptarray_free(pa);
+ return NULL;
+ }
byte = encodedpolyline[idx++] - 63;
res |= (byte & 0x1F) << shift;
shift += 5;
commit f96466a2824bd7c97eec51ab189518525769f32d
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Sun Aug 9 22:02:03 2026 +0400
postgis: free ST_DWithin temporary geometries
Ported-from: https://gitea.osgeo.org/postgis/postgis/commit/94cc593de819c917edc0d0a49c9c2ee76a5f88ce
diff --git a/NEWS b/NEWS
index 1314c3c807..dd7d758765 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ PostGIS 3.6.5
* Fixes *
+- Fix temporary geometry leaks in ST_DWithin (Darafei Praliaskouski)
- GT-674, [flatgeobuf] Validate size-prefixed buffers and variable-length property
values before decoding
(reported by Mehmet Ince;
diff --git a/postgis/lwgeom_functions_basic.c b/postgis/lwgeom_functions_basic.c
index 9a7a1b898c..b8cfc9b5f2 100644
--- a/postgis/lwgeom_functions_basic.c
+++ b/postgis/lwgeom_functions_basic.c
@@ -751,6 +751,8 @@ Datum LWGEOM_dwithin(PG_FUNCTION_ARGS)
}
mindist = lwgeom_mindistance2d_tolerance(lwgeom1, lwgeom2, tolerance);
+ lwgeom_free(lwgeom1);
+ lwgeom_free(lwgeom2);
PG_FREE_IF_COPY(geom1, 0);
PG_FREE_IF_COPY(geom2, 1);
-----------------------------------------------------------------------
Summary of changes:
NEWS | 11 +++-
extensions/postgis/Makefile.in | 16 +++++-
liblwgeom/cunit/cu_in_encoded_polyline.c | 8 +++
liblwgeom/lwgeom_geos.c | 87 ++++++++++++++++++++++++++++++++
liblwgeom/lwin_encoded_polyline.c | 11 ++++
postgis/lwgeom_functions_basic.c | 2 +
postgis/postgis.sql.in | 35 ++++++++++++-
regress/core/normalize.sql | 8 +++
regress/core/normalize_expected | 4 ++
regress/core/regress_management.sql | 60 ++++++++++++++++++++++
regress/core/regress_management_expected | 2 +
11 files changed, 240 insertions(+), 4 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list