From ac554eebb9365ca1bb383b62bb436ff3ae470bd8 Mon Sep 17 00:00:00 2001 From: kwiberg Date: Fri, 2 Sep 2016 00:39:33 -0700 Subject: [PATCH] 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} --- webrtc/base/BUILD.gn | 1 + webrtc/base/array_view.h | 5 + webrtc/base/base.gyp | 1 + webrtc/base/sanitizer.h | 107 ++++++++++++++++++ .../signal_processing/downsample_fast.c | 12 ++ .../signal_processing/filter_ma_fast_q12.c | 7 ++ .../audio_coding/codecs/audio_decoder.cc | 4 + .../codecs/ilbc/create_augmented_vec.c | 4 + .../modules/audio_coding/neteq/neteq_impl.cc | 2 + .../neteq/neteq_network_stats_unittest.cc | 4 +- 10 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 webrtc/base/sanitizer.h diff --git a/webrtc/base/BUILD.gn b/webrtc/base/BUILD.gn index e166a4f7ba..5da158a4a5 100644 --- a/webrtc/base/BUILD.gn +++ b/webrtc/base/BUILD.gn @@ -152,6 +152,7 @@ static_library("rtc_base_approved") { "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 868009631f..783e717b7b 100644 --- a/webrtc/base/array_view.h +++ b/webrtc/base/array_view.h @@ -130,6 +130,11 @@ class ArrayView final { size_t size_; }; +template +inline ArrayView MakeArrayView(T* data, size_t size) { + return ArrayView(data, size); +} + } // namespace rtc #endif // WEBRTC_BASE_ARRAY_VIEW_H_ diff --git a/webrtc/base/base.gyp b/webrtc/base/base.gyp index 6e3b02e5bd..b941544ea4 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 0000000000..3327e08f7d --- /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 +#endif +#if RTC_HAS_MSAN +#include +#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 +inline void AsanPoison(const T& mem) { + rtc_AsanPoison(mem.data(), sizeof(mem.data()[0]), mem.size()); +} + +template +inline void AsanUnpoison(const T& mem) { + rtc_AsanUnpoison(mem.data(), sizeof(mem.data()[0]), mem.size()); +} + +template +inline void MsanMarkUninitialized(const T& mem) { + rtc_MsanMarkUninitialized(mem.data(), sizeof(mem.data()[0]), mem.size()); +} + +template +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 726a88819a..3cbc3c111a 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 @@ int WebRtcSpl_DownsampleFastC(const int16_t* data_in, 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 @@ int WebRtcSpl_DownsampleFastC(const int16_t* data_in, 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 @@ int WebRtcSpl_DownsampleFastC(const int16_t* data_in, *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 f4d9a3d303..98f5b3cb6d 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 @@ void WebRtcSpl_FilterMAFastQ12(const int16_t* in_ptr, 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 442ddc1e4b..8d4a2bc175 100644 --- a/webrtc/modules/audio_coding/codecs/audio_decoder.cc +++ b/webrtc/modules/audio_coding/codecs/audio_decoder.cc @@ -12,7 +12,9 @@ #include +#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 AudioDecoder::Decode(const uint8_t* encoded, size_t encoded_len, 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 AudioDecoder::DecodeRedundant(const uint8_t* encoded, size_t encoded_len, 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 4dcf49b6e7..8dcb6b75a0 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 @@ void WebRtcIlbcfix_CreateAugmentedVec( */ 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 b911d5a27f..7d200f01e5 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 @@ NetEqImpl::~NetEqImpl() = default; int NetEqImpl::InsertPacket(const WebRtcRTPHeader& rtp_header, rtc::ArrayView 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 ca7c459676..15c60a83b5 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 @@ NetEqNetworkStatsTest(NetEqDecoder codec, 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 @@ NetEqNetworkStatsTest(NetEqDecoder codec, WebRtcRTPHeader rtp_header_; uint32_t last_lost_time_; uint32_t packet_loss_interval_; - uint8_t payload_[kPayloadSizeByte]; AudioFrame output_frame_; };