Skip to content

Commit

Permalink
Merge pull request #9400 from rouault/fix_9388
Browse files Browse the repository at this point in the history
OpenFileGDB writer: fix corrupted maximum blob size header field in some SetFeature() scenarios (fixes #9388)
  • Loading branch information
rouault authored Mar 6, 2024
2 parents 70e50ac + fdf3901 commit fd0c4f4
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
39 changes: 38 additions & 1 deletion autotest/ogr/ogr_openfilegdb_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ def setup_driver():
if filegdb_driver is not None:
filegdb_driver.Deregister()

yield
with gdaltest.config_option(
"OGR_OPENFILEGDB_ERROR_ON_INCONSISTENT_BUFFER_MAX_SIZE", "YES"
):
yield

if filegdb_driver is not None:
print("Reregistering FileGDB driver")
Expand Down Expand Up @@ -4493,3 +4496,37 @@ def test_ogr_openfilegdb_write_new_datetime_types(tmp_vsimem):
f = sql_lyr.GetNextFeature()
assert f["MIN_timestamp_offset"] == "1900/12/31 14:01:01"
assert f["MAX_timestamp_offset"] == "2023/12/30 14:01:01"


###############################################################################
# Test updating an existing feature with one whose m_nRowBlobLength is
# larger than m_nHeaderBufferMaxSize


def test_ogr_openfilegdb_write_update_feature_larger(tmp_vsimem):

filename = str(tmp_vsimem / "out.gdb")
ds = ogr.GetDriverByName("OpenFileGDB").CreateDataSource(filename)
srs = osr.SpatialReference()
srs.ImportFromEPSG(4326)
lyr = ds.CreateLayer("test", srs, ogr.wkbLineString)
f = ogr.Feature(lyr.GetLayerDefn())
g = ogr.Geometry(ogr.wkbLineString)
g.SetPoint_2D(10, 0, 0)
f.SetGeometry(g)
lyr.CreateFeature(f)
ds = None

ds = ogr.Open(filename, update=1)
lyr = ds.GetLayer(0)
f = lyr.GetNextFeature()
g = ogr.Geometry(ogr.wkbLineString)
g.SetPoint_2D(999, 0, 0)
f.SetGeometry(g)
lyr.SetFeature(f)
ds = None

ds = ogr.Open(filename)
lyr = ds.GetLayer(0)
f = lyr.GetNextFeature()
assert f.GetGeometryRef().GetGeometryRef(0).GetPointCount() == 1000
24 changes: 24 additions & 0 deletions ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1532,6 +1532,30 @@ int FileGDBTable::SelectRow(int iRow)
m_nRowBlobLength > INT_MAX - ZEROES_AFTER_END_OF_BUFFER,
m_nCurRow = -1);

if (m_nRowBlobLength > m_nHeaderBufferMaxSize)
{
if (CPLTestBool(CPLGetConfigOption(
"OGR_OPENFILEGDB_ERROR_ON_INCONSISTENT_BUFFER_MAX_SIZE",
"NO")))
{
CPLError(CE_Failure, CPLE_AppDefined,
"Invalid row length (%u) on feature %u compared "
"to the maximum size in the header (%u)",
m_nRowBlobLength, iRow + 1,
m_nHeaderBufferMaxSize);
m_nCurRow = -1;
return errorRetValue;
}
else
{
CPLDebug("OpenFileGDB",
"Invalid row length (%u) on feature %u compared "
"to the maximum size in the header (%u)",
m_nRowBlobLength, iRow + 1,
m_nHeaderBufferMaxSize);
}
}

if (m_nRowBlobLength > m_nRowBufferMaxSize)
{
/* For suspicious row blob length, check if we don't go beyond
Expand Down
9 changes: 9 additions & 0 deletions ogr/ogrsf_frmts/openfilegdb/filegdbtable_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1880,6 +1880,10 @@ bool FileGDBTable::CreateFeature(const std::vector<OGRField> &asRawFields,
*pnFID = nObjectID;

m_nRowBlobLength = static_cast<uint32_t>(m_abyBuffer.size());
if (m_nRowBlobLength > m_nHeaderBufferMaxSize)
{
m_nHeaderBufferMaxSize = m_nRowBlobLength;
}
m_nRowBufferMaxSize = std::max(m_nRowBufferMaxSize, m_nRowBlobLength);
if (nFreeOffset == OFFSET_MINUS_ONE)
{
Expand Down Expand Up @@ -2012,6 +2016,11 @@ bool FileGDBTable::UpdateFeature(int nFID,
return false;

m_nRowBlobLength = static_cast<uint32_t>(m_abyBuffer.size());
if (m_nRowBlobLength > m_nHeaderBufferMaxSize)
{
m_bDirtyHeader = true;
m_nHeaderBufferMaxSize = m_nRowBlobLength;
}
m_nRowBufferMaxSize = std::max(m_nRowBufferMaxSize, m_nRowBlobLength);
if (nFreeOffset == OFFSET_MINUS_ONE)
{
Expand Down

0 comments on commit fd0c4f4

Please sign in to comment.