OSDN Git Service

Fuzzer for g722 encoder
authordakshesh <daksheshkumar@google.com>
Tue, 18 Aug 2020 15:19:04 +0000 (15:19 +0000)
committerdakshesh <daksheshkumar@google.com>
Tue, 25 Aug 2020 15:20:42 +0000 (15:20 +0000)
Max-length of Input provided to fuzzer is 4096. Ideally it would be less
than that in the encoder call.

To Build the fuzzer:
SANITIZE_TARGET=hwaddress m g722_enc_fuzzer

To run(on device):
adb shell data/fuzz/arm64/g722_enc_fuzzer/g722_enc_fuzzer

Bug: 164457579
Tag: #security
Test: Tested on pixel 4 with no initial corpus and getting ~6000 exec/s
Change-Id: I8392e2d3b432f213402789fd6af60901b1df8bdc

embdrv/g722/fuzzer/Android.bp [new file with mode: 0644]
embdrv/g722/fuzzer/g722_enc_fuzzer.cc [new file with mode: 0644]

diff --git a/embdrv/g722/fuzzer/Android.bp b/embdrv/g722/fuzzer/Android.bp
new file mode 100644 (file)
index 0000000..77c61f7
--- /dev/null
@@ -0,0 +1,15 @@
+cc_fuzz {
+    name: "g722_enc_fuzzer",
+    srcs: [
+        "g722_enc_fuzzer.cc",
+    ],
+    host_supported: false,
+    static_libs: [
+        "libg722codec",
+    ],
+    fuzz_config: {
+        cc: [
+            "hsz@google.com",
+        ],
+    },
+}
diff --git a/embdrv/g722/fuzzer/g722_enc_fuzzer.cc b/embdrv/g722/fuzzer/g722_enc_fuzzer.cc
new file mode 100644 (file)
index 0000000..19df472
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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 <fuzzer/FuzzedDataProvider.h>
+
+#include "../g722_enc_dec.h"
+
+uint32_t get_rate_from_fdp(FuzzedDataProvider* fdp) {
+  uint32_t rate = fdp->ConsumeIntegralInRange<uint32_t>(
+      0, 3);  // Currently 3 different bit rates are available in G.722 codec
+  switch (rate) {
+    case 0:
+      return 48000;
+    case 1:
+      return 56000;
+    default:
+      return 64000;
+  }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  FuzzedDataProvider fdp(data, size);
+
+  std::vector<uint8_t> buff;
+  for (size_t i = 0; i < size; i++) {
+    buff.push_back(data[i]);
+  }
+
+  int num_samples =
+      buff.size() / (2 /*bytes_per_sample*/ * 2 /*number of channels*/);
+
+  // The G.722 codec accept only even number of samples for encoding
+  if (num_samples % 2 != 0) {
+    num_samples--;
+  }
+
+  // Making channel data from buffer
+  std::vector<uint16_t> channel_data;
+
+  for (int i = 0; i < num_samples; i++) {
+    const uint8_t* sample = buff.data() + i * 2;
+    int16_t left = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
+
+    sample += 2;
+    int16_t right = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
+
+    uint16_t mono_data = (int16_t)(((uint32_t)left + (uint32_t)right) >> 1);
+    channel_data.push_back(mono_data);
+  }
+
+  uint32_t rate = get_rate_from_fdp(&fdp);
+
+  // Encoder Initialization
+  g722_encode_state_t* encoder_state = nullptr;
+  encoder_state = g722_encode_init(nullptr, rate, G722_PACKED);
+
+  // Encode
+  std::vector<uint8_t> encoded_data;
+  // Magic number is used in api, It should basically fit the number generated
+  // by this formula : num_channels * sample_rate * data_interval_ms
+  // * (bit_rate / 8)) / 1000 as mentioned in hearing_aid.cc And if we fit all
+  // the values in the above formula, the max value we can get is 1920. And I
+  // used "size" of the input that libfuzzer generates as the initial
+  // parameter to resize
+  encoded_data.resize(size);
+  int encoded_size =
+      g722_encode(encoder_state, encoded_data.data(),
+                  (const int16_t*)channel_data.data(), channel_data.size());
+  encoded_data.resize(encoded_size);
+
+  // Encoder release
+  if (encoder_state != nullptr) {
+    g722_encode_release(encoder_state);
+    encoder_state = nullptr;
+  }
+
+  return 0;
+}
\ No newline at end of file