1 // Copyright 2021 Code Intelligence GmbH
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 /*
16 * Jazzer's native main function, which starts a JVM suitably configured for
17 * fuzzing and passes control to the Java part of the driver.
18 */
19
20 #include <rules_jni.h>
21
22 #include <algorithm>
23 #include <iostream>
24 #include <memory>
25 #include <vector>
26
27 #include "absl/strings/str_split.h"
28 #include "jvm_tooling.h"
29
30 namespace {
31 const std::string kJazzerClassName = "com/code_intelligence/jazzer/Jazzer";
32
StartLibFuzzer(std::unique_ptr<jazzer::JVM> jvm,std::vector<std::string> argv)33 void StartLibFuzzer(std::unique_ptr<jazzer::JVM> jvm,
34 std::vector<std::string> argv) {
35 JNIEnv &env = jvm->GetEnv();
36 jclass runner = env.FindClass(kJazzerClassName.c_str());
37 if (runner == nullptr) {
38 env.ExceptionDescribe();
39 exit(1);
40 }
41 jmethodID startDriver = env.GetStaticMethodID(runner, "main", "([[B)V");
42 if (startDriver == nullptr) {
43 env.ExceptionDescribe();
44 exit(1);
45 }
46 jclass byteArrayClass = env.FindClass("[B");
47 if (byteArrayClass == nullptr) {
48 env.ExceptionDescribe();
49 exit(1);
50 }
51 jobjectArray args = env.NewObjectArray(argv.size(), byteArrayClass, nullptr);
52 if (args == nullptr) {
53 env.ExceptionDescribe();
54 exit(1);
55 }
56 for (jsize i = 0; i < argv.size(); ++i) {
57 jint len = argv[i].size();
58 jbyteArray arg = env.NewByteArray(len);
59 if (arg == nullptr) {
60 env.ExceptionDescribe();
61 exit(1);
62 }
63 // startDriver expects UTF-8 encoded strings that are not null-terminated.
64 env.SetByteArrayRegion(arg, 0, len,
65 reinterpret_cast<const jbyte *>(argv[i].data()));
66 if (env.ExceptionCheck()) {
67 env.ExceptionDescribe();
68 exit(1);
69 }
70 env.SetObjectArrayElement(args, i, arg);
71 if (env.ExceptionCheck()) {
72 env.ExceptionDescribe();
73 exit(1);
74 }
75 env.DeleteLocalRef(arg);
76 }
77 env.CallStaticVoidMethod(runner, startDriver, args);
78 // Should not return.
79 if (env.ExceptionCheck()) {
80 env.ExceptionDescribe();
81 }
82 exit(1);
83 }
84 } // namespace
85
main(int argc,char ** argv)86 int main(int argc, char **argv) {
87 rules_jni_init(argv[0]);
88
89 for (int i = 1; i < argc; ++i) {
90 const std::string &arg = argv[i];
91 std::vector<std::string> split =
92 absl::StrSplit(arg, absl::MaxSplits('=', 1));
93 if (split.size() < 2) {
94 continue;
95 }
96 if (split[0] == "--cp") {
97 FLAGS_cp = split[1];
98 } else if (split[0] == "--jvm_args") {
99 FLAGS_jvm_args = split[1];
100 } else if (split[0] == "--additional_jvm_args") {
101 FLAGS_additional_jvm_args = split[1];
102 } else if (split[0] == "--agent_path") {
103 FLAGS_agent_path = split[1];
104 }
105 }
106
107 StartLibFuzzer(std::unique_ptr<jazzer::JVM>(new jazzer::JVM()),
108 std::vector<std::string>(argv + 1, argv + argc));
109 }
110