mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-18 03:26:15 +02:00
Fix crash when feeding invalid ranges into flac
This commit is contained in:
parent
1725cffc6e
commit
5d7aedeb31
5 changed files with 38 additions and 12 deletions
|
@ -28,7 +28,7 @@ using namespace std;
|
|||
namespace encoder
|
||||
{
|
||||
|
||||
// static constexpr auto LOG_TAG = "FlacEnc";
|
||||
static constexpr auto LOG_TAG = "FlacEnc";
|
||||
|
||||
FlacEncoder::FlacEncoder(const std::string& codecOptions) : Encoder(codecOptions), encoder_(nullptr), pcmBufferSize_(0), encodedSamples_(0), flacChunk_(nullptr)
|
||||
{
|
||||
|
@ -76,8 +76,8 @@ void FlacEncoder::encode(const msg::PcmChunk& chunk)
|
|||
|
||||
int samples = chunk.getSampleCount();
|
||||
int frames = chunk.getFrameCount();
|
||||
// LOG(INFO, LOG_TAG) << "payload: " << chunk->payloadSize << "\tframes: " << frames << "\tsamples: " << samples << "\tduration: " <<
|
||||
// chunk->duration<chronos::msec>().count() << "\n";
|
||||
// LOG(TRACE, LOG_TAG) << "payload: " << chunk.payloadSize << "\tframes: " << frames << "\tsamples: " << samples
|
||||
// << "\tduration: " << chunk.duration<chronos::msec>().count() << ", format: " << chunk.format.toString() << "\n";
|
||||
|
||||
if (pcmBufferSize_ < samples)
|
||||
{
|
||||
|
@ -85,24 +85,40 @@ void FlacEncoder::encode(const msg::PcmChunk& chunk)
|
|||
pcmBuffer_ = static_cast<FLAC__int32*>(realloc(pcmBuffer_, pcmBufferSize_ * sizeof(FLAC__int32)));
|
||||
}
|
||||
|
||||
auto clip = [](int32_t min, int32_t max, int32_t value) -> int32_t {
|
||||
if (value < min)
|
||||
return min;
|
||||
if (value > max)
|
||||
return max;
|
||||
return value;
|
||||
};
|
||||
|
||||
if (sampleFormat_.sampleSize() == 1)
|
||||
{
|
||||
auto* buffer = reinterpret_cast<FLAC__int8*>(chunk.payload);
|
||||
for (int i = 0; i < samples; i++)
|
||||
pcmBuffer_[i] = static_cast<FLAC__int32>(buffer[i]);
|
||||
pcmBuffer_[i] = clip(-128, 127, static_cast<FLAC__int32>(buffer[i]));
|
||||
}
|
||||
else if (sampleFormat_.sampleSize() == 2)
|
||||
{
|
||||
auto* buffer = reinterpret_cast<FLAC__int16*>(chunk.payload);
|
||||
for (int i = 0; i < samples; i++)
|
||||
pcmBuffer_[i] = static_cast<FLAC__int32>(buffer[i]);
|
||||
pcmBuffer_[i] = clip(-32768, 32767, static_cast<FLAC__int32>(buffer[i]));
|
||||
}
|
||||
else if (sampleFormat_.sampleSize() == 4)
|
||||
{
|
||||
auto* buffer = reinterpret_cast<FLAC__int32*>(chunk.payload);
|
||||
if (sampleFormat_.bits() == 24)
|
||||
{
|
||||
for (int i = 0; i < samples; i++)
|
||||
pcmBuffer_[i] = clip(-8388608, 8388607, buffer[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < samples; i++)
|
||||
pcmBuffer_[i] = buffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FLAC__stream_encoder_process_interleaved(encoder_, pcmBuffer_, frames);
|
||||
|
@ -150,20 +166,22 @@ FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder* encoder
|
|||
|
||||
void FlacEncoder::initEncoder()
|
||||
{
|
||||
int quality(2);
|
||||
int compression_level(2);
|
||||
try
|
||||
{
|
||||
quality = cpt::stoi(codecOptions_);
|
||||
compression_level = cpt::stoi(codecOptions_);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw SnapException("Invalid codec option: \"" + codecOptions_ + "\"");
|
||||
}
|
||||
if ((quality < 0) || (quality > 8))
|
||||
if ((compression_level < 0) || (compression_level > 8))
|
||||
{
|
||||
throw SnapException("compression level has to be between 0 and 8");
|
||||
}
|
||||
|
||||
LOG(INFO, LOG_TAG) << "Init - compression level: " << compression_level << "\n";
|
||||
|
||||
FLAC__bool ok = 1;
|
||||
FLAC__StreamEncoderInitStatus init_status;
|
||||
FLAC__StreamMetadata_VorbisComment_Entry entry;
|
||||
|
@ -178,7 +196,7 @@ void FlacEncoder::initEncoder()
|
|||
// latency:
|
||||
// 0-2: 1152 frames, ~26.1224ms
|
||||
// 3-8: 4096 frames, ~92.8798ms
|
||||
ok &= FLAC__stream_encoder_set_compression_level(encoder_, quality);
|
||||
ok &= FLAC__stream_encoder_set_compression_level(encoder_, compression_level);
|
||||
ok &= FLAC__stream_encoder_set_channels(encoder_, sampleFormat_.channels());
|
||||
ok &= FLAC__stream_encoder_set_bits_per_sample(encoder_, sampleFormat_.bits());
|
||||
ok &= FLAC__stream_encoder_set_sample_rate(encoder_, sampleFormat_.rate());
|
||||
|
|
|
@ -17,11 +17,13 @@
|
|||
***/
|
||||
|
||||
#include "null_encoder.hpp"
|
||||
#include "common/aixlog.hpp"
|
||||
|
||||
|
||||
namespace encoder
|
||||
{
|
||||
|
||||
static constexpr auto LOG_TAG = "NullEnc";
|
||||
|
||||
NullEncoder::NullEncoder(const std::string& codecOptions) : Encoder(codecOptions)
|
||||
{
|
||||
|
@ -37,6 +39,7 @@ void NullEncoder::encode(const msg::PcmChunk& chunk)
|
|||
|
||||
void NullEncoder::initEncoder()
|
||||
{
|
||||
LOG(INFO, LOG_TAG) << "Init\n";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -178,6 +178,8 @@ void OggEncoder::initEncoder()
|
|||
throw SnapException("compression level has to be between -0.1 and 1.0");
|
||||
}
|
||||
|
||||
LOG(INFO, LOG_TAG) << "Init - quality: " << quality << "\n";
|
||||
|
||||
/********** Encode setup ************/
|
||||
vorbis_info_init(&vi_);
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ void OpusEncoder::initEncoder()
|
|||
throw SnapException("Opus error parsing options: " + codecOptions_);
|
||||
}
|
||||
|
||||
LOG(INFO, LOG_TAG) << "Opus bitrate: " << bitrate << " bps, complexity: " << complexity << "\n";
|
||||
LOG(INFO, LOG_TAG) << "Init - bitrate: " << bitrate << " bps, complexity: " << complexity << "\n";
|
||||
|
||||
int error;
|
||||
enc_ = opus_encoder_create(sampleFormat_.rate(), sampleFormat_.channels(), OPUS_APPLICATION_RESTRICTED_LOWDELAY, &error);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
***/
|
||||
|
||||
#include "pcm_encoder.hpp"
|
||||
#include "common/aixlog.hpp"
|
||||
#include "common/endian.hpp"
|
||||
#include <memory>
|
||||
|
||||
|
@ -29,6 +30,7 @@ static constexpr auto ID_WAVE = 0x45564157;
|
|||
static constexpr auto ID_FMT = 0x20746d66;
|
||||
static constexpr auto ID_DATA = 0x61746164;
|
||||
|
||||
static constexpr auto LOG_TAG = "PcmEnc";
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -57,6 +59,7 @@ void PcmEncoder::encode(const msg::PcmChunk& chunk)
|
|||
|
||||
void PcmEncoder::initEncoder()
|
||||
{
|
||||
LOG(INFO, LOG_TAG) << "Init\n";
|
||||
headerChunk_->payloadSize = 44;
|
||||
headerChunk_->payload = static_cast<char*>(realloc(headerChunk_->payload, headerChunk_->payloadSize));
|
||||
char* payload = headerChunk_->payload;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue