[SCM] PostGIS branch stable-3.5 updated. 3.5.6-3-ga636b7efc
git at osgeo.org
git at osgeo.org
Wed May 27 16:22:09 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 a636b7efccd358acc430d8863159a54800b76079 (commit)
via 33505fb1ab7f8ff8789273f233aeb18753e8ac02 (commit)
from 0f83064d660300256e043ff55c44320d25b9ad42 (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 a636b7efccd358acc430d8863159a54800b76079
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date: Wed May 27 16:22:03 2026 -0700
News entry for flatgeobuf schema fix
diff --git a/NEWS b/NEWS
index 5382dc191..b6e81181a 100644
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,8 @@ PostGIS 3.5.7
* Bug Fixes *
- -
+ - Flatgeobuf schema mismatch vulnerability (NeuroWinter)
+
PostGIS 3.5.6
commit 33505fb1ab7f8ff8789273f233aeb18753e8ac02
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date: Wed May 27 21:52:25 2026 +0000
Check that user-provided flatbuffer schema matches
The flatbuffer import maps an incoming file to a provided
table schema, and the consistency of those two schemes
needs to be checked before data are copied across.
diff --git a/postgis/flatgeobuf.c b/postgis/flatgeobuf.c
index 52ef420ef..048e9fbe0 100644
--- a/postgis/flatgeobuf.c
+++ b/postgis/flatgeobuf.c
@@ -287,8 +287,6 @@ static void decode_properties(struct flatgeobuf_decode_ctx *ctx, Datum *values,
POSTGIS_DEBUGF(3, "flatgeobuf: decode_properties from byte array with length %d at offset %d", size, offset);
- // TODO: init isnull
-
if (size > 0 && size < (sizeof(uint16_t) + sizeof(uint8_t)))
elog(ERROR, "flatgeobuf: decode_properties: Unexpected properties data size %d", size);
while (offset + 1 < size) {
@@ -389,7 +387,10 @@ static void decode_properties(struct flatgeobuf_decode_ctx *ctx, Datum *values,
if (offset + sizeof(float) > size)
elog(ERROR, "flatgeobuf: decode_properties: Invalid size for float value");
memcpy(&value, data + offset, sizeof(float));
- values[ci] = Float4GetDatum(value);
+ if (getBaseType(TupleDescAttr(ctx->tupdesc, ci)->atttypid) == FLOAT8OID)
+ values[ci] = Float8GetDatum((double) value);
+ else
+ values[ci] = Float4GetDatum(value);
offset += sizeof(float);
break;
}
@@ -467,7 +468,9 @@ void flatgeobuf_decode_row(struct flatgeobuf_decode_ctx *ctx)
uint32_t natts = ctx->tupdesc->natts;
Datum *values = palloc0(natts * sizeof(Datum));
- bool *isnull = palloc0(natts * sizeof(bool));
+ bool *isnull = palloc(natts * sizeof(bool));
+ for (uint32_t j = 0; j < natts; j++) isnull[j] = true;
+ isnull[0] = false;
values[0] = Int32GetDatum(ctx->fid);
@@ -476,6 +479,7 @@ void flatgeobuf_decode_row(struct flatgeobuf_decode_ctx *ctx)
if (ctx->ctx->lwgeom != NULL) {
values[1] = PointerGetDatum(geometry_serialize(ctx->ctx->lwgeom));
+ isnull[1] = false;
} else {
POSTGIS_DEBUG(3, "geometry is null");
isnull[1] = true;
diff --git a/postgis/lwgeom_in_flatgeobuf.c b/postgis/lwgeom_in_flatgeobuf.c
index ac460ff7a..773b50f98 100644
--- a/postgis/lwgeom_in_flatgeobuf.c
+++ b/postgis/lwgeom_in_flatgeobuf.c
@@ -67,6 +67,60 @@ static char *get_pgtype(uint8_t column_type) {
elog(ERROR, "unknown column_type %d", column_type);
}
+static const char *
+flatgeobuf_type_name(uint8_t fgb_type)
+{
+ /* Names match FlatGeobuf::EnumNamesColumnType() in header_generated.h */
+ static const char * const names[] = {
+ "Byte", "UByte", "Bool", "Short", "UShort",
+ "Int", "UInt", "Long", "ULong",
+ "Float", "Double", "String", "Json", "DateTime", "Binary"
+ };
+ if (fgb_type >= sizeof(names) / sizeof(names[0]))
+ return "unknown";
+ return names[fgb_type];
+}
+
+static bool
+flatgeobuf_type_compatible(uint8_t fgb_type, Oid pgtype)
+{
+ switch (fgb_type)
+ {
+ case flatgeobuf_column_type_bool:
+ return pgtype == BOOLOID;
+ /* small integer types: allow widening into larger signed ints */
+ case flatgeobuf_column_type_byte:
+ case flatgeobuf_column_type_ubyte:
+ case flatgeobuf_column_type_short:
+ case flatgeobuf_column_type_ushort:
+ return pgtype == INT2OID || pgtype == INT4OID || pgtype == INT8OID;
+ /* int32: allow widening to bigint */
+ case flatgeobuf_column_type_int:
+ return pgtype == INT4OID || pgtype == INT8OID;
+ /* uint32 max exceeds INT4, must land in bigint */
+ case flatgeobuf_column_type_uint:
+ return pgtype == INT8OID;
+ case flatgeobuf_column_type_long:
+ case flatgeobuf_column_type_ulong:
+ return pgtype == INT8OID;
+ /* float: allow widening to double (explicit conversion handled in decode) */
+ case flatgeobuf_column_type_float:
+ return pgtype == FLOAT4OID || pgtype == FLOAT8OID;
+ case flatgeobuf_column_type_double:
+ return pgtype == FLOAT8OID;
+ case flatgeobuf_column_type_string:
+ return pgtype == TEXTOID || pgtype == VARCHAROID;
+ case flatgeobuf_column_type_datetime:
+ return pgtype == DATEOID || pgtype == TIMEOID ||
+ pgtype == TIMESTAMPOID || pgtype == TIMESTAMPTZOID;
+ case flatgeobuf_column_type_json:
+ return pgtype == JSONBOID;
+ case flatgeobuf_column_type_binary:
+ return pgtype == BYTEAOID;
+ }
+ return false;
+}
+
PG_FUNCTION_INFO_V1(pgis_tablefromflatgeobuf);
Datum pgis_tablefromflatgeobuf(PG_FUNCTION_ARGS)
{
@@ -192,7 +246,29 @@ Datum pgis_fromflatgeobuf(PG_FUNCTION_ARGS)
SRF_RETURN_DONE(funcctx);
}
- // TODO: get table and verify structure against header
+ /* Validate that the file schema matches the caller-supplied composite type.
+ * tupdesc positions 0 (fid) and 1 (geom) are fixed; file columns start at 2. */
+ if (ctx->ctx->columns_size != (uint32_t)(tupdesc->natts - 2))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("flatgeobuf: column count mismatch: "
+ "file has %u columns, target type has %d",
+ ctx->ctx->columns_size, tupdesc->natts - 2)));
+
+ for (uint16_t col_i = 0; col_i < ctx->ctx->columns_size; col_i++)
+ {
+ flatgeobuf_column *col = ctx->ctx->columns[col_i];
+ Oid pgtype = getBaseType(TupleDescAttr(tupdesc, col_i + 2)->atttypid);
+ if (!flatgeobuf_type_compatible(col->type, pgtype))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("flatgeobuf: column \"%s\" type mismatch: "
+ "file type \"%s\" is not compatible with PostgreSQL type %s",
+ col->name,
+ flatgeobuf_type_name(col->type),
+ format_type_be(pgtype))));
+ }
+
MemoryContextSwitchTo(oldcontext);
}
-----------------------------------------------------------------------
Summary of changes:
NEWS | 3 +-
postgis/flatgeobuf.c | 12 ++++---
postgis/lwgeom_in_flatgeobuf.c | 78 +++++++++++++++++++++++++++++++++++++++++-
3 files changed, 87 insertions(+), 6 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list