mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-08 09:03:18 +00:00
Detect source location overflow due includes
Summary: As discussed in http://lists.llvm.org/pipermail/cfe-dev/2019-October/063459.html the overflow of the souce locations (limited to 2^31 chars) can generate all sorts of weird things (bogus warnings, hangs, crashes, miscompilation and correct compilation). In debug mode this assert would fail. So it might be a good start, as in PR42301, to detect the failure and exit with a proper error message. Reviewers: rsmith, thakis, miyuki Reviewed By: miyuki Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D70183
This commit is contained in:
parent
ec62bf2fd3
commit
bce360b704
@ -282,6 +282,9 @@ def err_file_modified : Error<
|
||||
"file '%0' modified since it was first processed">, DefaultFatal;
|
||||
def err_file_too_large : Error<
|
||||
"sorry, unsupported: file '%0' is too large for Clang to process">;
|
||||
def err_include_too_large : Error<
|
||||
"sorry, this include generates a translation unit too large for"
|
||||
" Clang to process.">, DefaultFatal;
|
||||
def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but "
|
||||
"encoding is not supported">, DefaultFatal;
|
||||
def err_unable_to_rename_temp : Error<
|
||||
|
@ -2203,12 +2203,14 @@ private:
|
||||
ModuleBegin,
|
||||
ModuleImport,
|
||||
SkippedModuleImport,
|
||||
Failure,
|
||||
} Kind;
|
||||
Module *ModuleForHeader = nullptr;
|
||||
|
||||
ImportAction(ActionKind AK, Module *Mod = nullptr)
|
||||
: Kind(AK), ModuleForHeader(Mod) {
|
||||
assert((AK == None || Mod) && "no module for module action");
|
||||
assert((AK == None || Mod || AK == Failure) &&
|
||||
"no module for module action");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -577,13 +577,15 @@ FileID SourceManager::createFileID(const ContentCache *File, StringRef Filename,
|
||||
SLocEntryLoaded[Index] = true;
|
||||
return FileID::get(LoadedID);
|
||||
}
|
||||
unsigned FileSize = File->getSize();
|
||||
if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
|
||||
NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
|
||||
Diag.Report(IncludePos, diag::err_include_too_large);
|
||||
return FileID();
|
||||
}
|
||||
LocalSLocEntryTable.push_back(
|
||||
SLocEntry::get(NextLocalOffset,
|
||||
FileInfo::get(IncludePos, File, FileCharacter, Filename)));
|
||||
unsigned FileSize = File->getSize();
|
||||
assert(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
|
||||
NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset &&
|
||||
"Ran out of source locations!");
|
||||
// We do a +1 here because we want a SourceLocation that means "the end of the
|
||||
// file", e.g. for the "no newline at the end of the file" diagnostic.
|
||||
NextLocalOffset += FileSize + 1;
|
||||
|
@ -1708,6 +1708,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
||||
EnterAnnotationToken(SourceRange(HashLoc, EndLoc),
|
||||
tok::annot_module_include, Action.ModuleForHeader);
|
||||
break;
|
||||
case ImportAction::Failure:
|
||||
assert(TheModuleLoader.HadFatalFailure &&
|
||||
"This should be an early exit only to a fatal error");
|
||||
TheModuleLoader.HadFatalFailure = true;
|
||||
IncludeTok.setKind(tok::eof);
|
||||
CurLexer->cutOffLexing();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2165,7 +2172,10 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
|
||||
if (IncludePos.isMacroID())
|
||||
IncludePos = SourceMgr.getExpansionRange(IncludePos).getEnd();
|
||||
FileID FID = SourceMgr.createFileID(*File, IncludePos, FileCharacter);
|
||||
assert(FID.isValid() && "Expected valid file ID");
|
||||
if (!FID.isValid()) {
|
||||
TheModuleLoader.HadFatalFailure = true;
|
||||
return ImportAction::Failure;
|
||||
}
|
||||
|
||||
// If all is good, enter the new file!
|
||||
if (EnterSourceFile(FID, CurDir, FilenameTok.getLocation()))
|
||||
|
@ -906,6 +906,9 @@ void Preprocessor::Lex(Token &Result) {
|
||||
}
|
||||
} while (!ReturnedToken);
|
||||
|
||||
if (Result.is(tok::unknown) && TheModuleLoader.HadFatalFailure)
|
||||
return;
|
||||
|
||||
if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
|
||||
// Remember the identifier before code completion token.
|
||||
setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
|
||||
@ -1200,6 +1203,13 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
|
||||
Suffix[0].setAnnotationValue(Action.ModuleForHeader);
|
||||
// FIXME: Call the moduleImport callback?
|
||||
break;
|
||||
case ImportAction::Failure:
|
||||
assert(TheModuleLoader.HadFatalFailure &&
|
||||
"This should be an early exit only to a fatal error");
|
||||
Result.setKind(tok::eof);
|
||||
CurLexer->cutOffLexing();
|
||||
EnterTokens(Suffix);
|
||||
return true;
|
||||
}
|
||||
|
||||
EnterTokens(Suffix);
|
||||
|
1470
clang/test/Lexer/Inputs/inc1.h
Normal file
1470
clang/test/Lexer/Inputs/inc1.h
Normal file
File diff suppressed because it is too large
Load Diff
1000
clang/test/Lexer/Inputs/inc2.h
Normal file
1000
clang/test/Lexer/Inputs/inc2.h
Normal file
File diff suppressed because it is too large
Load Diff
25
clang/test/Lexer/SourceLocationsOverflow.c
Normal file
25
clang/test/Lexer/SourceLocationsOverflow.c
Normal file
@ -0,0 +1,25 @@
|
||||
// RUN: not %clang %s -S -o - 2>&1 | FileCheck %s
|
||||
// CHECK: In file included from {{.*}}SourceLocationsOverflow.c
|
||||
// CHECK-NEXT: inc1.h{{.*}}: fatal error: sorry, this include generates a translation unit too large for Clang to process.
|
||||
// CHECK-NEXT: #include "inc2.h"
|
||||
// CHECK-NEXT: ^
|
||||
// CHECK-NEXT: 1 error generated.
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
||||
#include "Inputs/inc1.h"
|
Loading…
Reference in New Issue
Block a user