diff options
Diffstat (limited to 'contrib/llvm/lib/Support/MemoryBuffer.cpp')
-rw-r--r-- | contrib/llvm/lib/Support/MemoryBuffer.cpp | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/contrib/llvm/lib/Support/MemoryBuffer.cpp b/contrib/llvm/lib/Support/MemoryBuffer.cpp index 0771af5..16e5c7a 100644 --- a/contrib/llvm/lib/Support/MemoryBuffer.cpp +++ b/contrib/llvm/lib/Support/MemoryBuffer.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Config/config.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Errno.h" #include "llvm/Support/Path.h" @@ -29,15 +30,12 @@ #include <sys/stat.h> #if !defined(_MSC_VER) && !defined(__MINGW32__) #include <unistd.h> -#include <sys/uio.h> #else #include <io.h> #endif #include <fcntl.h> using namespace llvm; -namespace { const llvm::error_code success; } - //===----------------------------------------------------------------------===// // MemoryBuffer implementation itself. //===----------------------------------------------------------------------===// @@ -306,7 +304,17 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, RealMapOffset)) { result.reset(GetNamedBuffer<MemoryBufferMMapFile>( StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator)); - return success; + + if (RequiresNullTerminator && result->getBufferEnd()[0] != '\0') { + // There could be a racing issue that resulted in the file being larger + // than the FileSize passed by the caller. We already have an assertion + // for this in MemoryBuffer::init() but have a runtime guarantee that + // the buffer will be null-terminated here, so do a copy that adds a + // null-terminator. + result.reset(MemoryBuffer::getMemBufferCopy(result->getBuffer(), + Filename)); + } + return error_code::success(); } } @@ -321,29 +329,35 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, char *BufPtr = const_cast<char*>(SB->getBufferStart()); size_t BytesLeft = MapSize; +#ifndef HAVE_PREAD if (lseek(FD, Offset, SEEK_SET) == -1) return error_code(errno, posix_category()); +#endif while (BytesLeft) { +#ifdef HAVE_PREAD + ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset); +#else ssize_t NumRead = ::read(FD, BufPtr, BytesLeft); +#endif if (NumRead == -1) { if (errno == EINTR) continue; // Error while reading. return error_code(errno, posix_category()); - } else if (NumRead == 0) { - // We hit EOF early, truncate and terminate buffer. - Buf->BufferEnd = BufPtr; - *BufPtr = 0; - result.swap(SB); - return success; + } + if (NumRead == 0) { + assert(0 && "We got inaccurate FileSize value or fstat reported an " + "invalid file size."); + *BufPtr = '\0'; // null-terminate at the actual size. + break; } BytesLeft -= NumRead; BufPtr += NumRead; } result.swap(SB); - return success; + return error_code::success(); } //===----------------------------------------------------------------------===// @@ -372,5 +386,5 @@ error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) { } while (ReadBytes != 0); result.reset(getMemBufferCopy(Buffer, "<stdin>")); - return success; + return error_code::success(); } |