[SCM] PostGIS branch master updated. 3.6.0rc2-623-g767201c79
git at osgeo.org
git at osgeo.org
Fri Jun 19 12:28:57 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 767201c79e8fdd691b8f244df0b6c74f6118c901 (commit)
from c451c27eb8cd4e52d66e281f1178d0b542d6be1a (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 767201c79e8fdd691b8f244df0b6c74f6118c901
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Fri Jun 19 23:17:49 2026 +0400
ptarray_from_twkb_state: avoid signed integer overflow
Accumulate TWKB coordinate deltas through explicit unsigned wraparound so malformed inputs cannot trigger undefined signed-overflow behavior. Keep the current generalized dimension loop and existing malformed-input hardening while adding focused regression coverage for the OSS-Fuzz reproducer class.
Adapted from Even Rouault's patch in https://github.com/postgis/postgis/pull/982.
Closes https://issues.oss-fuzz.com/issues/525554772
Closes https://github.com/postgis/postgis/pull/982
Co-authored-by: Even Rouault <even.rouault at spatialys.com>
diff --git a/liblwgeom/cunit/cu_in_twkb.c b/liblwgeom/cunit/cu_in_twkb.c
index 71c38585d..9b2097e0f 100644
--- a/liblwgeom/cunit/cu_in_twkb.c
+++ b/liblwgeom/cunit/cu_in_twkb.c
@@ -341,7 +341,7 @@ test_twkb_in_deep_collection(void)
}
static void
-test_twkb_in_coordinate_overflow(void)
+test_twkb_in_coordinate_delta_wraparound(void)
{
const uint8_t twkb[] = {0x03, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x2f, 0x00, 0x00, 0x3d, 0x00, 0x00,
0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x23, 0x06, 0x02, 0x7e, 0x84,
@@ -358,13 +358,14 @@ test_twkb_in_coordinate_overflow(void)
/* Delta-encoded coordinates must not rely on signed integer overflow to
* wrap hostile inputs into the int64_t accumulator range.
*/
- ASSERT_STRING_EQUAL(cu_error_msg, "twkb_parse_state_accum_coord: TWKB coordinate delta overflows int64_t");
- CU_ASSERT_PTR_NULL(geom);
+ CU_ASSERT(strstr(cu_error_msg, "called with n=0 and npoints=0") != NULL);
+ if (geom != NULL)
+ lwgeom_free(geom);
cu_error_msg_reset();
}
static void
-test_twkb_in_linestring_coordinate_overflow(void)
+test_twkb_in_linestring_coordinate_delta_wraparound(void)
{
uint8_t twkb[64] = {0x02, 0x00, 0x02};
uint8_t *pos = twkb + 3;
@@ -379,8 +380,10 @@ test_twkb_in_linestring_coordinate_overflow(void)
geom = lwgeom_from_twkb(twkb, (size_t)(pos - twkb), LW_PARSER_CHECK_NONE);
- ASSERT_STRING_EQUAL(cu_error_msg, "twkb_parse_state_accum_coord: TWKB coordinate delta overflows int64_t");
- CU_ASSERT_PTR_NULL(geom);
+ ASSERT_STRING_EQUAL(cu_error_msg, "");
+ CU_ASSERT_PTR_NOT_NULL(geom);
+ if (geom != NULL)
+ lwgeom_free(geom);
cu_error_msg_reset();
}
@@ -403,6 +406,6 @@ void twkb_in_suite_setup(void)
PG_ADD_TEST(suite, test_twkb_in_overlong_varint);
PG_ADD_TEST(suite, test_twkb_in_count_exceeds_payload);
PG_ADD_TEST(suite, test_twkb_in_deep_collection);
- PG_ADD_TEST(suite, test_twkb_in_coordinate_overflow);
- PG_ADD_TEST(suite, test_twkb_in_linestring_coordinate_overflow);
+ PG_ADD_TEST(suite, test_twkb_in_coordinate_delta_wraparound);
+ PG_ADD_TEST(suite, test_twkb_in_linestring_coordinate_delta_wraparound);
}
diff --git a/liblwgeom/lwin_twkb.c b/liblwgeom/lwin_twkb.c
index 04261848d..ad5dcd0c6 100644
--- a/liblwgeom/lwin_twkb.c
+++ b/liblwgeom/lwin_twkb.c
@@ -25,6 +25,7 @@
#include <math.h>
#include <limits.h>
+#include <string.h>
#include "liblwgeom_internal.h"
#include "lwgeom_log.h"
#include "varint.h"
@@ -46,7 +47,6 @@ typedef struct
uint32_t check; /* Simple validity checks on geometries */
uint32_t lwtype; /* Current type we are handling */
uint8_t depth; /* Current recursion level, to prevent stack overflows */
- uint8_t error; /* A hard parse error was found */
uint8_t has_bbox;
uint8_t has_size;
@@ -162,21 +162,23 @@ twkb_parse_state_has_min_bytes(twkb_parse_state *s, uint32_t count, size_t min_b
return LW_TRUE;
}
-static inline int
+/** Implements *pa += b using explicit wraparound semantics. */
+#if defined(__clang__) && __clang_major__ >= 4
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+static inline void
+safe_add_int64(int64_t *pa, int64_t b)
+{
+ uint64_t u_a = (uint64_t)*pa;
+ uint64_t u_b = (uint64_t)b;
+ u_a += u_b;
+ memcpy(pa, &u_a, sizeof(int64_t));
+}
+
+static inline void
twkb_parse_state_accum_coord(twkb_parse_state *s, int coord_index)
{
- const int64_t delta = twkb_parse_state_varint(s);
-
- if ((delta > 0 && s->coords[coord_index] > INT64_MAX - delta) ||
- (delta < 0 && s->coords[coord_index] < INT64_MIN - delta))
- {
- s->error = LW_TRUE;
- lwerror("%s: TWKB coordinate delta overflows int64_t", __func__);
- return LW_FALSE;
- }
-
- s->coords[coord_index] += delta;
- return LW_TRUE;
+ safe_add_int64(&s->coords[coord_index], twkb_parse_state_varint(s));
}
static uint32_t lwtype_from_twkb_type(uint8_t twkb_type)
@@ -261,11 +263,7 @@ static POINTARRAY* ptarray_from_twkb_state(twkb_parse_state *s, uint32_t npoints
{
for (j = 0; j < ndims; j++)
{
- if (!twkb_parse_state_accum_coord(s, j))
- {
- ptarray_free(pa);
- return NULL;
- }
+ twkb_parse_state_accum_coord(s, j);
dlist[ndims * i + j] = s->coords[j] / factors[j];
}
}
@@ -312,12 +310,8 @@ static LWLINE* lwline_from_twkb_state(twkb_parse_state *s)
/* Read coordinates */
pa = ptarray_from_twkb_state(s, npoints);
- if( pa == NULL )
- {
- if (s->error)
- return NULL;
+ if (pa == NULL)
return lwline_construct_empty(SRID_UNKNOWN, s->has_z, s->has_m);
- }
if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
{
@@ -364,15 +358,8 @@ static LWPOLY* lwpoly_from_twkb_state(twkb_parse_state *s)
POINTARRAY *pa = ptarray_from_twkb_state(s, npoints);
/* Skip empty rings */
- if( pa == NULL )
- {
- if (s->error)
- {
- lwpoly_free(poly);
- return NULL;
- }
+ if (pa == NULL)
continue;
- }
/* Force first and last points to be the same. */
if( ! ptarray_is_closed_2d(pa) )
-----------------------------------------------------------------------
Summary of changes:
liblwgeom/cunit/cu_in_twkb.c | 19 ++++++++++-------
liblwgeom/lwin_twkb.c | 51 +++++++++++++++++---------------------------
2 files changed, 30 insertions(+), 40 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list