Commit bce360b7 authored by Diogo Sampaio's avatar Diogo Sampaio
Browse files

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
parent ec62bf2f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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<
+3 −1
Original line number Diff line number Diff line
@@ -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");
    }
  };

+6 −4
Original line number Diff line number Diff line
@@ -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;
+11 −1
Original line number Diff line number Diff line
@@ -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()))
+10 −0
Original line number Diff line number Diff line
@@ -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);
Loading