Skip to content

Commit 68a63a8

Browse files
authored
Ensure required bytes when reading Polygon types (#4831)
1 parent c04c113 commit 68a63a8

2 files changed

Lines changed: 65 additions & 1 deletion

File tree

src/Npgsql.GeoJSON/Internal/GeoJSONHandler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ async ValueTask<GeoJSONObject> ReadGeometryCore(NpgsqlReadBuffer buf, bool async
167167
var lines = new LineString[buf.ReadInt32(littleEndian)];
168168
for (var i = 0; i < lines.Length; ++i)
169169
{
170+
await buf.Ensure(SizeOfLength, async);
170171
var coordinates = new Position[buf.ReadInt32(littleEndian)];
171172
for (var j = 0; j < coordinates.Length; ++j)
172173
{
@@ -230,6 +231,7 @@ async ValueTask<GeoJSONObject> ReadGeometryCore(NpgsqlReadBuffer buf, bool async
230231
var lines = new LineString[buf.ReadInt32(littleEndian)];
231232
for (var j = 0; j < lines.Length; ++j)
232233
{
234+
await buf.Ensure(SizeOfLength, async);
233235
var coordinates = new Position[buf.ReadInt32(littleEndian)];
234236
for (var k = 0; k < coordinates.Length; ++k)
235237
{
@@ -498,7 +500,7 @@ public async Task Write(Polygon value, NpgsqlWriteBuffer buf, NpgsqlLengthCache?
498500

499501
for (var i = 0; i < lines.Count; ++i)
500502
{
501-
if (buf.WriteSpaceLeft < 4)
503+
if (buf.WriteSpaceLeft < SizeOfLength)
502504
await buf.Flush(async, cancellationToken);
503505
var coordinates = lines[i].Coordinates;
504506
buf.WriteInt32(coordinates.Count);

test/Npgsql.PluginTests/GeoJSONTests.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,68 @@ public async Task Import_big_geometry()
346346
Assert.That(actual, Is.EqualTo(geometry));
347347
}
348348

349+
[Test, TestCaseSource(nameof(Tests))]
350+
public async Task Export_geometry(TestData data)
351+
{
352+
await using var conn = await OpenConnectionAsync(options: GeoJSONOptions.BoundingBox);
353+
var table = await CreateTempTable(conn, "field geometry");
354+
355+
await using (var writer = await conn.BeginBinaryImportAsync($"COPY {table} (field) FROM STDIN BINARY"))
356+
{
357+
await writer.StartRowAsync();
358+
await writer.WriteAsync(data.Geometry, NpgsqlDbType.Geometry);
359+
360+
var rowsWritten = await writer.CompleteAsync();
361+
Assert.That(rowsWritten, Is.EqualTo(1));
362+
}
363+
364+
await using (var reader = await conn.BeginBinaryExportAsync($"COPY {table} (field) TO STDOUT BINARY"))
365+
{
366+
await reader.StartRowAsync();
367+
var field = await reader.ReadAsync<GeoJSONObject>(NpgsqlDbType.Geometry);
368+
Assert.That(field, Is.EqualTo(data.Geometry));
369+
}
370+
}
371+
372+
[Test, IssueLink("https://github.com/npgsql/npgsql/issues/4830")]
373+
public async Task Export_big_geometry()
374+
{
375+
await using var conn = await OpenConnectionAsync();
376+
var table = await CreateTempTable(conn, "id text, field geometry");
377+
378+
var geometry = new Polygon(new[] {
379+
new LineString(
380+
Enumerable.Range(1, 507)
381+
.Select(i => new Position(longitude: i, latitude: i))
382+
.Append(new Position(longitude: 1d, latitude: 1d))),
383+
new LineString(new[] {
384+
new Position(longitude: 1d, latitude: 1d),
385+
new Position(longitude: 1d, latitude: 2d),
386+
new Position(longitude: 1d, latitude: 3d),
387+
new Position(longitude: 1d, latitude: 1d),
388+
})
389+
});
390+
391+
await using (var writer = await conn.BeginBinaryImportAsync($"COPY {table} (id, field) FROM STDIN BINARY"))
392+
{
393+
await writer.StartRowAsync();
394+
await writer.WriteAsync("aaaa", NpgsqlDbType.Text);
395+
await writer.WriteAsync(geometry, NpgsqlDbType.Geometry);
396+
397+
var rowsWritten = await writer.CompleteAsync();
398+
Assert.That(rowsWritten, Is.EqualTo(1));
399+
}
400+
401+
await using (var reader = await conn.BeginBinaryExportAsync($"COPY {table} (id, field) TO STDOUT BINARY"))
402+
{
403+
await reader.StartRowAsync();
404+
var id = await reader.ReadAsync<string>();
405+
var field = await reader.ReadAsync<GeoJSONObject>(NpgsqlDbType.Geometry);
406+
Assert.That(id, Is.EqualTo("aaaa"));
407+
Assert.That(field, Is.EqualTo(geometry));
408+
}
409+
}
410+
349411
ValueTask<NpgsqlConnection> OpenConnectionAsync(GeoJSONOptions options = GeoJSONOptions.None)
350412
=> GetDataSource(options).OpenConnectionAsync();
351413

0 commit comments

Comments
 (0)