1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/audio/sync_reader.h"
6
7 #include <limits>
8 #include <memory>
9 #include <string>
10 #include <type_traits>
11 #include <utility>
12
13 #include "base/bind.h"
14 #include "base/memory/unsafe_shared_memory_region.h"
15 #include "base/sync_socket.h"
16 #include "base/test/task_environment.h"
17 #include "base/time/time.h"
18 #include "media/base/audio_bus.h"
19 #include "media/base/audio_parameters.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 using ::testing::TestWithParam;
24
25 using media::AudioBus;
26 using media::AudioOutputBuffer;
27 using media::AudioOutputBufferParameters;
28 using media::AudioParameters;
29
30 namespace audio {
31
NoLog(const std::string &)32 void NoLog(const std::string&) {}
33
34 static_assert(
35 std::is_unsigned<
36 decltype(AudioOutputBufferParameters::bitstream_data_size)>::value,
37 "If |bitstream_data_size| is ever made signed, add tests for negative "
38 "buffer sizes.");
39
40 enum OverflowTestCase {
41 kZero,
42 kNoOverflow,
43 kOverflowByOne,
44 kOverflowByOneThousand,
45 kOverflowByMax
46 };
47
48 static const OverflowTestCase overflow_test_case_values[]{
49 kZero, kNoOverflow, kOverflowByOne, kOverflowByOneThousand, kOverflowByMax};
50
51 class SyncReaderBitstreamTest : public TestWithParam<OverflowTestCase> {
52 public:
SyncReaderBitstreamTest()53 SyncReaderBitstreamTest() {}
~SyncReaderBitstreamTest()54 ~SyncReaderBitstreamTest() override {}
55
56 private:
57 base::test::TaskEnvironment env_;
58 };
59
TEST_P(SyncReaderBitstreamTest,BitstreamBufferOverflow_DoesNotWriteOOB)60 TEST_P(SyncReaderBitstreamTest, BitstreamBufferOverflow_DoesNotWriteOOB) {
61 const int kSampleRate = 44100;
62 const int kFramesPerBuffer = 1;
63 AudioParameters params(AudioParameters::AUDIO_BITSTREAM_AC3,
64 media::CHANNEL_LAYOUT_STEREO, kSampleRate,
65 kFramesPerBuffer);
66
67 auto socket = std::make_unique<base::CancelableSyncSocket>();
68 SyncReader reader(base::BindRepeating(&NoLog), params, socket.get());
69 ASSERT_TRUE(reader.IsValid());
70 const base::WritableSharedMemoryMapping shmem =
71 reader.TakeSharedMemoryRegion().Map();
72 ASSERT_TRUE(shmem.IsValid());
73 auto* const buffer =
74 reinterpret_cast<media::AudioOutputBuffer*>(shmem.memory());
75 ASSERT_TRUE(buffer);
76 reader.RequestMoreData(base::TimeDelta(), base::TimeTicks(), 0);
77
78 uint32_t signal;
79 EXPECT_EQ(socket->Receive(&signal, sizeof(signal)), sizeof(signal));
80
81 // So far, this is an ordinary stream.
82 // Now |reader| expects data to be written to the shared memory. The renderer
83 // says how much data was written.
84 switch (GetParam()) {
85 case kZero:
86 buffer->params.bitstream_data_size = 0;
87 break;
88 case kNoOverflow:
89 buffer->params.bitstream_data_size =
90 shmem.mapped_size() - sizeof(AudioOutputBufferParameters);
91 break;
92 case kOverflowByOne:
93 buffer->params.bitstream_data_size =
94 shmem.mapped_size() - sizeof(AudioOutputBufferParameters) + 1;
95 break;
96 case kOverflowByOneThousand:
97 buffer->params.bitstream_data_size =
98 shmem.mapped_size() - sizeof(AudioOutputBufferParameters) + 1000;
99 break;
100 case kOverflowByMax:
101 buffer->params.bitstream_data_size = std::numeric_limits<decltype(
102 buffer->params.bitstream_data_size)>::max();
103 break;
104 }
105
106 ++signal;
107 EXPECT_EQ(socket->Send(&signal, sizeof(signal)), sizeof(signal));
108
109 // The purpose of the test is to ensure this call doesn't result in undefined
110 // behavior, which should be verified by sanitizers.
111 std::unique_ptr<AudioBus> output_bus = AudioBus::Create(params);
112 reader.Read(output_bus.get());
113 }
114
115 INSTANTIATE_TEST_SUITE_P(All,
116 SyncReaderBitstreamTest,
117 ::testing::ValuesIn(overflow_test_case_values));
118
119 } // namespace audio
120