//===-- SpecialCaseList.cpp - special case list for sanitizers ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This is a utility class for instrumentation passes (like AddressSanitizer
// or ThreadSanitizer) to avoid instrumenting some functions or global
// variables, or to instrument some functions or global variables in a specific
// way, based on a user-supplied list.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/SpecialCaseList.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <string>
#include <system_error>
#include <utility>

#include <stdio.h>
namespace llvm {

bool SpecialCaseList::Matcher::insert(std::string Regexp,
                                      unsigned LineNumber,
                                      std::string &REError) {
  if (Regexp.empty()) {
    REError = "Supplied regexp was blank";
    return false;
  }

  if (Regex::isLiteralERE(Regexp)) {
    Strings[Regexp] = LineNumber;
    return true;
  }
  Trigrams.insert(Regexp);

  // Replace * with .*
  for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos;
       pos += strlen(".*")) {
    Regexp.replace(pos, strlen("*"), ".*");
  }

  Regexp = (Twine("^(") + StringRef(Regexp) + ")$").str();

  // Check that the regexp is valid.
  Regex CheckRE(Regexp);
  if (!CheckRE.isValid(REError))
    return false;

  RegExes.emplace_back(
      std::make_pair(std::make_unique<Regex>(std::move(CheckRE)), LineNumber));
  return true;
}

unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
  auto It = Strings.find(Query);
  if (It != Strings.end())
    return It->second;
  if (Trigrams.isDefinitelyOut(Query))
    return false;
  for (const auto &RegExKV : RegExes)
    if (RegExKV.first->match(Query))
      return RegExKV.second;
  return 0;
}

std::unique_ptr<SpecialCaseList>
SpecialCaseList::create(const std::vector<std::string> &Paths,
                        llvm::vfs::FileSystem &FS, std::string &Error) {
  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
  if (SCL->createInternal(Paths, FS, Error))
    return SCL;
  return nullptr;
}

std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
                                                         std::string &Error) {
  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
  if (SCL->createInternal(MB, Error))
    return SCL;
  return nullptr;
}

std::unique_ptr<SpecialCaseList>
SpecialCaseList::createOrDie(const std::vector<std::string> &Paths,
                             llvm::vfs::FileSystem &FS) {
  std::string Error;
  if (auto SCL = create(Paths, FS, Error))
    return SCL;
  report_fatal_error(Twine(Error));
}

bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
                                     vfs::FileSystem &VFS, std::string &Error) {
  StringMap<size_t> Sections;
  for (const auto &Path : Paths) {
    ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
        VFS.getBufferForFile(Path);
    if (std::error_code EC = FileOrErr.getError()) {
      Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
      return false;
    }
    std::string ParseError;
    if (!parse(FileOrErr.get().get(), Sections, ParseError)) {
      Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
      return false;
    }
  }
  return true;
}

bool SpecialCaseList::createInternal(const MemoryBuffer *MB,
                                     std::string &Error) {
  StringMap<size_t> Sections;
  if (!parse(MB, Sections, Error))
    return false;
  return true;
}

bool SpecialCaseList::parse(const MemoryBuffer *MB,
                            StringMap<size_t> &SectionsMap,
                            std::string &Error) {
  // Iterate through each line in the exclusion list file.
  SmallVector<StringRef, 16> Lines;
  MB->getBuffer().split(Lines, '\n');

  unsigned LineNo = 1;
  StringRef Section = "*";

  for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
    *I = I->trim();
    // Ignore empty lines and lines starting with "#"
    if (I->empty() || I->startswith("#"))
      continue;

    // Save section names
    if (I->startswith("[")) {
      if (!I->endswith("]")) {
        Error = (Twine("malformed section header on line ") + Twine(LineNo) +
                 ": " + *I).str();
        return false;
      }

      Section = I->slice(1, I->size() - 1);

      std::string REError;
      Regex CheckRE(Section);
      if (!CheckRE.isValid(REError)) {
        Error =
            (Twine("malformed regex for section ") + Section + ": '" + REError)
                .str();
        return false;
      }

      continue;
    }

    // Get our prefix and unparsed regexp.
    std::pair<StringRef, StringRef> SplitLine = I->split(":");
    StringRef Prefix = SplitLine.first;
    if (SplitLine.second.empty()) {
      // Missing ':' in the line.
      Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
               SplitLine.first + "'").str();
      return false;
    }

    std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
    std::string Regexp = std::string(SplitRegexp.first);
    StringRef Category = SplitRegexp.second;

    // Create this section if it has not been seen before.
    if (SectionsMap.find(Section) == SectionsMap.end()) {
      std::unique_ptr<Matcher> M = std::make_unique<Matcher>();
      std::string REError;
      if (!M->insert(std::string(Section), LineNo, REError)) {
        Error = (Twine("malformed section ") + Section + ": '" + REError).str();
        return false;
      }

      SectionsMap[Section] = Sections.size();
      Sections.emplace_back(std::move(M));
    }

    auto &Entry = Sections[SectionsMap[Section]].Entries[Prefix][Category];
    std::string REError;
    if (!Entry.insert(std::move(Regexp), LineNo, REError)) {
      Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
               SplitLine.second + "': " + REError).str();
      return false;
    }
  }
  return true;
}

SpecialCaseList::~SpecialCaseList() {}

bool SpecialCaseList::inSection(StringRef Section, StringRef Prefix,
                                StringRef Query, StringRef Category) const {
  return inSectionBlame(Section, Prefix, Query, Category);
}

unsigned SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
                                         StringRef Query,
                                         StringRef Category) const {
  for (const auto &SectionIter : Sections)
    if (SectionIter.SectionMatcher->match(Section)) {
      unsigned Blame =
          inSectionBlame(SectionIter.Entries, Prefix, Query, Category);
      if (Blame)
        return Blame;
    }
  return 0;
}

unsigned SpecialCaseList::inSectionBlame(const SectionEntries &Entries,
                                         StringRef Prefix, StringRef Query,
                                         StringRef Category) const {
  SectionEntries::const_iterator I = Entries.find(Prefix);
  if (I == Entries.end()) return 0;
  StringMap<Matcher>::const_iterator II = I->second.find(Category);
  if (II == I->second.end()) return 0;

  return II->getValue().match(Query);
}

}  // namespace llvm
