summaryrefslogtreecommitdiff
path: root/src/audio_core/sink
diff options
context:
space:
mode:
authorGravatar Morph2023-06-30 00:54:23 -0400
committerGravatar Morph2023-06-30 00:54:23 -0400
commitea8d5ef5e81861e013b5c58189faeffe7d3a6f18 (patch)
treeae781e60097b06182a9cb8cd06434d049fc0f0a0 /src/audio_core/sink
parentMerge pull request #10955 from 8bitDream/gradle (diff)
downloadyuzu-ea8d5ef5e81861e013b5c58189faeffe7d3a6f18.tar.gz
yuzu-ea8d5ef5e81861e013b5c58189faeffe7d3a6f18.tar.xz
yuzu-ea8d5ef5e81861e013b5c58189faeffe7d3a6f18.zip
sink_stream: Resolve heap buffer corruption due to out of bounds write
Also, remove the use of ScratchBuffer when upmixing, as other channels may not be initialized with zeroed out data.
Diffstat (limited to 'src/audio_core/sink')
-rw-r--r--src/audio_core/sink/sink_stream.cpp34
-rw-r--r--src/audio_core/sink/sink_stream.h3
2 files changed, 20 insertions, 17 deletions
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp
index 404dcd0e9..6081352a2 100644
--- a/src/audio_core/sink/sink_stream.cpp
+++ b/src/audio_core/sink/sink_stream.cpp
@@ -12,6 +12,7 @@
12#include "audio_core/sink/sink_stream.h" 12#include "audio_core/sink/sink_stream.h"
13#include "common/common_types.h" 13#include "common/common_types.h"
14#include "common/fixed_point.h" 14#include "common/fixed_point.h"
15#include "common/scope_exit.h"
15#include "common/settings.h" 16#include "common/settings.h"
16#include "core/core.h" 17#include "core/core.h"
17#include "core/core_timing.h" 18#include "core/core_timing.h"
@@ -19,9 +20,12 @@
19namespace AudioCore::Sink { 20namespace AudioCore::Sink {
20 21
21void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { 22void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
22 if (type == StreamType::In) { 23 SCOPE_EXIT({
23 queue.enqueue(buffer); 24 queue.enqueue(buffer);
24 queued_buffers++; 25 ++queued_buffers;
26 });
27
28 if (type == StreamType::In) {
25 return; 29 return;
26 } 30 }
27 31
@@ -66,16 +70,17 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
66 static_cast<s16>(std::clamp(right_sample, min, max)); 70 static_cast<s16>(std::clamp(right_sample, min, max));
67 } 71 }
68 72
69 samples = samples.subspan(0, samples.size() / system_channels * device_channels); 73 samples_buffer.Push(samples.subspan(0, samples.size() / system_channels * device_channels));
74 return;
75 }
70 76
71 } else if (system_channels == 2 && device_channels == 6) { 77 if (system_channels == 2 && device_channels == 6) {
72 // We need moar samples! Not all games will provide 6 channel audio. 78 // We need moar samples! Not all games will provide 6 channel audio.
73 // TODO: Implement some upmixing here. Currently just passthrough, with other 79 // TODO: Implement some upmixing here. Currently just passthrough, with other
74 // channels left as silence. 80 // channels left as silence.
75 auto new_size = samples.size() / system_channels * device_channels; 81 std::vector<s16> new_samples(samples.size() / system_channels * device_channels);
76 tmp_samples.resize_destructive(new_size);
77 82
78 for (u32 read_index = 0, write_index = 0; read_index < new_size; 83 for (u32 read_index = 0, write_index = 0; read_index < samples.size();
79 read_index += system_channels, write_index += device_channels) { 84 read_index += system_channels, write_index += device_channels) {
80 const auto left_sample{static_cast<s16>(std::clamp( 85 const auto left_sample{static_cast<s16>(std::clamp(
81 static_cast<s32>( 86 static_cast<s32>(
@@ -83,7 +88,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
83 volume), 88 volume),
84 min, max))}; 89 min, max))};
85 90
86 tmp_samples[write_index + static_cast<u32>(Channels::FrontLeft)] = left_sample; 91 new_samples[write_index + static_cast<u32>(Channels::FrontLeft)] = left_sample;
87 92
88 const auto right_sample{static_cast<s16>(std::clamp( 93 const auto right_sample{static_cast<s16>(std::clamp(
89 static_cast<s32>( 94 static_cast<s32>(
@@ -91,20 +96,21 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
91 volume), 96 volume),
92 min, max))}; 97 min, max))};
93 98
94 tmp_samples[write_index + static_cast<u32>(Channels::FrontRight)] = right_sample; 99 new_samples[write_index + static_cast<u32>(Channels::FrontRight)] = right_sample;
95 } 100 }
96 samples = std::span<s16>(tmp_samples);
97 101
98 } else if (volume != 1.0f) { 102 samples_buffer.Push(new_samples);
99 for (u32 i = 0; i < samples.size(); i++) { 103 return;
104 }
105
106 if (volume != 1.0f) {
107 for (u32 i = 0; i < samples.size(); ++i) {
100 samples[i] = static_cast<s16>( 108 samples[i] = static_cast<s16>(
101 std::clamp(static_cast<s32>(static_cast<f32>(samples[i]) * volume), min, max)); 109 std::clamp(static_cast<s32>(static_cast<f32>(samples[i]) * volume), min, max));
102 } 110 }
103 } 111 }
104 112
105 samples_buffer.Push(samples); 113 samples_buffer.Push(samples);
106 queue.enqueue(buffer);
107 queued_buffers++;
108} 114}
109 115
110std::vector<s16> SinkStream::ReleaseBuffer(u64 num_samples) { 116std::vector<s16> SinkStream::ReleaseBuffer(u64 num_samples) {
diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h
index 98d72ace1..6a4996ca3 100644
--- a/src/audio_core/sink/sink_stream.h
+++ b/src/audio_core/sink/sink_stream.h
@@ -16,7 +16,6 @@
16#include "common/polyfill_thread.h" 16#include "common/polyfill_thread.h"
17#include "common/reader_writer_queue.h" 17#include "common/reader_writer_queue.h"
18#include "common/ring_buffer.h" 18#include "common/ring_buffer.h"
19#include "common/scratch_buffer.h"
20#include "common/thread.h" 19#include "common/thread.h"
21 20
22namespace Core { 21namespace Core {
@@ -256,8 +255,6 @@ private:
256 /// Signalled when ring buffer entries are consumed 255 /// Signalled when ring buffer entries are consumed
257 std::condition_variable_any release_cv; 256 std::condition_variable_any release_cv;
258 std::mutex release_mutex; 257 std::mutex release_mutex;
259 /// Temporary buffer for appending samples when upmixing
260 Common::ScratchBuffer<s16> tmp_samples{};
261}; 258};
262 259
263using SinkStreamPtr = std::unique_ptr<SinkStream>; 260using SinkStreamPtr = std::unique_ptr<SinkStream>;