Skip to content

Commit

Permalink
Merge pull request #11149 from OSGeo/backport-11138-to-release/3.10
Browse files Browse the repository at this point in the history
[Backport release/3.10] SQLite/GPKG: turn on SQLite 'PRAGMA secure_delete=1' by default
  • Loading branch information
rouault authored Oct 28, 2024
2 parents 2287b5a + b2328a7 commit 0607e2e
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 1 deletion.
46 changes: 46 additions & 0 deletions autotest/ogr/ogr_gpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -10540,3 +10540,49 @@ def test_gpkg_create_more_than_2000_fields(tmp_vsimem):
with pytest.raises(Exception, match="Limit of 2000 columns reached"):
lyr.CreateField(ogr.FieldDefn("foo"))
assert lyr.GetLayerDefn().GetFieldCount() == 2000 - 2


###############################################################################
# Test that secure_delete is turned on


@gdaltest.enable_exceptions()
def test_gpkg_secure_delete(tmp_vsimem):

filename = str(tmp_vsimem / "secure_delete.gpkg")
with ogr.GetDriverByName("GPKG").CreateDataSource(filename) as ds:

with ds.ExecuteSQL("PRAGMA secure_delete") as sql_lyr:
f = sql_lyr.GetNextFeature()
assert f.GetField(0) == 1

lyr = ds.CreateLayer("test")
lyr.CreateField(ogr.FieldDefn("foo"))
f = ogr.Feature(lyr.GetLayerDefn())
f["foo"] = "very_secret"
lyr.CreateFeature(f)

f = gdal.VSIFOpenL(filename, "rb")
data = gdal.VSIFReadL(1, 100000, f)
gdal.VSIFCloseL(f)
assert b"very_secret" in data

with ogr.Open(filename, update=1) as ds:

with ds.ExecuteSQL("PRAGMA secure_delete") as sql_lyr:
f = sql_lyr.GetNextFeature()
assert f.GetField(0) == 1

lyr = ds.GetLayer(0)
lyr.DeleteFeature(1)

f = gdal.VSIFOpenL(filename, "rb")
data = gdal.VSIFReadL(1, 100000, f)
gdal.VSIFCloseL(f)
assert b"very_secret" not in data

with gdaltest.config_option("OGR_SQLITE_PRAGMA", "secure_delete=0"):
with ogr.Open(filename, update=1) as ds:
with ds.ExecuteSQL("PRAGMA secure_delete") as sql_lyr:
f = sql_lyr.GetNextFeature()
assert f.GetField(0) == 0
12 changes: 12 additions & 0 deletions doc/source/drivers/vector/gpkg.rst
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,18 @@ Examples
-sql "SELECT poly.id, other.foo FROM poly JOIN other_schema.other USING (id)" \
-oo PRELUDE_STATEMENTS="ATTACH DATABASE 'other.gpkg' AS other_schema"

Secure deletion
---------------

Depending on how SQLite3 is built, `secure deletion <https://www.sqlite.org/pragma.html#pragma_secure_delete>`__
might or might not be enabled.
Starting with GDAL 3.10, secure deletion is always enabled, unless
``SECURE_DELETE`` is specified through the :config:`OGR_SQLITE_PRAGMA`
configuration option.
Note that secure deletion does not recover potential lost space, so running
a `VACUUM <https://sqlite.org/lang_vacuum.html>`__ query is recommended to fully
optimized a database that has been subject to updates or deletions.

See Also
--------

Expand Down
11 changes: 11 additions & 0 deletions doc/source/drivers/vector/sqlite.rst
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,17 @@ and optimize it.

ogrinfo db.sqlite -sql "VACUUM"

Secure deletion
---------------

Depending on how SQLite3 is built, `secure deletion <https://www.sqlite.org/pragma.html#pragma_secure_delete>`__
might or might not be enabled.
Starting with GDAL 3.10, secure deletion is always enabled, unless
``SECURE_DELETE`` is specified through the :config:`OGR_SQLITE_PRAGMA`
configuration option.
Note that secure deletion does not recover potential lost space, so running
a `VACUUM <https://sqlite.org/lang_vacuum.html>`__ query is recommended to fully
optimized a database that has been subject to updates or deletions.

Example
-------
Expand Down
15 changes: 14 additions & 1 deletion ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,7 @@ bool OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn,
#endif

bool bPageSizeFound = false;
bool bSecureDeleteFound = false;

const char *pszSqlitePragma =
CPLGetConfigOption("OGR_SQLITE_PRAGMA", nullptr);
Expand Down Expand Up @@ -1456,7 +1457,7 @@ bool OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn,
{
if (STARTS_WITH_CI(papszTokens[i], "PAGE_SIZE"))
bPageSizeFound = true;
if (STARTS_WITH_CI(papszTokens[i], "JOURNAL_MODE"))
else if (STARTS_WITH_CI(papszTokens[i], "JOURNAL_MODE"))
{
const char *pszEqual = strchr(papszTokens[i], '=');
if (pszEqual)
Expand All @@ -1467,6 +1468,8 @@ bool OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn,
continue;
}
}
else if (STARTS_WITH_CI(papszTokens[i], "SECURE_DELETE"))
bSecureDeleteFound = true;

const char *pszSQL = CPLSPrintf("PRAGMA %s", papszTokens[i]);

Expand Down Expand Up @@ -1646,6 +1649,16 @@ bool OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn,
sqlite3_exec(hDB, pszSQL, nullptr, nullptr, nullptr));
}

if (!bSecureDeleteFound)
{
// Turn on secure_delete by default (unless the user specifies a
// value of this pragma through OGR_SQLITE_PRAGMA)
// For example, Debian and Conda-Forge SQLite3 builds already turn on
// secure_delete.
CPL_IGNORE_RET_VAL(sqlite3_exec(hDB, "PRAGMA secure_delete = 1",
nullptr, nullptr, nullptr));
}

SetCacheSize();
SetSynchronous();
if (bLoadExtensions)
Expand Down

0 comments on commit 0607e2e

Please sign in to comment.