Skip to content

Commit 706fe8a

Browse files
authored
Merge pull request #13521 from dbaston/check-coverage-multiple-input
GDALGeosNonStreamingAlgorithmDataset: Avoid crash with multiple input layers
2 parents 379bec3 + 7286103 commit 706fe8a

File tree

3 files changed

+53
-14
lines changed

3 files changed

+53
-14
lines changed

apps/gdalalg_vector_geom.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,22 +138,42 @@ GDALGeosNonStreamingAlgorithmDataset::GDALGeosNonStreamingAlgorithmDataset()
138138

139139
GDALGeosNonStreamingAlgorithmDataset::~GDALGeosNonStreamingAlgorithmDataset()
140140
{
141+
Cleanup();
142+
if (m_poGeosContext != nullptr)
143+
{
144+
finishGEOS_r(m_poGeosContext);
145+
}
146+
}
147+
148+
void GDALGeosNonStreamingAlgorithmDataset::Cleanup()
149+
{
150+
m_apoFeatures.clear();
151+
141152
if (m_poGeosContext != nullptr)
142153
{
143154
for (auto &poGeom : m_apoGeosInputs)
144155
{
145156
GEOSGeom_destroy_r(m_poGeosContext, poGeom);
146157
}
158+
m_apoGeosInputs.clear();
147159

148-
GEOSGeom_destroy_r(m_poGeosContext, m_poGeosResultAsCollection);
160+
if (m_poGeosContext != nullptr)
161+
{
162+
GEOSGeom_destroy_r(m_poGeosContext, m_poGeosResultAsCollection);
163+
m_poGeosResultAsCollection = nullptr;
164+
}
149165

150166
for (size_t i = 0; i < m_nGeosResultSize; i++)
151167
{
152168
GEOSGeom_destroy_r(m_poGeosContext, m_papoGeosResults[i]);
153169
}
170+
m_nGeosResultSize = 0;
154171

155-
GEOSFree_r(m_poGeosContext, m_papoGeosResults);
156-
finishGEOS_r(m_poGeosContext);
172+
if (m_papoGeosResults != nullptr)
173+
{
174+
GEOSFree_r(m_poGeosContext, m_papoGeosResults);
175+
m_papoGeosResults = nullptr;
176+
}
157177
}
158178
}
159179

@@ -314,6 +334,8 @@ bool GDALGeosNonStreamingAlgorithmDataset::ConvertOutputsFromGeos(
314334
bool GDALGeosNonStreamingAlgorithmDataset::Process(OGRLayer &srcLayer,
315335
OGRLayer &dstLayer)
316336
{
337+
Cleanup();
338+
317339
bool sameDefn = dstLayer.GetLayerDefn()->IsSame(srcLayer.GetLayerDefn());
318340

319341
if (!ConvertInputsToGeos(srcLayer, dstLayer, sameDefn))

apps/gdalalg_vector_geom.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,6 @@ class GDALGeosNonStreamingAlgorithmDataset
207207

208208
CPL_DISALLOW_COPY_ASSIGN(GDALGeosNonStreamingAlgorithmDataset)
209209

210-
bool ConvertInputsToGeos(OGRLayer &srcLayer, OGRLayer &dstLayer,
211-
bool sameDefn);
212-
213-
bool ConvertOutputsFromGeos(OGRLayer &dstLayer);
214-
215210
bool Process(OGRLayer &srcLayer, OGRLayer &dstLayer) override;
216211

217212
virtual bool ProcessGeos() = 0;
@@ -234,6 +229,13 @@ class GDALGeosNonStreamingAlgorithmDataset
234229
GEOSGeometry **m_papoGeosResults{nullptr};
235230

236231
private:
232+
bool ConvertInputsToGeos(OGRLayer &srcLayer, OGRLayer &dstLayer,
233+
bool sameDefn);
234+
235+
bool ConvertOutputsFromGeos(OGRLayer &dstLayer);
236+
237+
void Cleanup();
238+
237239
std::vector<std::unique_ptr<OGRFeature>> m_apoFeatures{};
238240
unsigned int m_nGeosResultSize{0};
239241
int m_sourceGeometryField{0};

autotest/utilities/test_gdalalg_vector_check_coverage.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ def test_gdalalg_vector_check_coverage_invalid_layer(alg, three_rectangles):
8080
assert alg.Run()
8181

8282

83-
def test_gdalalg_vector_check_geometry_two_layers(alg, three_rectangles):
83+
@pytest.mark.parametrize("input_layers", (1, 2))
84+
def test_gdalalg_vector_check_coverage_two_layers(alg, three_rectangles, input_layers):
8485

8586
poly_ds = gdal.OpenEx("../ogr/data/poly.shp", gdal.OF_VECTOR)
8687

@@ -89,18 +90,32 @@ def test_gdalalg_vector_check_geometry_two_layers(alg, three_rectangles):
8990
ds.CopyLayer(three_rectangles.GetLayer(0), "poly2")
9091

9192
alg["input"] = ds
92-
alg["input-layer"] = "poly2"
9393
alg["output"] = ""
9494
alg["output-format"] = "stream"
95+
if input_layers == 1:
96+
alg["input-layer"] = "poly2"
97+
else:
98+
alg["input-layer"] = ["poly2", "poly1"]
9599

96100
assert alg.Run()
97101

98102
dst_ds = alg["output"].GetDataset()
99-
dst_lyr = dst_ds.GetLayer(0)
103+
assert dst_ds.GetLayerCount() == input_layers
104+
105+
for i in range(input_layers):
106+
dst_lyr = dst_ds.GetLayer(i)
107+
108+
errors = 2 if i == 0 else 0
109+
110+
if input_layers == 1:
111+
assert dst_lyr.GetName() == "invalid_edge"
112+
else:
113+
assert dst_lyr.GetName() == f"invalid_edge_{alg['input-layer'][i]}"
114+
115+
assert dst_lyr.GetFeatureCount() == errors
100116

101-
assert dst_lyr.GetFeatureCount() == 2
102-
for f in dst_lyr:
103-
assert f.GetGeometryRef().GetGeometryType() == ogr.wkbMultiLineString
117+
for f in dst_lyr:
118+
assert f.GetGeometryRef().GetGeometryType() == ogr.wkbMultiLineString
104119

105120
assert alg.Finalize()
106121

0 commit comments

Comments
 (0)