xref: /aosp_15_r20/external/jazzer-api/launcher/fuzzed_data_provider_test.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 #include <cstddef>
16*33edd672SMark #include <cstdint>
17*33edd672SMark #include <random>
18*33edd672SMark #include <string>
19*33edd672SMark #include <vector>
20*33edd672SMark 
21*33edd672SMark #include "gtest/gtest.h"
22*33edd672SMark #include "launcher/jvm_tooling.h"
23*33edd672SMark #include "tools/cpp/runfiles/runfiles.h"
24*33edd672SMark 
25*33edd672SMark namespace jazzer {
26*33edd672SMark 
27*33edd672SMark std::pair<std::string, jint> FixUpModifiedUtf8(const uint8_t* pos,
28*33edd672SMark                                                jint max_bytes, jint max_length,
29*33edd672SMark                                                bool ascii_only,
30*33edd672SMark                                                bool stop_on_backslash);
31*33edd672SMark 
32*33edd672SMark class FuzzedDataProviderTest : public ::testing::Test {
33*33edd672SMark  protected:
34*33edd672SMark   // After DestroyJavaVM() no new JVM instance can be created in the same
35*33edd672SMark   // process, so we set up a single JVM instance for this test binary which gets
36*33edd672SMark   // destroyed after all tests in this test suite have finished.
SetUpTestCase()37*33edd672SMark   static void SetUpTestCase() {
38*33edd672SMark     using ::bazel::tools::cpp::runfiles::Runfiles;
39*33edd672SMark     std::unique_ptr<Runfiles> runfiles(Runfiles::CreateForTest());
40*33edd672SMark     FLAGS_cp = runfiles->Rlocation(
41*33edd672SMark         "jazzer/launcher/testdata/fuzz_target_mocks_deploy.jar");
42*33edd672SMark 
43*33edd672SMark     jvm_ = std::make_unique<JVM>();
44*33edd672SMark   }
45*33edd672SMark 
TearDownTestCase()46*33edd672SMark   static void TearDownTestCase() { jvm_.reset(nullptr); }
47*33edd672SMark 
48*33edd672SMark   static std::unique_ptr<JVM> jvm_;
49*33edd672SMark };
50*33edd672SMark 
51*33edd672SMark std::unique_ptr<JVM> FuzzedDataProviderTest::jvm_ = nullptr;
52*33edd672SMark 
53*33edd672SMark constexpr std::size_t kValidModifiedUtf8NumRuns = 1000;
54*33edd672SMark constexpr std::size_t kValidModifiedUtf8NumBytes = 100000;
55*33edd672SMark constexpr uint32_t kValidModifiedUtf8Seed = 0x12345678;
56*33edd672SMark 
TEST_F(FuzzedDataProviderTest,InvalidModifiedUtf8AfterFixup)57*33edd672SMark TEST_F(FuzzedDataProviderTest, InvalidModifiedUtf8AfterFixup) {
58*33edd672SMark   auto& env = jvm_->GetEnv();
59*33edd672SMark   auto modified_utf8_validator = env.FindClass("test/ModifiedUtf8Encoder");
60*33edd672SMark   ASSERT_NE(nullptr, modified_utf8_validator);
61*33edd672SMark   auto string_to_modified_utf_bytes = env.GetStaticMethodID(
62*33edd672SMark       modified_utf8_validator, "encode", "(Ljava/lang/String;)[B");
63*33edd672SMark   ASSERT_NE(nullptr, string_to_modified_utf_bytes);
64*33edd672SMark   auto random_bytes = std::vector<uint8_t>(kValidModifiedUtf8NumBytes);
65*33edd672SMark   auto random = std::mt19937(kValidModifiedUtf8Seed);
66*33edd672SMark   for (bool ascii_only : {false, true}) {
67*33edd672SMark     for (bool stop_on_backslash : {false, true}) {
68*33edd672SMark       for (std::size_t i = 0; i < kValidModifiedUtf8NumRuns; ++i) {
69*33edd672SMark         std::generate(random_bytes.begin(), random_bytes.end(), random);
70*33edd672SMark         std::string fixed_string;
71*33edd672SMark         std::tie(fixed_string, std::ignore) = FixUpModifiedUtf8(
72*33edd672SMark             random_bytes.data(), random_bytes.size(),
73*33edd672SMark             std::numeric_limits<jint>::max(), ascii_only, stop_on_backslash);
74*33edd672SMark 
75*33edd672SMark         jstring jni_fixed_string = env.NewStringUTF(fixed_string.c_str());
76*33edd672SMark         auto jni_roundtripped_bytes = (jbyteArray)env.CallStaticObjectMethod(
77*33edd672SMark             modified_utf8_validator, string_to_modified_utf_bytes,
78*33edd672SMark             jni_fixed_string);
79*33edd672SMark         ASSERT_FALSE(env.ExceptionCheck());
80*33edd672SMark         env.DeleteLocalRef(jni_fixed_string);
81*33edd672SMark         jint roundtripped_bytes_length =
82*33edd672SMark             env.GetArrayLength(jni_roundtripped_bytes);
83*33edd672SMark         jbyte* roundtripped_bytes =
84*33edd672SMark             env.GetByteArrayElements(jni_roundtripped_bytes, nullptr);
85*33edd672SMark         auto roundtripped_string =
86*33edd672SMark             std::string(reinterpret_cast<char*>(roundtripped_bytes),
87*33edd672SMark                         roundtripped_bytes_length);
88*33edd672SMark         env.ReleaseByteArrayElements(jni_roundtripped_bytes, roundtripped_bytes,
89*33edd672SMark                                      JNI_ABORT);
90*33edd672SMark         env.DeleteLocalRef(jni_roundtripped_bytes);
91*33edd672SMark 
92*33edd672SMark         // Verify that the bytes obtained from running our modified UTF-8 fix-up
93*33edd672SMark         // function remain unchanged when turned into a Java string and
94*33edd672SMark         // reencoded into modified UTF-8. This will only happen if the our
95*33edd672SMark         // fix-up function indeed returned valid modified UTF-8.
96*33edd672SMark         ASSERT_EQ(fixed_string, roundtripped_string);
97*33edd672SMark       }
98*33edd672SMark     }
99*33edd672SMark   }
100*33edd672SMark }
101*33edd672SMark }  // namespace jazzer
102