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