[SCM] PostGIS branch master updated. 3.7.0beta2-10-g2b8bb15d7

git at osgeo.org git at osgeo.org
Mon Aug 10 02:01: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, master has been updated
       via  2b8bb15d7a3a872ce9f0f6f4e680f9edd8b7415a (commit)
       via  c7287d8a085581c37be947859c4b0cc285a83cd2 (commit)
      from  8b55c63cfa65a37dd0cabdf51782d589b62f8773 (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 2b8bb15d7a3a872ce9f0f6f4e680f9edd8b7415a
Merge: 8b55c63cf c7287d8a0
Author: Darafei Praliaskouski <komzpa at gmail.com>
Date:   Mon Aug 10 02:01:37 2026 -0700

    Merge pull request 'liblwgeom: reject overlong encoded polylines' (!715) from Komzpa/postgis:fix/encoded-polyline-shift-544518840 into master
    
    Encoded polyline coordinate varints were accumulated into a signed `int`, so malformed inputs could shift a high 5-bit group into the signed bit range under UBSAN. Decode the varint into a bounded unsigned accumulator instead, and reject truncated, invalid, or overlong coordinate varints before shifting them.
    
    Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/715


commit c7287d8a085581c37be947859c4b0cc285a83cd2
Author: Darafei Praliaskouski <me at komzpa.net>
Date:   Mon Aug 10 12:55:53 2026 +0400

    fix(liblwgeom): reject overlong encoded polylines

diff --git a/NEWS b/NEWS
index 024608787..258077332 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ These are only changes since 3.7.0beta2.
 
 * Bug Fixes *
 
+ - OSSFuzz 6152109301760000, reject overlong encoded polyline coordinate
+          varints (Darafei Praliaskouski)
 
 
 
diff --git a/liblwgeom/cunit/cu_in_encoded_polyline.c b/liblwgeom/cunit/cu_in_encoded_polyline.c
index 9cd4a7e1f..7fcb7841a 100644
--- a/liblwgeom/cunit/cu_in_encoded_polyline.c
+++ b/liblwgeom/cunit/cu_in_encoded_polyline.c
@@ -69,6 +69,13 @@ static void in_encoded_polyline_test_truncated_input(void)
 	CU_ASSERT_PTR_NULL(lwgeom_from_encoded_polyline("`", 5));
 }
 
+static void
+in_encoded_polyline_test_overlong_varint(void)
+{
+	/* OSSFuzz 6152109301760000: 17 << 30 must be rejected before shifting. */
+	CU_ASSERT_PTR_NULL(lwgeom_from_encoded_polyline("~~~~~~P", 5));
+}
+
 /*
 ** Used by test harness to register the tests in this file.
 */
@@ -80,4 +87,5 @@ void in_encoded_polyline_suite_setup(void)
 	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);
+	PG_ADD_TEST(suite, in_encoded_polyline_test_overlong_varint);
 }
diff --git a/liblwgeom/lwin_encoded_polyline.c b/liblwgeom/lwin_encoded_polyline.c
index d1af103ea..ef35d8c0f 100644
--- a/liblwgeom/lwin_encoded_polyline.c
+++ b/liblwgeom/lwin_encoded_polyline.c
@@ -32,6 +32,50 @@
 #include "lwgeom_log.h"
 #include "../postgis_config.h"
 
+static int
+encoded_polyline_read_varint(const char *encodedpolyline, int length, int *idx, uint32_t *value)
+{
+	uint32_t res = 0;
+	unsigned int shift = 0;
+
+	while (1)
+	{
+		int byte;
+		if (*idx >= length)
+		{
+			lwerror("lwgeom_from_encoded_polyline: input is truncated");
+			return LW_FALSE;
+		}
+
+		byte = (unsigned char)encodedpolyline[(*idx)++] - 63;
+		if (byte < 0)
+		{
+			lwerror("lwgeom_from_encoded_polyline: input contains an invalid byte");
+			return LW_FALSE;
+		}
+		if (shift > 30 || (shift == 30 && ((byte & 0x1C) || (byte >= 0x20))))
+		{
+			lwerror("lwgeom_from_encoded_polyline: coordinate value is too large");
+			return LW_FALSE;
+		}
+
+		res |= (uint32_t)(byte & 0x1F) << shift;
+		if (byte < 0x20)
+			break;
+
+		shift += 5;
+	}
+
+	*value = res;
+	return LW_TRUE;
+}
+
+static int32_t
+encoded_polyline_zigzag_decode(uint32_t value)
+{
+	return (int32_t)((value >> 1) ^ (uint32_t)(-(int32_t)(value & 1)));
+}
+
 LWGEOM*
 lwgeom_from_encoded_polyline(const char *encodedpolyline, int precision)
 {
@@ -48,36 +92,22 @@ lwgeom_from_encoded_polyline(const char *encodedpolyline, int precision)
 
   while (idx < length) {
     POINT4D pt;
-    char byte = 0;
+    uint32_t res = 0;
 
-    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;
-    } while (byte >= 0x20);
-    int32_t deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1));
+    if (!encoded_polyline_read_varint(encodedpolyline, length, &idx, &res))
+    {
+	    ptarray_free(pa);
+	    return NULL;
+    }
+    int32_t deltaLat = encoded_polyline_zigzag_decode(res);
     latitude += deltaLat;
 
-    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;
-    } while (byte >= 0x20);
-    int32_t deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1));
+    if (!encoded_polyline_read_varint(encodedpolyline, length, &idx, &res))
+    {
+	    ptarray_free(pa);
+	    return NULL;
+    }
+    int32_t deltaLon = encoded_polyline_zigzag_decode(res);
     longitude += deltaLon;
 
     pt.x = longitude/scale;

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

Summary of changes:
 NEWS                                     |  2 +
 liblwgeom/cunit/cu_in_encoded_polyline.c |  8 +++
 liblwgeom/lwin_encoded_polyline.c        | 86 +++++++++++++++++++++-----------
 3 files changed, 68 insertions(+), 28 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list