summaryrefslogtreecommitdiffstats
path: root/clang/lib/Basic/SourceManager.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-06-21 20:46:22 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-06-21 20:46:22 +0000
commit979ae80af7ec49624b932954d22cb91900f17121 (patch)
tree012d338975038e58b16a6ec3f8810cd53a4f2e93 /clang/lib/Basic/SourceManager.cpp
parent5050a8da189d126b49dc5a07e01bdbe1c2271b06 (diff)
downloadbcm5719-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.cpp25
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);
OpenPOWER on IntegriCloud