xref: /aosp_15_r20/external/jazzer-api/launcher/jazzer_main.cpp (revision 33edd6723662ea34453766bfdca85dbfdd5342b8)
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