Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lldb/include/lldb/API/SBFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ class LLDB_API SBFile {
SBFile(FileSP file_sp);
#ifndef SWIG
SBFile(const SBFile &rhs);
LLDB_DEPRECATED_FIXME("Use the constructor that specifies mode instead",
"SBFile(FILE*, const char*, bool)")
SBFile(FILE *file, bool transfer_ownership);
SBFile(FILE *file, const char *mode, bool transfer_ownership);
#endif
SBFile(int fd, const char *mode, bool transfer_ownership);
~SBFile();
Expand Down
5 changes: 4 additions & 1 deletion lldb/include/lldb/Host/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class File : public IOObject {
LLVM_MARK_AS_BITMASK_ENUM(/* largest_value= */ eOpenOptionInvalid)
};

static constexpr OpenOptions OpenOptionsModeMask =
eOpenOptionReadOnly | eOpenOptionWriteOnly | eOpenOptionReadWrite;

static mode_t ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options);
static llvm::Expected<OpenOptions> GetOptionsFromMode(llvm::StringRef mode);
static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; };
Expand Down Expand Up @@ -384,7 +387,7 @@ class NativeFile : public File {

NativeFile();

NativeFile(FILE *fh, bool transfer_ownership);
NativeFile(FILE *fh, OpenOptions options, bool transfer_ownership);

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

Expand Down
3 changes: 2 additions & 1 deletion lldb/include/lldb/Host/StreamFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ class LockableStreamFile {
LockableStreamFile(StreamFile &stream_file, Mutex &mutex)
: m_file_sp(stream_file.GetFileSP()), m_mutex(mutex) {}
LockableStreamFile(FILE *fh, bool transfer_ownership, Mutex &mutex)
: m_file_sp(std::make_shared<NativeFile>(fh, transfer_ownership)),
: m_file_sp(std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,
transfer_ownership)),
m_mutex(mutex) {}
LockableStreamFile(std::shared_ptr<File> file_sp, Mutex &mutex)
: m_file_sp(file_sp), m_mutex(mutex) {}
Expand Down
7 changes: 5 additions & 2 deletions lldb/source/API/SBCommandReturnObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "lldb/API/SBValue.h"
#include "lldb/API/SBValueList.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Host/File.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Instrumentation.h"
Expand Down Expand Up @@ -275,14 +276,16 @@ void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) {
void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh,
bool transfer_ownership) {
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership);
FileSP file = std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,
transfer_ownership);
ref().SetImmediateOutputFile(file);
}

void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh,
bool transfer_ownership) {
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership);
FileSP file = std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,
transfer_ownership);
ref().SetImmediateErrorFile(file);
}

Expand Down
16 changes: 10 additions & 6 deletions lldb/source/API/SBDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,8 @@ void SBDebugger::SkipAppInitFiles(bool b) {
void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) {
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
if (m_opaque_sp)
m_opaque_sp->SetInputFile(
(FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
m_opaque_sp->SetInputFile((FileSP)std::make_shared<NativeFile>(
fh, File::eOpenOptionReadOnly, transfer_ownership));
}

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

void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) {
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
SetOutputFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
SetOutputFile((FileSP)std::make_shared<NativeFile>(
fh, File::eOpenOptionWriteOnly, transfer_ownership));
}

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

void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) {
LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
SetErrorFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
SetErrorFile((FileSP)std::make_shared<NativeFile>(
fh, File::eOpenOptionWriteOnly, transfer_ownership));
}

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

FileSP outfile = std::make_shared<NativeFile>(out, false);
FileSP errfile = std::make_shared<NativeFile>(err, false);
FileSP outfile =
std::make_shared<NativeFile>(out, File::eOpenOptionWriteOnly, false);
FileSP errfile =
std::make_shared<NativeFile>(err, File::eOpenOptionWriteOnly, false);
return HandleProcessEvent(process, event, outfile, errfile);
}

Expand Down
17 changes: 16 additions & 1 deletion lldb/source/API/SBFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,22 @@ SBFile::SBFile() { LLDB_INSTRUMENT_VA(this); }
SBFile::SBFile(FILE *file, bool transfer_ownership) {
LLDB_INSTRUMENT_VA(this, file, transfer_ownership);

m_opaque_sp = std::make_shared<NativeFile>(file, transfer_ownership);
// For backwards comptability, this defaulted to ReadOnly previously.
m_opaque_sp = std::make_shared<NativeFile>(file, File::eOpenOptionReadOnly,
transfer_ownership);
}

SBFile::SBFile(FILE *file, const char *mode, bool transfer_ownership) {
LLDB_INSTRUMENT_VA(this, file, transfer_ownership);

auto options = File::GetOptionsFromMode(mode);
if (!options) {
llvm::consumeError(options.takeError());
return;
}

m_opaque_sp =
std::make_shared<NativeFile>(file, options.get(), transfer_ownership);
}

SBFile::SBFile(int fd, const char *mode, bool transfer_owndership) {
Expand Down
5 changes: 3 additions & 2 deletions lldb/source/API/SBInstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include "lldb/Utility/Instrumentation.h"

#include "lldb/API/SBAddress.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBFile.h"
#include "lldb/API/SBFrame.h"

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

void SBInstruction::Print(FILE *outp) {
LLDB_INSTRUMENT_VA(this, outp);
FileSP out = std::make_shared<NativeFile>(outp, /*take_ownership=*/false);
FileSP out = std::make_shared<NativeFile>(outp, File::eOpenOptionWriteOnly,
/*take_ownership=*/false);
Print(out);
}

Expand Down
4 changes: 3 additions & 1 deletion lldb/source/API/SBProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "lldb/API/SBProcess.h"
#include "lldb/Host/File.h"
#include "lldb/Utility/Instrumentation.h"

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

void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const {
LLDB_INSTRUMENT_VA(this, event, out);
FileSP outfile = std::make_shared<NativeFile>(out, false);
FileSP outfile =
std::make_shared<NativeFile>(out, File::eOpenOptionWriteOnly, false);
return ReportEventState(event, outfile);
}

Expand Down
3 changes: 2 additions & 1 deletion lldb/source/API/SBStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ void SBStream::RedirectToFile(const char *path, bool append) {

void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
LLDB_INSTRUMENT_VA(this, fh, transfer_fh_ownership);
FileSP file = std::make_unique<NativeFile>(fh, transfer_fh_ownership);
FileSP file = std::make_unique<NativeFile>(fh, File::eOpenOptionReadWrite,
transfer_fh_ownership);
return RedirectToFile(file);
}

Expand Down
9 changes: 6 additions & 3 deletions lldb/source/Core/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,8 @@ llvm::StringRef Debugger::GetStaticBroadcasterClass() {
Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
: UserID(g_unique_id++),
Properties(std::make_shared<OptionValueProperties>()),
m_input_file_sp(std::make_shared<NativeFile>(stdin, NativeFile::Unowned)),
m_input_file_sp(std::make_shared<NativeFile>(
stdin, File::eOpenOptionReadOnly, NativeFile::Unowned)),
m_output_stream_sp(std::make_shared<LockableStreamFile>(
stdout, NativeFile::Unowned, m_output_mutex)),
m_error_stream_sp(std::make_shared<LockableStreamFile>(
Expand Down Expand Up @@ -1172,7 +1173,8 @@ Status Debugger::SetInputString(const char *data) {
return result;
}

SetInputFile((FileSP)std::make_shared<NativeFile>(commands_file, true));
SetInputFile((FileSP)std::make_shared<NativeFile>(
commands_file, File::eOpenOptionReadOnly, true));
return result;
}

Expand Down Expand Up @@ -1378,7 +1380,8 @@ void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in,
in = GetInputFileSP();
// If there is nothing, use stdin
if (!in)
in = std::make_shared<NativeFile>(stdin, NativeFile::Unowned);
in = std::make_shared<NativeFile>(stdin, File::eOpenOptionReadOnly,
NativeFile::Unowned);
}
// If no STDOUT has been set, then set it appropriately
if (!out || !out->GetUnlockedFile().IsValid()) {
Expand Down
42 changes: 36 additions & 6 deletions lldb/source/Host/common/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,35 @@ uint32_t File::GetPermissions(Status &error) const {

NativeFile::NativeFile() = default;

NativeFile::NativeFile(FILE *fh, bool transfer_ownership)
: m_stream(fh), m_own_stream(transfer_ownership) {
NativeFile::NativeFile(FILE *fh, OpenOptions options, bool transfer_ownership)
: m_stream(fh), m_options(options), m_own_stream(transfer_ownership) {
#ifdef _WIN32
// In order to properly display non ASCII characters in Windows, we need to
// use Windows APIs to print to the console. This is only required if the
// stream outputs to a console.
int fd = _fileno(fh);
is_windows_console =
::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR;
#else
#ifndef NDEBUG
int fd = fileno(fh);
if (fd != -1) {
int required_mode = ConvertOpenOptionsForPOSIXOpen(options) & O_ACCMODE;
int mode = fcntl(fd, F_GETFL);
if (mode != -1) {
mode &= O_ACCMODE;
// Check that the file is open with a valid subset of the requested file
// access mode, e.g. if we expected the file to be writable then ensure it
// was opened with O_WRONLY or O_RDWR.
assert(
(required_mode == O_RDWR && mode == O_RDWR) ||
(required_mode == O_RDONLY && (mode == O_RDWR || mode == O_RDONLY) ||
(required_mode == O_WRONLY &&
(mode == O_RDWR || mode == O_WRONLY))) &&
"invalid file access mode");
}
}
#endif
#endif
}

Expand All @@ -274,7 +294,8 @@ NativeFile::NativeFile(int fd, OpenOptions options, bool transfer_ownership)
}

bool NativeFile::IsValid() const {
std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex);
std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex,
m_stream_mutex);
return DescriptorIsValidUnlocked() || StreamIsValidUnlocked();
}

Expand Down Expand Up @@ -343,7 +364,8 @@ FILE *NativeFile::GetStream() {
}

Status NativeFile::Close() {
std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex);
std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex,
m_stream_mutex);

Status error;

Expand Down Expand Up @@ -548,6 +570,10 @@ Status NativeFile::Sync() {
Status NativeFile::Read(void *buf, size_t &num_bytes) {
Status error;

// Ensure the file is open for reading.
if ((m_options & File::OpenOptionsModeMask) == eOpenOptionWriteOnly)
return Status(std::make_error_code(std::errc::bad_file_descriptor));

#if defined(MAX_READ_SIZE)
if (num_bytes > MAX_READ_SIZE) {
uint8_t *p = (uint8_t *)buf;
Expand Down Expand Up @@ -612,6 +638,10 @@ Status NativeFile::Read(void *buf, size_t &num_bytes) {
Status NativeFile::Write(const void *buf, size_t &num_bytes) {
Status error;

// Ensure the file is open for writing.
if ((m_options & File::OpenOptionsModeMask) == File::eOpenOptionReadOnly)
return Status(std::make_error_code(std::errc::bad_file_descriptor));

#if defined(MAX_WRITE_SIZE)
if (num_bytes > MAX_WRITE_SIZE) {
const uint8_t *p = (const uint8_t *)buf;
Expand Down Expand Up @@ -776,8 +806,8 @@ Status NativeFile::Write(const void *buf, size_t &num_bytes, off_t &offset) {
int fd = GetDescriptor();
if (fd != kInvalidDescriptor) {
#ifndef _WIN32
ssize_t bytes_written =
llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset);
ssize_t bytes_written = llvm::sys::RetryAfterSignal(
-1, ::pwrite, m_descriptor, buf, num_bytes, offset);
if (bytes_written < 0) {
num_bytes = 0;
error = Status::FromErrno();
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Host/common/StreamFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ StreamFile::StreamFile(int fd, bool transfer_ownership) : Stream() {
}

StreamFile::StreamFile(FILE *fh, bool transfer_ownership) : Stream() {
m_file_sp = std::make_shared<NativeFile>(fh, transfer_ownership);
m_file_sp = std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,
transfer_ownership);
}

StreamFile::StreamFile(const char *path, File::OpenOptions options,
Expand Down
22 changes: 21 additions & 1 deletion lldb/unittests/Host/FileTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "lldb/Host/File.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
Expand Down Expand Up @@ -35,7 +36,7 @@ TEST(File, GetWaitableHandleFileno) {
FILE *stream = fdopen(fd, "r");
ASSERT_TRUE(stream);

NativeFile file(stream, true);
NativeFile file(stream, File::eOpenOptionReadWrite, true);
#ifdef _WIN32
EXPECT_EQ(file.GetWaitableHandle(), (HANDLE)_get_osfhandle(fd));
#else
Expand Down Expand Up @@ -67,3 +68,22 @@ TEST(File, GetStreamFromDescriptor) {
EXPECT_EQ(file.GetWaitableHandle(), (file_t)fd);
#endif
}

TEST(File, ReadOnlyModeNotWritable) {
const auto *Info = testing::UnitTest::GetInstance()->current_test_info();
llvm::SmallString<128> name;
int fd;
llvm::sys::fs::createTemporaryFile(llvm::Twine(Info->test_case_name()) + "-" +
Info->name(),
"test", fd, name);

llvm::FileRemover remover(name);
ASSERT_GE(fd, 0);

NativeFile file(fd, File::eOpenOptionReadOnly, true);
ASSERT_TRUE(file.IsValid());
llvm::StringLiteral buf = "Hello World";
size_t bytes_written = buf.size();
Status error = file.Write(buf.data(), bytes_written);
EXPECT_EQ(error.Fail(), true);
}
Loading