diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-01-28 15:02:40 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-01-28 15:02:40 +0000 |
commit | b2702d6a45016b24bed936901c183a5b1851858a (patch) | |
tree | ac94a272963be35296887161473b2821f3d0534a /llvm/tools/llvm-objcopy/Buffer.cpp | |
parent | 6c5dfcb89edf93eb50356dc39ea0ea2dcbba906f (diff) | |
download | bcm5719-llvm-b2702d6a45016b24bed936901c183a5b1851858a.tar.gz bcm5719-llvm-b2702d6a45016b24bed936901c183a5b1851858a.zip |
[llvm-objcopy] Fix crash when writing empty binary output
Summary: When using llvm-objcopy -O binary and the resulting file will be empty (e.g. removing the only section that would be written, or using --only-keep with a section that doesn't exist/isn't SHF_ALLOC), we crash because FileOutputBuffer expects Size > 0. Add a regression test, and change Buffer to open/truncate the output file in this case.
Reviewers: alexshap, jhenderson, jakehehrlich, espindola
Reviewed By: alexshap, jhenderson
Subscribers: jfb, llvm-commits, emaste, arichardson
Differential Revision: https://reviews.llvm.org/D56806
llvm-svn: 352371
Diffstat (limited to 'llvm/tools/llvm-objcopy/Buffer.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/Buffer.cpp | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/llvm/tools/llvm-objcopy/Buffer.cpp b/llvm/tools/llvm-objcopy/Buffer.cpp index 1789097f276..7af9d912eda 100644 --- a/llvm/tools/llvm-objcopy/Buffer.cpp +++ b/llvm/tools/llvm-objcopy/Buffer.cpp @@ -9,7 +9,9 @@ #include "Buffer.h" #include "llvm-objcopy.h" #include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" #include <memory> namespace llvm { @@ -17,7 +19,23 @@ namespace objcopy { Buffer::~Buffer() {} +static Error createEmptyFile(StringRef FileName) { + // Create an empty tempfile and atomically swap it in place with the desired + // output file. + Expected<sys::fs::TempFile> Temp = + sys::fs::TempFile::create(FileName + ".temp-empty-%%%%%%%"); + return Temp ? Temp->keep(FileName) : Temp.takeError(); +} + Error FileBuffer::allocate(size_t Size) { + // When a 0-sized file is requested, skip allocation but defer file + // creation/truncation until commit() to avoid side effects if something + // happens between allocate() and commit(). + if (Size == 0) { + EmptyFile = true; + return Error::success(); + } + Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable); // FileOutputBuffer::create() returns an Error that is just a wrapper around @@ -29,6 +47,10 @@ Error FileBuffer::allocate(size_t Size) { } Error FileBuffer::commit() { + if (EmptyFile) + return createEmptyFile(getName()); + + assert(Buf && "allocate() not called before commit()!"); Error Err = Buf->commit(); // FileOutputBuffer::commit() returns an Error that is just a wrapper around // std::error_code. Wrap it in FileError to include the actual filename. |