Skip to content

Commit bb9df2e

Browse files
authored
[lldb] Ensure FILE* access mode is correctly specified when creating a NativeFile. (#167764)
If we open a `NativeFile` with a `FILE*`, the OpenOptions default to `eOpenOptionReadOnly`. This is an issue in python scripts if you try to write to one of the files like `print("Hi", file=lldb.debugger.GetOutputFileHandle())`. To address this, we need to specify the access mode whenever we create a `NativeFile` from a `FILE*`. I also added an assert on the `NativeFile` that validates the file is opened with the correct access mode and updated `NativeFile::Read` and `NativeFile::Write` to check the access mode. Before these changes: ``` $ lldb -b -O 'script lldb.debugger.GetOutputFileHandle().write("abc")' (lldb) script lldb.debugger.GetOutputFileHandle().write("abc") Traceback (most recent call last): File "<input>", line 1, in <module> io.UnsupportedOperation: not writable ``` After: ``` $ lldb -b -O 'script lldb.debugger.GetOutputFileHandle().write("abc")' (lldb) script lldb.debugger.GetOutputFileHandle().write("abc") abc3 ``` Fixes #122387
1 parent 6360bbb commit bb9df2e

File tree

13 files changed

+113
-26
lines changed

13 files changed

+113
-26
lines changed

lldb/include/lldb/API/SBFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ class LLDB_API SBFile {
2727
SBFile(FileSP file_sp);
2828
#ifndef SWIG
2929
SBFile(const SBFile &rhs);
30+
LLDB_DEPRECATED_FIXME("Use the constructor that specifies mode instead",
31+
"SBFile(FILE*, const char*, bool)")
3032
SBFile(FILE *file, bool transfer_ownership);
33+
SBFile(FILE *file, const char *mode, bool transfer_ownership);
3134
#endif
3235
SBFile(int fd, const char *mode, bool transfer_ownership);
3336
~SBFile();

lldb/include/lldb/Host/File.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class File : public IOObject {
6666
LLVM_MARK_AS_BITMASK_ENUM(/* largest_value= */ eOpenOptionInvalid)
6767
};
6868

69+
static constexpr OpenOptions OpenOptionsModeMask =
70+
eOpenOptionReadOnly | eOpenOptionWriteOnly | eOpenOptionReadWrite;
71+
6972
static mode_t ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options);
7073
static llvm::Expected<OpenOptions> GetOptionsFromMode(llvm::StringRef mode);
7174
static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; };
@@ -384,7 +387,7 @@ class NativeFile : public File {
384387

385388
NativeFile();
386389

387-
NativeFile(FILE *fh, bool transfer_ownership);
390+
NativeFile(FILE *fh, OpenOptions options, bool transfer_ownership);
388391

389392
NativeFile(int fd, OpenOptions options, bool transfer_ownership);
390393

lldb/include/lldb/Host/StreamFile.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ class LockableStreamFile {
8181
LockableStreamFile(StreamFile &stream_file, Mutex &mutex)
8282
: m_file_sp(stream_file.GetFileSP()), m_mutex(mutex) {}
8383
LockableStreamFile(FILE *fh, bool transfer_ownership, Mutex &mutex)
84-
: m_file_sp(std::make_shared<NativeFile>(fh, transfer_ownership)),
84+
: m_file_sp(std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,
85+
transfer_ownership)),
8586
m_mutex(mutex) {}
8687
LockableStreamFile(std::shared_ptr<File> file_sp, Mutex &mutex)
8788
: m_file_sp(file_sp), m_mutex(mutex) {}

lldb/source/API/SBCommandReturnObject.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "lldb/API/SBValue.h"
1616
#include "lldb/API/SBValueList.h"
1717
#include "lldb/Core/StructuredDataImpl.h"
18+
#include "lldb/Host/File.h"
1819
#include "lldb/Interpreter/CommandReturnObject.h"
1920
#include "lldb/Utility/ConstString.h"
2021
#include "lldb/Utility/Instrumentation.h"
@@ -275,14 +276,16 @@ void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) {
275276
void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh,
276277
bool transfer_ownership) {
277278
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
278-
FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership);
279+
FileSP file = std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,
280+
transfer_ownership);
279281
ref().SetImmediateOutputFile(file);
280282
}
281283

282284
void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh,
283285
bool transfer_ownership) {
284286
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
285-
FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership);
287+
FileSP file = std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,
288+
transfer_ownership);
286289
ref().SetImmediateErrorFile(file);
287290
}
288291

lldb/source/API/SBDebugger.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,8 @@ void SBDebugger::SkipAppInitFiles(bool b) {
327327
void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) {
328328
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
329329
if (m_opaque_sp)
330-
m_opaque_sp->SetInputFile(
331-
(FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
330+
m_opaque_sp->SetInputFile((FileSP)std::make_shared<NativeFile>(
331+
fh, File::eOpenOptionReadOnly, transfer_ownership));
332332
}
333333

334334
SBError SBDebugger::SetInputString(const char *data) {
@@ -385,7 +385,8 @@ SBError SBDebugger::SetOutputFile(FileSP file_sp) {
385385

386386
void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) {
387387
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
388-
SetOutputFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
388+
SetOutputFile((FileSP)std::make_shared<NativeFile>(
389+
fh, File::eOpenOptionWriteOnly, transfer_ownership));
389390
}
390391

391392
SBError SBDebugger::SetOutputFile(SBFile file) {
@@ -405,7 +406,8 @@ SBError SBDebugger::SetOutputFile(SBFile file) {
405406

406407
void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) {
407408
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
408-
SetErrorFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
409+
SetErrorFile((FileSP)std::make_shared<NativeFile>(
410+
fh, File::eOpenOptionWriteOnly, transfer_ownership));
409411
}
410412

411413
SBError SBDebugger::SetErrorFile(FileSP file_sp) {
@@ -576,8 +578,10 @@ void SBDebugger::HandleProcessEvent(const SBProcess &process,
576578
FILE *err) {
577579
LLDB_INSTRUMENT_VA(this, process, event, out, err);
578580

579-
FileSP outfile = std::make_shared<NativeFile>(out, false);
580-
FileSP errfile = std::make_shared<NativeFile>(err, false);
581+
FileSP outfile =
582+
std::make_shared<NativeFile>(out, File::eOpenOptionWriteOnly, false);
583+
FileSP errfile =
584+
std::make_shared<NativeFile>(err, File::eOpenOptionWriteOnly, false);
581585
return HandleProcessEvent(process, event, outfile, errfile);
582586
}
583587

lldb/source/API/SBFile.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,22 @@ SBFile::SBFile() { LLDB_INSTRUMENT_VA(this); }
3939
SBFile::SBFile(FILE *file, bool transfer_ownership) {
4040
LLDB_INSTRUMENT_VA(this, file, transfer_ownership);
4141

42-
m_opaque_sp = std::make_shared<NativeFile>(file, transfer_ownership);
42+
// For backwards comptability, this defaulted to ReadOnly previously.
43+
m_opaque_sp = std::make_shared<NativeFile>(file, File::eOpenOptionReadOnly,
44+
transfer_ownership);
45+
}
46+
47+
SBFile::SBFile(FILE *file, const char *mode, bool transfer_ownership) {
48+
LLDB_INSTRUMENT_VA(this, file, transfer_ownership);
49+
50+
auto options = File::GetOptionsFromMode(mode);
51+
if (!options) {
52+
llvm::consumeError(options.takeError());
53+
return;
54+
}
55+
56+
m_opaque_sp =
57+
std::make_shared<NativeFile>(file, options.get(), transfer_ownership);
4358
}
4459

4560
SBFile::SBFile(int fd, const char *mode, bool transfer_owndership) {

lldb/source/API/SBInstruction.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
#include "lldb/Utility/Instrumentation.h"
1111

1212
#include "lldb/API/SBAddress.h"
13-
#include "lldb/API/SBFrame.h"
1413
#include "lldb/API/SBFile.h"
14+
#include "lldb/API/SBFrame.h"
1515

1616
#include "lldb/API/SBStream.h"
1717
#include "lldb/API/SBTarget.h"
@@ -268,7 +268,8 @@ bool SBInstruction::GetDescription(lldb::SBStream &s) {
268268

269269
void SBInstruction::Print(FILE *outp) {
270270
LLDB_INSTRUMENT_VA(this, outp);
271-
FileSP out = std::make_shared<NativeFile>(outp, /*take_ownership=*/false);
271+
FileSP out = std::make_shared<NativeFile>(outp, File::eOpenOptionWriteOnly,
272+
/*take_ownership=*/false);
272273
Print(out);
273274
}
274275

lldb/source/API/SBProcess.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/API/SBProcess.h"
10+
#include "lldb/Host/File.h"
1011
#include "lldb/Utility/Instrumentation.h"
1112

1213
#include <cinttypes>
@@ -310,7 +311,8 @@ void SBProcess::ReportEventState(const SBEvent &event, SBFile out) const {
310311

311312
void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const {
312313
LLDB_INSTRUMENT_VA(this, event, out);
313-
FileSP outfile = std::make_shared<NativeFile>(out, false);
314+
FileSP outfile =
315+
std::make_shared<NativeFile>(out, File::eOpenOptionWriteOnly, false);
314316
return ReportEventState(event, outfile);
315317
}
316318

lldb/source/API/SBStream.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ void SBStream::RedirectToFile(const char *path, bool append) {
116116

117117
void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
118118
LLDB_INSTRUMENT_VA(this, fh, transfer_fh_ownership);
119-
FileSP file = std::make_unique<NativeFile>(fh, transfer_fh_ownership);
119+
FileSP file = std::make_unique<NativeFile>(fh, File::eOpenOptionReadWrite,
120+
transfer_fh_ownership);
120121
return RedirectToFile(file);
121122
}
122123

lldb/source/Core/Debugger.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,8 @@ llvm::StringRef Debugger::GetStaticBroadcasterClass() {
965965
Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
966966
: UserID(g_unique_id++),
967967
Properties(std::make_shared<OptionValueProperties>()),
968-
m_input_file_sp(std::make_shared<NativeFile>(stdin, NativeFile::Unowned)),
968+
m_input_file_sp(std::make_shared<NativeFile>(
969+
stdin, File::eOpenOptionReadOnly, NativeFile::Unowned)),
969970
m_output_stream_sp(std::make_shared<LockableStreamFile>(
970971
stdout, NativeFile::Unowned, m_output_mutex)),
971972
m_error_stream_sp(std::make_shared<LockableStreamFile>(
@@ -1172,7 +1173,8 @@ Status Debugger::SetInputString(const char *data) {
11721173
return result;
11731174
}
11741175

1175-
SetInputFile((FileSP)std::make_shared<NativeFile>(commands_file, true));
1176+
SetInputFile((FileSP)std::make_shared<NativeFile>(
1177+
commands_file, File::eOpenOptionReadOnly, true));
11761178
return result;
11771179
}
11781180

@@ -1378,7 +1380,8 @@ void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in,
13781380
in = GetInputFileSP();
13791381
// If there is nothing, use stdin
13801382
if (!in)
1381-
in = std::make_shared<NativeFile>(stdin, NativeFile::Unowned);
1383+
in = std::make_shared<NativeFile>(stdin, File::eOpenOptionReadOnly,
1384+
NativeFile::Unowned);
13821385
}
13831386
// If no STDOUT has been set, then set it appropriately
13841387
if (!out || !out->GetUnlockedFile().IsValid()) {

0 commit comments

Comments
 (0)