diff options
author | Lawrence D'Anna <lawrence_danna@apple.com> | 2019-10-30 09:45:13 -0700 |
---|---|---|
committer | Lawrence D'Anna <lawrence_danna@apple.com> | 2019-10-30 09:46:51 -0700 |
commit | 3071ebf7b38341e89be04aa64c257c4643e0648c (patch) | |
tree | dd8c3ba1dd23d951146cce6085e576635f8c0cb8 /lldb/source/Plugins/ScriptInterpreter/Python | |
parent | fbe7f5e9729ac24374182fca92242f88baa08f90 (diff) | |
download | bcm5719-llvm-3071ebf7b38341e89be04aa64c257c4643e0648c.tar.gz bcm5719-llvm-3071ebf7b38341e89be04aa64c257c4643e0648c.zip |
[LLDB][PythonFile] fix dangerous borrow semantics on python2
Summary:
It is inherently unsafe to allow a python program to manipulate borrowed
memory from a python object's destructor. It would be nice to
flush a borrowed file when python is finished with it, but it's not safe
to do on python 2.
Python 3 does not suffer from this issue.
Reviewers: labath, mgorny
Reviewed By: labath
Subscribers: lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D69532
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python')
-rw-r--r-- | lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index df8bac951fc..ef5eb7a57d9 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -1500,21 +1500,23 @@ Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { PyObject *file_obj; #if PY_MAJOR_VERSION >= 3 file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, - "ignore", nullptr, 0); + "ignore", nullptr, /*closefd=*/0); #else - // We pass ::flush instead of ::fclose here so we borrow the FILE* -- - // the lldb_private::File still owns it. NetBSD does not allow - // input files to be flushed, so we have to check for that case too. - int (*closer)(FILE *); - auto opts = file.GetOptions(); - if (!opts) - return opts.takeError(); - if (opts.get() & File::eOpenOptionWrite) - closer = ::fflush; - else - closer = [](FILE *) { return 0; }; + // I'd like to pass ::fflush here if the file is writable, so that + // when the python side destructs the file object it will be flushed. + // However, this would be dangerous. It can cause fflush to be called + // after fclose if the python program keeps a reference to the file after + // the original lldb_private::File has been destructed. + // + // It's all well and good to ask a python program not to use a closed file + // but asking a python program to make sure objects get released in a + // particular order is not safe. + // + // The tradeoff here is that if a python 2 program wants to make sure this + // file gets flushed, they'll have to do it explicitly or wait untill the + // original lldb File itself gets flushed. file_obj = PyFile_FromFile(file.GetStream(), py2_const_cast(""), - py2_const_cast(mode), closer); + py2_const_cast(mode), [](FILE *) { return 0; }); #endif if (!file_obj) |