Merge "ANDROID: Add simple fuzzing targets for video and video+audio encoding."
diff --git a/fuzzing/Android.bp b/fuzzing/Android.bp
new file mode 100644
index 0000000..50da3e3
--- /dev/null
+++ b/fuzzing/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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.
+
+cc_library {
+    name: "libwebm_mkvmuxer_fuzzer_common",
+    srcs: ["common.cpp"],
+    shared_libs: ["libwebm_mkvmuxer"],
+    host_supported: true,
+}
+
+cc_defaults {
+    name: "libwebm_mkvmuxer_fuzzer_defaults",
+    shared_libs: [
+        "libwebm_mkvmuxer_fuzzer_common",
+        "libwebm_mkvmuxer",
+    ],
+    host_supported: true,
+    fuzz_config: { componentid: 46263 },
+}
+
+cc_fuzz {
+    name: "libwebm_mkvmuxer_fuzzer_one_video_track",
+    srcs: ["mkvmuxer_one_video_track.cpp"],
+    defaults: ["libwebm_mkvmuxer_fuzzer_defaults"],
+}
+
+cc_fuzz {
+    name: "libwebm_mkvmuxer_fuzzer_one_video_audio_track",
+    srcs: ["mkvmuxer_one_video_audio_track.cpp"],
+    defaults: ["libwebm_mkvmuxer_fuzzer_defaults"],
+}
diff --git a/fuzzing/common.cpp b/fuzzing/common.cpp
new file mode 100644
index 0000000..5709673
--- /dev/null
+++ b/fuzzing/common.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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 "fuzzing/common.h"
+
+using mkvmuxer::int32;
+using mkvmuxer::int64;
+using mkvmuxer::uint32;
+using mkvmuxer::uint64;
+
+DiscardingMkvWriter::DiscardingMkvWriter() : position_(0), checksum_(0) {}
+
+int32 DiscardingMkvWriter::Write(const void* buf, uint32 len) {
+  auto data = static_cast<const uint8_t*>(buf);
+  for (uint32 i = 0; i < len; i++) {
+    // Force reads on all data in buf so ASAN can validate it
+    checksum_ += data[i];
+  }
+  position_ += len;
+  return 0;
+}
+
+int64 DiscardingMkvWriter::Position() const {
+  return position_;
+}
+
+int32 DiscardingMkvWriter::Position(int64 position) {
+  position_ = position;
+  return 0;
+}
+
+bool DiscardingMkvWriter::Seekable() const {
+  return true;
+}
+
+void DiscardingMkvWriter::ElementStartNotify(uint64, int64) {
+}
+
+std::vector<uint8_t> FuzzerRandomLengthBytes(FuzzedDataProvider& fdp) {
+  // https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#main-concepts
+  // ConsumeRandomLengthString is a good source of data, but we have to remove
+  // the null terminator to not hide off-by-one access errors.
+  std::string str = fdp.ConsumeRandomLengthString();
+  std::vector<uint8_t> data(str.begin(), str.end());
+  return data;
+}
diff --git a/fuzzing/common.h b/fuzzing/common.h
new file mode 100644
index 0000000..b0f498e
--- /dev/null
+++ b/fuzzing/common.h
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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.
+
+#pragma once
+
+#include <stdint.h>
+#include <vector>
+
+#include "mkvmuxer/mkvmuxer.h"
+#include "fuzzer/FuzzedDataProvider.h"
+
+class DiscardingMkvWriter : public mkvmuxer::IMkvWriter {
+public:
+  DiscardingMkvWriter();
+
+  mkvmuxer::int32 Write(const void* buf, mkvmuxer::uint32 len) override;
+  mkvmuxer::int64 Position() const override;
+  mkvmuxer::int32 Position(mkvmuxer::int64 position) override;
+  bool Seekable() const override;
+  void ElementStartNotify(mkvmuxer::uint64, mkvmuxer::int64) override;
+
+private:
+  mkvmuxer::int64 position_;
+  mkvmuxer::int64 checksum_;
+};
+
+std::vector<uint8_t> FuzzerRandomLengthBytes(FuzzedDataProvider&);
diff --git a/fuzzing/mkvmuxer_one_video_audio_track.cpp b/fuzzing/mkvmuxer_one_video_audio_track.cpp
new file mode 100644
index 0000000..b51788a
--- /dev/null
+++ b/fuzzing/mkvmuxer_one_video_audio_track.cpp
@@ -0,0 +1,71 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include <sstream>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "mkvmuxer/mkvmuxer.h"
+#include "fuzzing/common.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  FuzzedDataProvider fdp(data, size);
+
+  mkvmuxer::Segment segment;
+  DiscardingMkvWriter writer;
+  segment.Init(&writer);
+
+  auto width = fdp.ConsumeIntegral<int32_t>();
+  auto height = fdp.ConsumeIntegral<int32_t>();
+
+  uint64_t video_track_number = segment.AddVideoTrack(width, height, 0);
+
+  if (video_track_number == 0) {
+    return 0;
+  }
+
+  auto sample_rate = fdp.ConsumeIntegral<int32_t>();
+  auto channels = fdp.ConsumeIntegral<int32_t>();
+
+  uint64_t audio_track_number = segment.AddAudioTrack(sample_rate, channels, 0);
+
+  if (audio_track_number == 0) {
+    return 0;
+  }
+
+  while (fdp.remaining_bytes() > 0) {
+    auto video_frame = FuzzerRandomLengthBytes(fdp);
+    segment.AddFrame(
+        video_frame.data(),
+        video_frame.size(),
+        video_track_number,
+        fdp.ConsumeIntegral<uint64_t>(),
+        fdp.ConsumeBool());
+
+    auto audio_frame = FuzzerRandomLengthBytes(fdp);
+    segment.AddFrame(
+        audio_frame.data(),
+        audio_frame.size(),
+        audio_track_number,
+        fdp.ConsumeIntegral<uint64_t>(),
+        fdp.ConsumeBool());
+  }
+
+  segment.Finalize();
+
+  return 0;
+}
diff --git a/fuzzing/mkvmuxer_one_video_track.cpp b/fuzzing/mkvmuxer_one_video_track.cpp
new file mode 100644
index 0000000..b4f1bdc
--- /dev/null
+++ b/fuzzing/mkvmuxer_one_video_track.cpp
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include <sstream>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "mkvmuxer/mkvmuxer.h"
+#include "fuzzing/common.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  FuzzedDataProvider fdp(data, size);
+
+  mkvmuxer::Segment segment;
+  DiscardingMkvWriter writer;
+  segment.Init(&writer);
+
+  int width = fdp.ConsumeIntegral<int>();
+  int height = fdp.ConsumeIntegral<int>();
+
+  uint64_t video_track_number = segment.AddVideoTrack(width, height, 0);
+
+  if (video_track_number == 0) {
+    return 0;
+  }
+
+  while (fdp.remaining_bytes() > 0) {
+    auto frame = FuzzerRandomLengthBytes(fdp);
+    segment.AddFrame(
+        frame.data(),
+        frame.size(),
+        video_track_number,
+        fdp.ConsumeIntegral<uint64_t>(),
+        fdp.ConsumeBool());
+  }
+
+  segment.Finalize();
+
+  return 0;
+}