diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-21 20:46:22 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-21 20:46:22 +0000 |
commit | 979ae80af7ec49624b932954d22cb91900f17121 (patch) | |
tree | 012d338975038e58b16a6ec3f8810cd53a4f2e93 /clang/lib/Basic/SourceManager.cpp | |
parent | 5050a8da189d126b49dc5a07e01bdbe1c2271b06 (diff) | |
download | bcm5719-llvm-979ae80af7ec49624b932954d22cb91900f17121.tar.gz bcm5719-llvm-979ae80af7ec49624b932954d22cb91900f17121.zip |
PR42301: Abort cleanly if we encounter a huge source file rather than
crashing.
Ideally we wouldn't care about the size of a file so long as it fits in
memory, but in practice we have lots of hardocded assumptions that
unsigned can be used to index files, string literals, and so on.
llvm-svn: 364103
Diffstat (limited to 'clang/lib/Basic/SourceManager.cpp')
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index e62cef7ec55..8d56b19b106 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -108,6 +108,31 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, return Buffer.getPointer(); } + // Check that the file's size fits in an 'unsigned' (with room for a + // past-the-end value). This is deeply regrettable, but various parts of + // Clang (including elsewhere in this file!) use 'unsigned' to represent file + // offsets, line numbers, string literal lengths, and so on, and fail + // miserably on large source files. + if (ContentsEntry->getSize() >= std::numeric_limits<unsigned>::max()) { + // We can't make a memory buffer of the required size, so just make a small + // one. We should never hit a situation where we've already parsed to a + // later offset of the file, so it shouldn't matter that the buffer is + // smaller than the file. + Buffer.setPointer( + llvm::MemoryBuffer::getMemBuffer("", ContentsEntry->getName()) + .release()); + if (Diag.isDiagnosticInFlight()) + Diag.SetDelayedDiagnostic(diag::err_file_too_large, + ContentsEntry->getName()); + else + Diag.Report(Loc, diag::err_file_too_large) + << ContentsEntry->getName(); + + Buffer.setInt(Buffer.getInt() | InvalidFlag); + if (Invalid) *Invalid = true; + return Buffer.getPointer(); + } + bool isVolatile = SM.userFilesAreVolatile() && !IsSystemFile; auto BufferOrError = SM.getFileManager().getBufferForFile(ContentsEntry, isVolatile); |