diff --git a/Lib/test/test_dbm.py b/Lib/test/test_dbm.py index ae9faabd536a6c..5db2e658f45585 100644 --- a/Lib/test/test_dbm.py +++ b/Lib/test/test_dbm.py @@ -71,6 +71,11 @@ def test_error(self): def test_anydbm_not_existing(self): self.assertRaises(dbm.error, dbm.open, _fname) + def test_open_nonexistent_directory(self): + missing_dir = os.path.join(dirname + "_does_not_exist", "test.db") + with self.assertRaises(OSError): + dbm.open(missing_dir, "c") + def test_anydbm_creation(self): f = dbm.open(_fname, 'c') self.assertEqual(list(f.keys()), []) diff --git a/Misc/NEWS.d/next/C_API/2026-01-20-20-17-16.gh-issue-144069.IE5fug.rst b/Misc/NEWS.d/next/C_API/2026-01-20-20-17-16.gh-issue-144069.IE5fug.rst new file mode 100644 index 00000000000000..6167c1d362b02b --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-01-20-20-17-16.gh-issue-144069.IE5fug.rst @@ -0,0 +1,2 @@ +Fix a memory leak in :func:`dbm.open` when database creation fails, such as +when the target directory does not exist. diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index f88861fa24423b..12ee08e01820f8 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -85,10 +85,11 @@ newdbmobject(_dbm_state *state, const char *file, int flags, int mode) } dp->di_size = -1; dp->flags = flags; + dp->di_dbm = NULL; PyObject_GC_Track(dp); /* See issue #19296 */ - if ( (dp->di_dbm = dbm_open((char *)file, flags, mode)) == 0 ) { + if ( (dp->di_dbm = dbm_open((char *)file, flags, mode)) == NULL ) { PyErr_SetFromErrnoWithFilename(state->dbm_error, file); Py_DECREF(dp); return NULL; @@ -105,6 +106,7 @@ dbm_dealloc(PyObject *self) PyObject_GC_UnTrack(dp); if (dp->di_dbm) { dbm_close(dp->di_dbm); + dp->di_dbm = NULL; } PyTypeObject *tp = Py_TYPE(dp); tp->tp_free(dp);