Check a2dp packet length is zero

Bug: 142546668
Bug: 168254957
Test: net_test_stack_a2dp_native

Change-Id: I105b445293c02cb4f37c759fd5b05758fd4e3646
Merged-In: I105b445293c02cb4f37c759fd5b05758fd4e3646
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 8b05056..dc6882f 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -80,6 +80,10 @@
     {
       "name" : "net_test_btif_rc",
       "host" : true
+    },
+    {
+        "name" : "net_test_stack_a2dp_native",
+        "host" : true
     }
   ]
 }
diff --git a/stack/Android.bp b/stack/Android.bp
index f9d11e2..c468423 100644
--- a/stack/Android.bp
+++ b/stack/Android.bp
@@ -447,3 +447,36 @@
         cfi: false,
     },
 }
+
+cc_test {
+    name: "net_test_stack_a2dp_native",
+    defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
+    host_supported: true,
+    include_dirs: [
+        "external/libldac/inc",
+        "system/bt",
+        "system/bt/stack/include",
+    ],
+    srcs: [
+        "test/a2dp/a2dp_vendor_ldac_decoder_test.cc",
+        "test/a2dp/misc_fake.cc",
+    ],
+    shared_libs: [
+        "libcrypto",
+        "libcutils",
+        "libprotobuf-cpp-lite",
+    ],
+    static_libs: [
+        "libbt-common",
+        "libbt-protos-lite",
+        "liblog",
+        "libosi",
+        "libosi-AllocationTestHarness",
+    ],
+    sanitize: {
+        address: true,
+        cfi: true,
+        misc_undefined: ["bounds"],
+    },
+}
diff --git a/stack/a2dp/a2dp_vendor_ldac_decoder.cc b/stack/a2dp/a2dp_vendor_ldac_decoder.cc
index 444af34..d49337a 100644
--- a/stack/a2dp/a2dp_vendor_ldac_decoder.cc
+++ b/stack/a2dp/a2dp_vendor_ldac_decoder.cc
@@ -217,11 +217,20 @@
 }
 
 bool a2dp_vendor_ldac_decoder_decode_packet(BT_HDR* p_buf) {
+  if (p_buf == nullptr) {
+    LOG_ERROR(LOG_TAG, "%s Dropping packet with nullptr", __func__);
+    return false;
+  }
   unsigned char* pBuffer =
       reinterpret_cast<unsigned char*>(p_buf->data + p_buf->offset);
   //  unsigned int bufferSize = p_buf->len;
   unsigned int bytesValid = p_buf->len;
   int err;
+  if (bytesValid == 0) {
+    LOG_WARN(LOG_TAG, "%s Dropping packet with zero length", __func__);
+    return false;
+  }
+
   LDACBT_SMPL_FMT_T fmt;
   int bs_bytes, used_bytes, wrote_bytes, frame_number;
 
diff --git a/stack/include/ldacBT_bco_for_fluoride.h b/stack/include/ldacBT_bco_for_fluoride.h
new file mode 100644
index 0000000..9666a7c
--- /dev/null
+++ b/stack/include/ldacBT_bco_for_fluoride.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2016 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.
+ */
+#ifndef LDACBT_BCO_FOR_FLUORIDE_H__
+#define LDACBT_BCO_FOR_FLUORIDE_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef LDAC_BCO_API
+#define LDAC_BCO_API
+#endif /* LDAC_BCO_API */
+
+/* This file contains the definitions, declarations and macros for an
+ * implementation of LDAC buffer control operation.
+ */
+
+#define LDAC_BCO_ERR_NONE 0
+#define LDAC_BCO_ERR_FATAL (-1)
+
+/* LDAC BCO handle type */
+typedef struct _ldacbt_bco_handle* HANDLE_LDAC_BCO;
+
+typedef void (*decoded_data_callback_t)(uint8_t* buf, uint32_t len);
+
+/* Prepare to use LDAC BCO.
+ *  - Register a callback function for passing decoded data.
+ *  - Allocation of LDAC BCO handle.
+ *  Format
+ *      HANDLE_LDAC_BCO ldac_BCO_init(decoded_data_callback_t decode_callback);
+ *  Arguments
+ *      decoded_data_callback_t decode_callback
+ *              Callback function that outputs PCM data after decoding.
+ *              (See also a2dp_codec_api.h)
+ *  Return value
+ *      HANDLE_LDAC_BCO for success, NULL for failure.
+ */
+LDAC_BCO_API HANDLE_LDAC_BCO
+ldac_BCO_init(decoded_data_callback_t decode_callback);
+
+/* End LDAC BCO.
+ *  - Release of LDAC BCO handle.
+ *  Format
+ *      int32_t ldac_BCO_cleanup(HANDLE_LDAC_BCO hLdacBco);
+ *  Arguments
+ *      HANDLE_LDAC_BCO  hLdacBco    LDAC BCO handle.
+ *  Return value
+ *      int32_t : Processing result.
+ *              LDAC_BCO_ERR_NONE:Successful completion
+ *              LDAC_BCO_ERR_FATAL:Error
+ *  Note
+ *      The function ldac_BCO_init() shall be called before calling this
+ *      function.
+ */
+LDAC_BCO_API int32_t ldac_BCO_cleanup(HANDLE_LDAC_BCO hLdacBco);
+
+/* Decode LDAC packets.
+ * - Perform buffer control and decode processing.
+ *  Format
+ *      int32_t ldac_BCO_decode_packet(HANDLE_LDAC_BCO hLdacBco, void *data,
+ *                                                            int32_t length);
+ * Arguments
+ *      HANDLE_LDAC_BCO  hLdacBco    LDAC BCO handle.
+ *      void *data                   LDAC packet.
+ *      int32_t length               LDAC packet size.
+ * Return value
+ *      int32_t : Processing result.
+ *              LDAC_BCO_ERR_NONE:Successful completion
+ *              LDAC_BCO_ERR_FATAL:Error
+ * Note
+ *      The function ldac_BCO_init() shall be called before calling this
+ *      function.
+ */
+LDAC_BCO_API int32_t ldac_BCO_decode_packet(HANDLE_LDAC_BCO hLdacBco,
+                                            void* data, int32_t length);
+
+/* Start decoding process.
+ *  - Start or resume decoder thread.
+ *  Format
+ *      int32_t ldac_BCO_start(HANDLE_LDAC_BCO hLdacBco);
+ *  Arguments
+ *      HANDLE_LDAC_BCO  hLdacBco    LDAC BCO handle.
+ *  Return value
+ *      int32_t : Processing result.
+ *              LDAC_BCO_ERR_NONE:Successful completion
+ *              LDAC_BCO_ERR_FATAL:Error
+ *  Note
+ *      The function ldac_BCO_init() shall be called before calling this
+ *      function.
+ */
+LDAC_BCO_API int32_t ldac_BCO_start(HANDLE_LDAC_BCO hLdacBco);
+
+/* Suspend decoding process.
+ *  - Suspend the decoder thread.
+ *  Format
+ *      int32_t ldac_BCO_suspend(HANDLE_LDAC_BCO hLdacBco);
+ *  Arguments
+ *      HANDLE_LDAC_BCO  hLdacBco    LDAC BCO handle.
+ *  Return value
+ *      int32_t : Processing result.
+ *              LDAC_BCO_ERR_NONE:Successful completion
+ *              LDAC_BCO_ERR_FATAL:Error
+ *  Note
+ *      The function ldac_BCO_init() shall be called before calling this
+ *      function.
+ */
+LDAC_BCO_API int32_t ldac_BCO_suspend(HANDLE_LDAC_BCO hLdacBco);
+
+/* Configure codec information.
+ *  - Set sample rate, bits/sample and channel mode.
+ *  Format
+ *      int32_t ldac_BCO_configure(HANDLE_LDAC_BCO hLdacBco,
+ *              int32_t sample_rate, int32_t bits_per_sample,
+ *              int32_t channel_mode);
+ *  Arguments
+ *      HANDLE_LDAC_BCO  hLdacBco    LDAC BCO handle.
+ *      int32_t sample_rate          sample rate.
+ *      int32_t bits_per_sample      bits/sample.
+ *      int32_t channel_mode         channel mode.
+ *  Return value
+ *      int32_t : Processing result.
+ *              LDAC_BCO_ERR_NONE:Successful completion
+ *              LDAC_BCO_ERR_FATAL:Error
+ *  Note
+ *      The function ldac_BCO_init() shall be called before calling this
+ *      function.
+ */
+LDAC_BCO_API int32_t ldac_BCO_configure(HANDLE_LDAC_BCO hLdacBco,
+                                        int32_t sample_rate,
+                                        int32_t bits_per_sample,
+                                        int32_t channel_mode);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LDACBT_BCO_FOR_FLUORIDE_H__ */
diff --git a/stack/test/a2dp/a2dp_vendor_ldac_decoder_test.cc b/stack/test/a2dp/a2dp_vendor_ldac_decoder_test.cc
new file mode 100644
index 0000000..ac8c260
--- /dev/null
+++ b/stack/test/a2dp/a2dp_vendor_ldac_decoder_test.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright 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 <base/logging.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include <cstdint>
+
+#include "stack/include/ldacBT_bco_for_fluoride.h"
+
+#include "osi/test/AllocationTestHarness.h"
+#undef LOG_TAG
+#include "stack/a2dp/a2dp_vendor_ldac_decoder.cc"
+
+extern void allocation_tracker_uninit(void);
+namespace {
+
+uint8_t* Data(BT_HDR* packet) { return packet->data + packet->offset; }
+
+}  // namespace
+
+/**
+ * Test class to test selected functionality in stack/a2dp
+ */
+class A2dpStackTest : public AllocationTestHarness {
+ protected:
+  void SetUp() override {
+    AllocationTestHarness::SetUp();
+    // Disable our allocation tracker to allow ASAN full range
+    allocation_tracker_uninit();
+  }
+
+  void TearDown() override { AllocationTestHarness::TearDown(); }
+
+  BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const {
+    auto packet = AllocatePacket(data.size());
+    std::copy(data.cbegin(), data.cend(), Data(packet));
+    return packet;
+  }
+
+ private:
+  BT_HDR* AllocatePacket(size_t packet_length) const {
+    BT_HDR* packet =
+        static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
+    packet->len = packet_length;
+    return packet;
+  }
+};
+
+TEST_F(A2dpStackTest, DecodePacket_ZeroLength) {
+  const std::vector<uint8_t> data;
+  BT_HDR* p_buf = AllocateL2capPacket(data);
+  CHECK(!a2dp_vendor_ldac_decoder_decode_packet(p_buf));
+  osi_free(p_buf);
+}
diff --git a/stack/test/a2dp/misc_fake.cc b/stack/test/a2dp/misc_fake.cc
new file mode 100644
index 0000000..6f06218
--- /dev/null
+++ b/stack/test/a2dp/misc_fake.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright 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 "service/common/bluetooth/a2dp_codec_config.h"
+#include "stack/include/a2dp_vendor_ldac.h"
+
+bluetooth::A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) {
+  return nullptr;
+}
+
+int A2DP_VendorGetTrackSampleRateLdac(const uint8_t* p_codec_info) { return 0; }
+int A2DP_VendorGetTrackBitsPerSampleLdac(const uint8_t* p_codec_info) {
+  return 0;
+}
+int A2DP_VendorGetChannelModeCodeLdac(const uint8_t* p_codec_info) { return 0; }