dgoldman created this revision.
Herald added subscribers: cfe-commits, jfb, mgorny.
Herald added a project: clang.

- Similar to that of `clang-fuzzer` itself but instead only targets Objective-C 
source files via cc1

- Also adds an example corpus directory containing some input for Objective-C


Repository:
  rC Clang

https://reviews.llvm.org/D69171

Files:
  tools/clang-fuzzer/CMakeLists.txt
  tools/clang-fuzzer/ClangObjectiveCFuzzer.cpp
  tools/clang-fuzzer/Dockerfile
  tools/clang-fuzzer/README.txt
  tools/clang-fuzzer/corpus_examples/objc/BasicClass.m
  tools/clang-fuzzer/corpus_examples/objc/ClassCategory.m
  tools/clang-fuzzer/corpus_examples/objc/ClassExtension.m
  tools/clang-fuzzer/corpus_examples/objc/SharedInstance.m
  tools/clang-fuzzer/handle-objc/CMakeLists.txt
  tools/clang-fuzzer/handle-objc/handle_objc.cpp
  tools/clang-fuzzer/handle-objc/handle_objc.h

Index: tools/clang-fuzzer/handle-objc/handle_objc.h
===================================================================
--- /dev/null
+++ tools/clang-fuzzer/handle-objc/handle_objc.h
@@ -0,0 +1,24 @@
+//==-- handle_objc.h - Helper function for Clang fuzzers -------------------==//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines HandleObjC for use by the Clang Objective-C fuzzers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_OBJC_HANDLEOBJC_H
+#define LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_OBJC_HANDLEOBJC_H
+
+#include <string>
+#include <vector>
+
+namespace clang_fuzzer {
+void HandleObjC(const std::string &S,
+                const std::vector<const char *> &ExtraArgs);
+} // namespace clang_fuzzer
+
+#endif
Index: tools/clang-fuzzer/handle-objc/handle_objc.cpp
===================================================================
--- /dev/null
+++ tools/clang-fuzzer/handle-objc/handle_objc.cpp
@@ -0,0 +1,51 @@
+//==-- handle_objc.cpp - Helper function for Clang fuzzers -----------------==//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements HandleObjC for use by the Clang Objective-C fuzzers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "handle_objc.h"
+
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Option/Option.h"
+
+using namespace clang;
+
+void clang_fuzzer::HandleObjC(const std::string &S,
+                              const std::vector<const char *> &ExtraArgs) {
+  llvm::opt::ArgStringList CC1Args;
+  CC1Args.push_back("-cc1");
+  for (auto &A : ExtraArgs)
+    CC1Args.push_back(A);
+  CC1Args.push_back("./test.m");
+
+  llvm::IntrusiveRefCntPtr<FileManager> Files(
+      new FileManager(FileSystemOptions()));
+  IgnoringDiagConsumer Diags;
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+  DiagnosticsEngine Diagnostics(
+      IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
+      &Diags, false);
+  std::unique_ptr<clang::CompilerInvocation> Invocation(
+      tooling::newInvocation(&Diagnostics, CC1Args));
+  std::unique_ptr<llvm::MemoryBuffer> Input =
+      llvm::MemoryBuffer::getMemBuffer(S);
+  Invocation->getPreprocessorOpts().addRemappedFile("./test.m",
+                                                    Input.release());
+  std::unique_ptr<tooling::ToolAction> action(
+      tooling::newFrontendActionFactory<clang::EmitObjAction>());
+  std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+      std::make_shared<PCHContainerOperations>();
+  action->runInvocation(std::move(Invocation), Files.get(), PCHContainerOps,
+                        &Diags);
+}
+
Index: tools/clang-fuzzer/handle-objc/CMakeLists.txt
===================================================================
--- /dev/null
+++ tools/clang-fuzzer/handle-objc/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Support)
+
+add_clang_library(clangHandleObjC
+  handle_objc.cpp
+
+  LINK_LIBS
+  clangBasic
+  clangCodeGen
+  clangFrontend
+  clangLex
+  clangSerialization
+  clangTooling
+  )
Index: tools/clang-fuzzer/corpus_examples/objc/SharedInstance.m
===================================================================
--- /dev/null
+++ tools/clang-fuzzer/corpus_examples/objc/SharedInstance.m
@@ -0,0 +1,34 @@
+@interface RootObject
++ (instancetype)alloc;
+
+- (instancetype)init;
+@end
+
+@interface BaseClass : RootObject
++ (instancetype)sharedInstance;
+
+- (instancetype)initWithFoo:(int)foo;
+@end
+
+static BaseClass *sharedInstance = (void *)0;
+static int counter = 0;
+
+@implementation BaseClass
++ (instancetype)sharedInstance {
+  if (sharedInstance) {
+    return sharedInstance;
+  }
+  sharedInstance = [[BaseClass alloc] initWithFoo:3];
+  return sharedInstance;
+}
+
+
+- (instancetype)initWithFoo:(int)foo {
+  self = [super init];
+  if (self) {
+    counter += foo;
+  }
+  return self;
+}
+@end
+
Index: tools/clang-fuzzer/corpus_examples/objc/ClassExtension.m
===================================================================
--- /dev/null
+++ tools/clang-fuzzer/corpus_examples/objc/ClassExtension.m
@@ -0,0 +1,20 @@
+@interface RootObject
+@end
+
+@interface BaseClass : RootObject
+@end
+
+@interface BaseClass() {
+  int _field1;
+}
+@property(atomic, assign, readonly) int field2;
+
+- (int)addFields;
+@end
+
+@implementation BaseClass
+- (int)addFields {
+  return self->_field1 + [self field2];
+}
+@end
+
Index: tools/clang-fuzzer/corpus_examples/objc/ClassCategory.m
===================================================================
--- /dev/null
+++ tools/clang-fuzzer/corpus_examples/objc/ClassCategory.m
@@ -0,0 +1,20 @@
+@interface RootObject
+@end
+
+@interface BaseClass : RootObject
+@property(atomic, assign, readonly) int field;
+@end
+
+@interface BaseClass(Private)
+@property(atomic, assign, readwrite) int field;
+
+- (int)something;
+@end
+
+@implementation BaseClass
+- (int)something {
+  self.field = self.field + 1;
+  return self.field;
+}
+@end
+
Index: tools/clang-fuzzer/corpus_examples/objc/BasicClass.m
===================================================================
--- /dev/null
+++ tools/clang-fuzzer/corpus_examples/objc/BasicClass.m
@@ -0,0 +1,29 @@
+@interface RootObject
+@end
+
+@interface BasicClass : RootObject {
+  int _foo;
+  char _boolean;
+}
+
+@property(nonatomic, assign) int bar;
+@property(atomic, retain) id objectField;
+@property(nonatomic, assign) id delegate;
+
+- (void)someMethod;
+@end
+
+@implementation BasicClass
+
+@synthesize bar = _bar;
+@synthesize objectField = _objectField;
+@synthesize delegate = _delegate;
+
+- (void)someMethod {
+  int value = self.bar;
+  _foo = (_boolean != 0) ? self.bar : [self.objectField bar];
+  [self setBar:value];
+  id obj = self.objectField;
+}
+@end
+
Index: tools/clang-fuzzer/README.txt
===================================================================
--- tools/clang-fuzzer/README.txt
+++ tools/clang-fuzzer/README.txt
@@ -1,15 +1,21 @@
-This directory contains two utilities for fuzzing Clang: clang-fuzzer and
-clang-proto-fuzzer.  Both use libFuzzer to generate inputs to clang via
-coverage-guided mutation.
+This directory contains three utilities for fuzzing Clang: clang-fuzzer,
+clang-objc-fuzzer, and clang-proto-fuzzer. All use libFuzzer to generate inputs
+to clang via coverage-guided mutation.
 
-The two utilities differ, however, in how they structure inputs to Clang.
+The three utilities differ, however, in how they structure inputs to Clang.
 clang-fuzzer makes no attempt to generate valid C++ programs and is therefore
 primarily useful for stressing the surface layers of Clang (i.e. lexer, parser).
+
+clang-objc-fuzzer is similar but for Objective-C: it makes no attempt to
+generate a valid Objective-C program.
+
 clang-proto-fuzzer uses a protobuf class to describe a subset of the C++
 language and then uses libprotobuf-mutator to mutate instantiations of that
 class, producing valid C++ programs in the process.  As a result,
 clang-proto-fuzzer is better at stressing deeper layers of Clang and LLVM.
 
+Some of the fuzzers have example corpuses inside the corpus_examples directory.
+
 ===================================
  Building clang-fuzzer
 ===================================
@@ -35,6 +41,35 @@
   bin/clang-fuzzer CORPUS_DIR
 
 
+===================================
+ Building clang-objc-fuzzer
+===================================
+Within your LLVM build directory, run CMake with the following variable
+definitions:
+- CMAKE_C_COMPILER=clang
+- CMAKE_CXX_COMPILER=clang++
+- LLVM_USE_SANITIZE_COVERAGE=YES
+- LLVM_USE_SANITIZER=Address
+
+Then build the clang-objc-fuzzer target.
+
+Example:
+  cd $LLVM_SOURCE_DIR
+  mkdir build && cd build
+  cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
+    -DLLVM_USE_SANITIZE_COVERAGE=YES -DLLVM_USE_SANITIZER=Address
+  ninja clang-objc-fuzzer
+
+======================
+ Running clang-objc-fuzzer
+======================
+  bin/clang-objc-fuzzer CORPUS_DIR
+
+e.g. using the example objc corpus,
+
+  bin/clang-objc-fuzzer <path to corpus_examples/objc> <path to new directory to store  corpus findings>
+
+
 =======================================================
  Building clang-proto-fuzzer (Linux-only instructions)
 =======================================================
Index: tools/clang-fuzzer/Dockerfile
===================================================================
--- tools/clang-fuzzer/Dockerfile
+++ tools/clang-fuzzer/Dockerfile
@@ -32,6 +32,7 @@
     -DLLVM_USE_SANITIZER=Address -DCLANG_ENABLE_PROTO_FUZZER=ON
 # Build the fuzzers
 RUN cd build1 && ninja clang-fuzzer
+RUN cd build1 && ninja clang-objc-fuzzer
 RUN cd build1 && ninja clang-proto-fuzzer
 RUN cd build1 && ninja clang-proto-to-cxx
 RUN cd build1 && ninja clang-loop-proto-to-cxx
Index: tools/clang-fuzzer/ClangObjectiveCFuzzer.cpp
===================================================================
--- /dev/null
+++ tools/clang-fuzzer/ClangObjectiveCFuzzer.cpp
@@ -0,0 +1,25 @@
+//===-- ClangObjectiveCFuzzer.cpp - Fuzz Clang ----------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a function that runs Clang on a single Objective-C
+///   input. This function is then linked into the Fuzzer library.
+///
+//===----------------------------------------------------------------------===//
+
+#include "handle-objc/handle_objc.h"
+
+using namespace clang_fuzzer;
+
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { return 0; }
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+  std::string s((const char *)data, size);
+  HandleObjC(s, {"-O2"});
+  return 0;
+}
Index: tools/clang-fuzzer/CMakeLists.txt
===================================================================
--- tools/clang-fuzzer/CMakeLists.txt
+++ tools/clang-fuzzer/CMakeLists.txt
@@ -12,6 +12,7 @@
 # Needed by LLVM's CMake checks because this file defines multiple targets.
 set(LLVM_OPTIONAL_SOURCES
   ClangFuzzer.cpp
+  ClangObjectiveCFuzzer.cpp
   DummyClangFuzzer.cpp
   ExampleClangProtoFuzzer.cpp
   ExampleClangLoopProtoFuzzer.cpp
@@ -107,6 +108,7 @@
 endif()
 
 add_clang_subdirectory(handle-cxx)
+add_clang_subdirectory(handle-objc)
 add_clang_subdirectory(handle-llvm)
 
 add_clang_executable(clang-fuzzer
@@ -120,3 +122,15 @@
   ${LLVM_LIB_FUZZING_ENGINE}
   clangHandleCXX
   )
+
+add_clang_executable(clang-objc-fuzzer
+  EXCLUDE_FROM_ALL
+  ${DUMMY_MAIN}
+  ClangObjectiveCFuzzer.cpp
+  )
+
+target_link_libraries(clang-objc-fuzzer
+  PRIVATE
+  ${LLVM_LIB_FUZZING_ENGINE}
+  clangHandleObjC
+  )
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to