aboutsummaryrefslogtreecommitdiff
path: root/launcher/fuzzed_data_provider_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'launcher/fuzzed_data_provider_test.cpp')
-rw-r--r--launcher/fuzzed_data_provider_test.cpp101
1 files changed, 101 insertions, 0 deletions
diff --git a/launcher/fuzzed_data_provider_test.cpp b/launcher/fuzzed_data_provider_test.cpp
new file mode 100644
index 00000000..9907b75e
--- /dev/null
+++ b/launcher/fuzzed_data_provider_test.cpp
@@ -0,0 +1,101 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cstddef>
+#include <cstdint>
+#include <random>
+#include <string>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "launcher/jvm_tooling.h"
+#include "tools/cpp/runfiles/runfiles.h"
+
+namespace jazzer {
+
+std::pair<std::string, jint> FixUpModifiedUtf8(const uint8_t* pos,
+ jint max_bytes, jint max_length,
+ bool ascii_only,
+ bool stop_on_backslash);
+
+class FuzzedDataProviderTest : public ::testing::Test {
+ protected:
+ // After DestroyJavaVM() no new JVM instance can be created in the same
+ // process, so we set up a single JVM instance for this test binary which gets
+ // destroyed after all tests in this test suite have finished.
+ static void SetUpTestCase() {
+ using ::bazel::tools::cpp::runfiles::Runfiles;
+ std::unique_ptr<Runfiles> runfiles(Runfiles::CreateForTest());
+ FLAGS_cp = runfiles->Rlocation(
+ "jazzer/launcher/testdata/fuzz_target_mocks_deploy.jar");
+
+ jvm_ = std::make_unique<JVM>();
+ }
+
+ static void TearDownTestCase() { jvm_.reset(nullptr); }
+
+ static std::unique_ptr<JVM> jvm_;
+};
+
+std::unique_ptr<JVM> FuzzedDataProviderTest::jvm_ = nullptr;
+
+constexpr std::size_t kValidModifiedUtf8NumRuns = 1000;
+constexpr std::size_t kValidModifiedUtf8NumBytes = 100000;
+constexpr uint32_t kValidModifiedUtf8Seed = 0x12345678;
+
+TEST_F(FuzzedDataProviderTest, InvalidModifiedUtf8AfterFixup) {
+ auto& env = jvm_->GetEnv();
+ auto modified_utf8_validator = env.FindClass("test/ModifiedUtf8Encoder");
+ ASSERT_NE(nullptr, modified_utf8_validator);
+ auto string_to_modified_utf_bytes = env.GetStaticMethodID(
+ modified_utf8_validator, "encode", "(Ljava/lang/String;)[B");
+ ASSERT_NE(nullptr, string_to_modified_utf_bytes);
+ auto random_bytes = std::vector<uint8_t>(kValidModifiedUtf8NumBytes);
+ auto random = std::mt19937(kValidModifiedUtf8Seed);
+ for (bool ascii_only : {false, true}) {
+ for (bool stop_on_backslash : {false, true}) {
+ for (std::size_t i = 0; i < kValidModifiedUtf8NumRuns; ++i) {
+ std::generate(random_bytes.begin(), random_bytes.end(), random);
+ std::string fixed_string;
+ std::tie(fixed_string, std::ignore) = FixUpModifiedUtf8(
+ random_bytes.data(), random_bytes.size(),
+ std::numeric_limits<jint>::max(), ascii_only, stop_on_backslash);
+
+ jstring jni_fixed_string = env.NewStringUTF(fixed_string.c_str());
+ auto jni_roundtripped_bytes = (jbyteArray)env.CallStaticObjectMethod(
+ modified_utf8_validator, string_to_modified_utf_bytes,
+ jni_fixed_string);
+ ASSERT_FALSE(env.ExceptionCheck());
+ env.DeleteLocalRef(jni_fixed_string);
+ jint roundtripped_bytes_length =
+ env.GetArrayLength(jni_roundtripped_bytes);
+ jbyte* roundtripped_bytes =
+ env.GetByteArrayElements(jni_roundtripped_bytes, nullptr);
+ auto roundtripped_string =
+ std::string(reinterpret_cast<char*>(roundtripped_bytes),
+ roundtripped_bytes_length);
+ env.ReleaseByteArrayElements(jni_roundtripped_bytes, roundtripped_bytes,
+ JNI_ABORT);
+ env.DeleteLocalRef(jni_roundtripped_bytes);
+
+ // Verify that the bytes obtained from running our modified UTF-8 fix-up
+ // function remain unchanged when turned into a Java string and
+ // reencoded into modified UTF-8. This will only happen if the our
+ // fix-up function indeed returned valid modified UTF-8.
+ ASSERT_EQ(fixed_string, roundtripped_string);
+ }
+ }
+ }
+}
+} // namespace jazzer