sammccall created this revision.
sammccall added a reviewer: hokein.
Herald added a subscriber: mgorny.
Herald added a project: All.
sammccall requested review of this revision.
Herald added subscribers: cfe-commits, alextsao1999.
Herald added a project: clang-tools-extra.

As confirmation, running this locally found 2 crashes:

- trivial: crashes on file with no tokens
- lexer: hits an assertion failure on bytes: 0x5c,0xa,0x5c,0x1,0x65,0x5c,0xa


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125037

Files:
  clang-tools-extra/pseudo/CMakeLists.txt
  clang-tools-extra/pseudo/fuzzer/CMakeLists.txt
  clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp
  clang-tools-extra/pseudo/fuzzer/Main.cpp
  clang-tools-extra/pseudo/test/CMakeLists.txt
  clang-tools-extra/pseudo/test/fuzzer.cpp

Index: clang-tools-extra/pseudo/test/fuzzer.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/pseudo/test/fuzzer.cpp
@@ -0,0 +1,4 @@
+// RUN: clang-pseudo-fuzzer -grammar=%cxx-bnf-file -print %s | FileCheck %s
+int x;
+// CHECK: translation-unit := declaration-seq
+// CHECK: simple-type-specifier := INT
Index: clang-tools-extra/pseudo/test/CMakeLists.txt
===================================================================
--- clang-tools-extra/pseudo/test/CMakeLists.txt
+++ clang-tools-extra/pseudo/test/CMakeLists.txt
@@ -1,5 +1,6 @@
 set(CLANG_PSEUDO_TEST_DEPS
   clang-pseudo
+  clang-pseudo-fuzzer
   ClangPseudoTests
   )
 
Index: clang-tools-extra/pseudo/fuzzer/Main.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/pseudo/fuzzer/Main.cpp
@@ -0,0 +1,16 @@
+//===--- Main.cpp - Entry point to sanity check the fuzzer ----------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/FuzzMutate/FuzzerCLI.h"
+
+extern "C" int LLVMFuzzerInitialize(int *, char ***);
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *, size_t);
+int main(int argc, char *argv[]) {
+  return llvm::runFuzzerOnInputs(argc, argv, LLVMFuzzerTestOneInput,
+                                 LLVMFuzzerInitialize);
+}
Index: clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp
@@ -0,0 +1,105 @@
+//===-- Fuzzer.cpp - Fuzz the pseudoparser --------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang-pseudo/DirectiveTree.h"
+#include "clang-pseudo/Forest.h"
+#include "clang-pseudo/GLR.h"
+#include "clang-pseudo/Grammar.h"
+#include "clang-pseudo/LRTable.h"
+#include "clang-pseudo/Token.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace pseudo {
+namespace {
+
+class Fuzzer {
+  clang::LangOptions LangOpts = clang::pseudo::genericLangOpts();
+  std::unique_ptr<Grammar> G;
+  LRTable T;
+  bool Print;
+
+public:
+  Fuzzer(llvm::StringRef GrammarPath, bool Print) : Print(Print) {
+    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> GrammarText =
+        llvm::MemoryBuffer::getFile(GrammarPath);
+    if (std::error_code EC = GrammarText.getError()) {
+      llvm::errs() << "Error: can't read grammar file '" << GrammarPath
+                   << "': " << EC.message() << "\n";
+      std::exit(1);
+    }
+    std::vector<std::string> Diags;
+    G = Grammar::parseBNF(GrammarText->get()->getBuffer(), Diags);
+    if (!Diags.empty()) {
+      for (const auto &Diag : Diags)
+        llvm::errs() << Diag << "\n";
+      std::exit(1);
+    }
+    T = LRTable::buildSLR(*G);
+  }
+
+  void operator()(llvm::StringRef Code) {
+    std::string CodeStr = Code.str(); // Must be null-terminated.
+    auto RawStream = lex(CodeStr, LangOpts);
+    auto DirectiveStructure = DirectiveTree::parse(RawStream);
+    clang::pseudo::chooseConditionalBranches(DirectiveStructure, RawStream);
+    // FIXME: strip preprocessor directives
+    auto ParseableStream =
+        clang::pseudo::stripComments(cook(RawStream, LangOpts));
+
+    clang::pseudo::ForestArena Arena;
+    clang::pseudo::GSS GSS;
+    auto &Root = glrParse(ParseableStream,
+                          clang::pseudo::ParseParams{*G, T, Arena, GSS});
+    if (Print)
+      llvm::outs() << Root.dumpRecursive(*G);
+  }
+};
+
+Fuzzer *Fuzz = nullptr;
+
+} // namespace
+} // namespace pseudo
+} // namespace clang
+
+extern "C" {
+
+// Set up the fuzzer from command line flags:
+//  -grammar=<file> (required) - path to cxx.bnf
+//  -print                     - used for testing the fuzzer
+int LLVMFuzzerInitialize(int *Argc, char ***Argv) {
+  llvm::StringRef GrammarFile;
+  bool PrintForest = false;
+  unsigned O = 1;
+  for (int I = 1; I < *Argc; ++I) {
+    llvm::StringRef Arg = (*Argv)[I];
+    if (Arg.consume_front("-grammar=")) {
+      GrammarFile = Arg;
+    } else if (Arg == "-print") {
+      PrintForest = true;
+    } else {
+      (*Argv)[O++] = (*Argv)[I];
+    }
+  }
+  *Argc = O;
+  if (GrammarFile.empty()) {
+    fprintf(stderr, "Fuzzer needs -grammar=/path/to/cxx.bnf\n");
+    exit(1);
+  }
+  clang::pseudo::Fuzz = new clang::pseudo::Fuzzer(GrammarFile, PrintForest);
+  return 0;
+}
+
+int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) {
+  (*clang::pseudo::Fuzz)(llvm::StringRef(reinterpret_cast<char *>(Data), Size));
+  return 0;
+}
+}
Index: clang-tools-extra/pseudo/fuzzer/CMakeLists.txt
===================================================================
--- /dev/null
+++ clang-tools-extra/pseudo/fuzzer/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS
+  FuzzMutate
+  Support
+  )
+
+add_llvm_fuzzer(clang-pseudo-fuzzer
+  Fuzzer.cpp
+  DUMMY_MAIN Main.cpp
+  )
+
+target_link_libraries(clang-pseudo-fuzzer
+  PRIVATE
+  clangPseudo
+  )
Index: clang-tools-extra/pseudo/CMakeLists.txt
===================================================================
--- clang-tools-extra/pseudo/CMakeLists.txt
+++ clang-tools-extra/pseudo/CMakeLists.txt
@@ -2,6 +2,7 @@
 include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
 add_subdirectory(lib)
 add_subdirectory(tool)
+add_subdirectory(fuzzer)
 if(CLANG_INCLUDE_TESTS)
   add_subdirectory(unittests)
   add_subdirectory(test)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to