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