diff --git a/src/audio_core/renderer/effect/biquad_filter.cpp b/src/audio_core/renderer/effect/biquad_filter.cpp index 08161d840..c1d931ac6 100644 --- a/src/audio_core/renderer/effect/biquad_filter.cpp +++ b/src/audio_core/renderer/effect/biquad_filter.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include + #include "audio_core/renderer/effect/biquad_filter.h" namespace AudioCore::Renderer { @@ -11,9 +13,45 @@ void BiquadFilterInfo::Update(BehaviorInfo::ErrorInfo& error_info, auto params{reinterpret_cast(parameter.data())}; std::memcpy(params, in_specific, sizeof(ParameterVersion1)); + + // Check for corrupted parameters - if detected, disable the effect to prevent audio issues + bool parameters_valid = true; + + // Validate channel_count + if (params->channel_count < 0 || params->channel_count > MaxChannels) { + LOG_WARNING(Service_Audio, "BiquadFilterInfo: Invalid channel_count {}, disabling effect", + params->channel_count); + parameters_valid = false; + } + + // Validate parameter state + if (static_cast(params->state) > static_cast(EffectInfoBase::ParameterState::Updated)) { + LOG_WARNING(Service_Audio, "BiquadFilterInfo: Invalid parameter state {}, disabling effect", + static_cast(params->state)); + parameters_valid = false; + } + + // Validate input/output buffer indices + for (s8 i = 0; i < MaxChannels && parameters_valid; i++) { + // Negative values are allowed (indicate unused channels), but check for out-of-range values + if (params->inputs[i] < -1 || params->inputs[i] >= static_cast(MaxChannels * 2)) { + LOG_WARNING(Service_Audio, "BiquadFilterInfo: Invalid input buffer index {} for channel {}, disabling effect", + params->inputs[i], i); + parameters_valid = false; + break; + } + if (params->outputs[i] < -1 || params->outputs[i] >= static_cast(MaxChannels * 2)) { + LOG_WARNING(Service_Audio, "BiquadFilterInfo: Invalid output buffer index {} for channel {}, disabling effect", + params->outputs[i], i); + parameters_valid = false; + break; + } + } + mix_id = in_params.mix_id; process_order = in_params.process_order; - enabled = in_params.enabled; + // Disable effect if parameters are corrupted to prevent audio issues + enabled = in_params.enabled && parameters_valid; error_info.error_code = ResultSuccess; error_info.address = CpuAddr(0); @@ -25,9 +63,40 @@ void BiquadFilterInfo::Update(BehaviorInfo::ErrorInfo& error_info, auto params{reinterpret_cast(parameter.data())}; std::memcpy(params, in_specific, sizeof(ParameterVersion2)); + + // Validate parameters - ParameterVersion2 uses native float coefficients and has an enable field + bool parameters_valid = true; + + // Validate channel_count using the standard validation function + if (!IsChannelCountValid(static_cast(params->channel_count))) { + LOG_WARNING(Service_Audio, "BiquadFilterInfo: Invalid channel_count {}, disabling effect", + params->channel_count); + parameters_valid = false; + } + + // Validate input/output buffer indices only for active channels + const s8 active_channels = parameters_valid ? params->channel_count : 0; + for (s8 i = 0; i < active_channels && parameters_valid; i++) { + // Negative values are allowed (indicate unused channels), but check for out-of-range values + if (params->inputs[i] < -1 || params->inputs[i] >= static_cast(MaxChannels * 2)) { + LOG_WARNING(Service_Audio, "BiquadFilterInfo: Invalid input buffer index {} for channel {}, disabling effect", + params->inputs[i], i); + parameters_valid = false; + break; + } + if (params->outputs[i] < -1 || params->outputs[i] >= static_cast(MaxChannels * 2)) { + LOG_WARNING(Service_Audio, "BiquadFilterInfo: Invalid output buffer index {} for channel {}, disabling effect", + params->outputs[i], i); + parameters_valid = false; + break; + } + } + mix_id = in_params.mix_id; process_order = in_params.process_order; - enabled = in_params.enabled; + // ParameterVersion2 has its own enable field at the parameter level + // Combine with in_params.enabled and parameter validation + enabled = in_params.enabled && parameters_valid && params->enable; error_info.error_code = ResultSuccess; error_info.address = CpuAddr(0);