Add functions to interact with ASan and MSan, and some sample uses

The sample uses are from when I debugged bug 617124. The change in neteq_network_stats_unittest.cc is a fix for a minor unrelated bug found by the try bots when I tried to land this CL (a test was passing uninitialized packet data to NetEq).

BUG=chromium:617124

Review-Url: https://codereview.webrtc.org/2293893002
Cr-Commit-Position: refs/heads/master@{#14034}
diff --git a/webrtc/base/BUILD.gn b/webrtc/base/BUILD.gn
index e166a4f..5da158a 100644
--- a/webrtc/base/BUILD.gn
+++ b/webrtc/base/BUILD.gn
@@ -152,6 +152,7 @@
     "refcount.h",
     "safe_conversions.h",
     "safe_conversions_impl.h",
+    "sanitizer.h",
     "scoped_ref_ptr.h",
     "stringencode.cc",
     "stringencode.h",
diff --git a/webrtc/base/array_view.h b/webrtc/base/array_view.h
index 8680096..783e717 100644
--- a/webrtc/base/array_view.h
+++ b/webrtc/base/array_view.h
@@ -130,6 +130,11 @@
   size_t size_;
 };
 
+template <typename T>
+inline ArrayView<T> MakeArrayView(T* data, size_t size) {
+  return ArrayView<T>(data, size);
+}
+
 }  // namespace rtc
 
 #endif  // WEBRTC_BASE_ARRAY_VIEW_H_
diff --git a/webrtc/base/base.gyp b/webrtc/base/base.gyp
index 6e3b02e..b941544 100644
--- a/webrtc/base/base.gyp
+++ b/webrtc/base/base.gyp
@@ -82,6 +82,7 @@
         'refcount.h',
         'safe_conversions.h',
         'safe_conversions_impl.h',
+        'sanitizer.h',
         'scoped_ref_ptr.h',
         'stringencode.cc',
         'stringencode.h',
diff --git a/webrtc/base/sanitizer.h b/webrtc/base/sanitizer.h
new file mode 100644
index 0000000..3327e08
--- /dev/null
+++ b/webrtc/base/sanitizer.h
@@ -0,0 +1,107 @@
+/*
+ *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_BASE_SANITIZER_H_
+#define WEBRTC_BASE_SANITIZER_H_
+
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+#define RTC_HAS_ASAN 1
+#endif
+#if __has_feature(memory_sanitizer)
+#define RTC_HAS_MSAN 1
+#endif
+#endif
+#ifndef RTC_HAS_ASAN
+#define RTC_HAS_ASAN 0
+#endif
+#ifndef RTC_HAS_MSAN
+#define RTC_HAS_MSAN 0
+#endif
+
+#if RTC_HAS_ASAN
+#include <sanitizer/asan_interface.h>
+#endif
+#if RTC_HAS_MSAN
+#include <sanitizer/msan_interface.h>
+#endif
+
+// Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements)
+// as being unaddressable, so that reads and writes are not allowed. ASan may
+// narrow the range to the nearest alignment boundaries.
+static inline void rtc_AsanPoison(const volatile void* ptr,
+                                  size_t element_size,
+                                  size_t num_elements) {
+#if RTC_HAS_ASAN
+  ASAN_POISON_MEMORY_REGION(ptr, element_size * num_elements);
+#endif
+}
+
+// Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements)
+// as being addressable, so that reads and writes are allowed. ASan may widen
+// the range to the nearest alignment boundaries.
+static inline void rtc_AsanUnpoison(const volatile void* ptr,
+                                    size_t element_size,
+                                    size_t num_elements) {
+#if RTC_HAS_ASAN
+  ASAN_UNPOISON_MEMORY_REGION(ptr, element_size * num_elements);
+#endif
+}
+
+// Ask MSan to mark the memory range [ptr, ptr + element_size * num_elements)
+// as being uninitialized.
+static inline void rtc_MsanMarkUninitialized(const volatile void* ptr,
+                                             size_t element_size,
+                                             size_t num_elements) {
+#if RTC_HAS_MSAN
+  __msan_poison(ptr, element_size * num_elements);
+#endif
+}
+
+// Force an MSan check (if any bits in the memory range [ptr, ptr +
+// element_size * num_elements) are uninitialized the call will crash with an
+// MSan report).
+static inline void rtc_MsanCheckInitialized(const volatile void* ptr,
+                                            size_t element_size,
+                                            size_t num_elements) {
+#if RTC_HAS_MSAN
+  __msan_check_mem_is_initialized(ptr, element_size * num_elements);
+#endif
+}
+
+#ifdef __cplusplus
+
+namespace rtc {
+
+template <typename T>
+inline void AsanPoison(const T& mem) {
+  rtc_AsanPoison(mem.data(), sizeof(mem.data()[0]), mem.size());
+}
+
+template <typename T>
+inline void AsanUnpoison(const T& mem) {
+  rtc_AsanUnpoison(mem.data(), sizeof(mem.data()[0]), mem.size());
+}
+
+template <typename T>
+inline void MsanMarkUninitialized(const T& mem) {
+  rtc_MsanMarkUninitialized(mem.data(), sizeof(mem.data()[0]), mem.size());
+}
+
+template <typename T>
+inline void MsanCheckInitialized(const T& mem) {
+  rtc_MsanCheckInitialized(mem.data(), sizeof(mem.data()[0]), mem.size());
+}
+
+}  // namespace rtc
+
+#endif  // __cplusplus
+
+#endif  // WEBRTC_BASE_SANITIZER_H_
diff --git a/webrtc/common_audio/signal_processing/downsample_fast.c b/webrtc/common_audio/signal_processing/downsample_fast.c
index 726a888..3cbc3c1 100644
--- a/webrtc/common_audio/signal_processing/downsample_fast.c
+++ b/webrtc/common_audio/signal_processing/downsample_fast.c
@@ -10,6 +10,9 @@
 
 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
 
+#include "webrtc/base/checks.h"
+#include "webrtc/base/sanitizer.h"
+
 // TODO(Bjornv): Change the function parameter order to WebRTC code style.
 // C version of WebRtcSpl_DownsampleFast() for generic platforms.
 int WebRtcSpl_DownsampleFastC(const int16_t* data_in,
@@ -20,6 +23,7 @@
                               size_t coefficients_length,
                               int factor,
                               size_t delay) {
+  int16_t* const original_data_out = data_out;
   size_t i = 0;
   size_t j = 0;
   int32_t out_s32 = 0;
@@ -31,10 +35,14 @@
     return -1;
   }
 
+  rtc_MsanCheckInitialized(coefficients, sizeof(coefficients[0]),
+                           coefficients_length);
+
   for (i = delay; i < endpos; i += factor) {
     out_s32 = 2048;  // Round value, 0.5 in Q12.
 
     for (j = 0; j < coefficients_length; j++) {
+      rtc_MsanCheckInitialized(&data_in[i - j], sizeof(data_in[0]), 1);
       out_s32 += coefficients[j] * data_in[i - j];  // Q12.
     }
 
@@ -44,5 +52,9 @@
     *data_out++ = WebRtcSpl_SatW32ToW16(out_s32);
   }
 
+  RTC_DCHECK_EQ(original_data_out + data_out_length, data_out);
+  rtc_MsanCheckInitialized(original_data_out, sizeof(original_data_out[0]),
+                           data_out_length);
+
   return 0;
 }
diff --git a/webrtc/common_audio/signal_processing/filter_ma_fast_q12.c b/webrtc/common_audio/signal_processing/filter_ma_fast_q12.c
index f4d9a3d..98f5b3c 100644
--- a/webrtc/common_audio/signal_processing/filter_ma_fast_q12.c
+++ b/webrtc/common_audio/signal_processing/filter_ma_fast_q12.c
@@ -17,6 +17,8 @@
 
 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
 
+#include "webrtc/base/sanitizer.h"
+
 void WebRtcSpl_FilterMAFastQ12(const int16_t* in_ptr,
                                int16_t* out_ptr,
                                const int16_t* B,
@@ -24,6 +26,11 @@
                                size_t length)
 {
     size_t i, j;
+
+    rtc_MsanCheckInitialized(B, sizeof(B[0]), B_length);
+    rtc_MsanCheckInitialized(in_ptr - B_length + 1, sizeof(in_ptr[0]),
+                             B_length + length - 1);
+
     for (i = 0; i < length; i++)
     {
         int32_t o = 0;
diff --git a/webrtc/modules/audio_coding/codecs/audio_decoder.cc b/webrtc/modules/audio_coding/codecs/audio_decoder.cc
index 442ddc1..8d4a2bc 100644
--- a/webrtc/modules/audio_coding/codecs/audio_decoder.cc
+++ b/webrtc/modules/audio_coding/codecs/audio_decoder.cc
@@ -12,7 +12,9 @@
 
 #include <assert.h>
 
+#include "webrtc/base/array_view.h"
 #include "webrtc/base/checks.h"
+#include "webrtc/base/sanitizer.h"
 #include "webrtc/base/trace_event.h"
 
 namespace webrtc {
@@ -21,6 +23,7 @@
                          int sample_rate_hz, size_t max_decoded_bytes,
                          int16_t* decoded, SpeechType* speech_type) {
   TRACE_EVENT0("webrtc", "AudioDecoder::Decode");
+  rtc::MsanCheckInitialized(rtc::MakeArrayView(encoded, encoded_len));
   int duration = PacketDuration(encoded, encoded_len);
   if (duration >= 0 &&
       duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
@@ -34,6 +37,7 @@
                                   int sample_rate_hz, size_t max_decoded_bytes,
                                   int16_t* decoded, SpeechType* speech_type) {
   TRACE_EVENT0("webrtc", "AudioDecoder::DecodeRedundant");
+  rtc::MsanCheckInitialized(rtc::MakeArrayView(encoded, encoded_len));
   int duration = PacketDurationRedundant(encoded, encoded_len);
   if (duration >= 0 &&
       duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
diff --git a/webrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.c b/webrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.c
index 4dcf49b..8dcb6b7 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.c
+++ b/webrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.c
@@ -18,6 +18,7 @@
 
 #include "defines.h"
 #include "constants.h"
+#include "webrtc/base/sanitizer.h"
 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
 
 /*----------------------------------------------------------------*
@@ -40,6 +41,9 @@
    */
   size_t interp_len = WEBRTC_SPL_MIN(index, 4);
 
+  rtc_MsanCheckInitialized(buffer - index - interp_len, sizeof(buffer[0]),
+                           index + interp_len);
+
   ilow = index - interp_len;
 
   /* copy the first noninterpolated part */
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
index b911d5a..7d200f0 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
@@ -19,6 +19,7 @@
 #include "webrtc/base/checks.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/safe_conversions.h"
+#include "webrtc/base/sanitizer.h"
 #include "webrtc/base/trace_event.h"
 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
@@ -132,6 +133,7 @@
 int NetEqImpl::InsertPacket(const WebRtcRTPHeader& rtp_header,
                             rtc::ArrayView<const uint8_t> payload,
                             uint32_t receive_timestamp) {
+  rtc::MsanCheckInitialized(payload);
   TRACE_EVENT0("webrtc", "NetEqImpl::InsertPacket");
   rtc::CritScope lock(&crit_sect_);
   int error =
diff --git a/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
index ca7c459..15c60a8 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
@@ -201,7 +201,8 @@
                                                       frame_size_samples_,
                                                       &rtp_header_);
         if (!Lost(next_send_time)) {
-          InsertPacket(rtp_header_, payload_, next_send_time);
+          static const uint8_t payload[kPayloadSizeByte] = {0};
+          InsertPacket(rtp_header_, payload, next_send_time);
         }
       }
       GetOutputAudio(&output_frame_);
@@ -277,7 +278,6 @@
   WebRtcRTPHeader rtp_header_;
   uint32_t last_lost_time_;
   uint32_t packet_loss_interval_;
-  uint8_t payload_[kPayloadSizeByte];
   AudioFrame output_frame_;
 };