Make alac check allocated buffer size and make player check and discard bad audio frames.
This commit is contained in:
@@ -710,6 +710,7 @@ void alac_decode_frame(alac_file *alac,
|
||||
unsigned char *inbuffer,
|
||||
void *outbuffer, int *outputsize)
|
||||
{
|
||||
int outbuffer_allocation_size = *outputsize; // initial value
|
||||
int channels;
|
||||
int32_t outputsamples = alac->setinfo_max_samples_per_frame;
|
||||
|
||||
@@ -720,6 +721,11 @@ void alac_decode_frame(alac_file *alac,
|
||||
channels = readbits(alac, 3);
|
||||
|
||||
*outputsize = outputsamples * alac->bytespersample;
|
||||
if (*outputsize>outbuffer_allocation_size) {
|
||||
fprintf(stderr, "FIXME: Not enough space if the output buffer for audio frame - E1.\n");
|
||||
*outputsize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(channels)
|
||||
{
|
||||
@@ -751,6 +757,12 @@ void alac_decode_frame(alac_file *alac,
|
||||
* as a 32bit integer */
|
||||
outputsamples = readbits(alac, 32);
|
||||
*outputsize = outputsamples * alac->bytespersample;
|
||||
if (*outputsize>outbuffer_allocation_size) {
|
||||
fprintf(stderr, "FIXME: Not enough space if the output buffer for audio frame - E2.\n");
|
||||
*outputsize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
readsamplesize = alac->setinfo_sample_size - (uncompressed_bytes * 8);
|
||||
@@ -928,6 +940,11 @@ void alac_decode_frame(alac_file *alac,
|
||||
* as a 32bit integer */
|
||||
outputsamples = readbits(alac, 32);
|
||||
*outputsize = outputsamples * alac->bytespersample;
|
||||
if (*outputsize>outbuffer_allocation_size) {
|
||||
fprintf(stderr, "FIXME: Not enough space if the output buffer for audio frame - E3.\n");
|
||||
*outputsize = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
readsamplesize = alac->setinfo_sample_size - (uncompressed_bytes * 8) + 1;
|
||||
|
||||
@@ -221,11 +221,12 @@ static inline int seq32_order(uint32_t a, uint32_t b) {
|
||||
return (C & 0x80000000) == 0;
|
||||
}
|
||||
|
||||
static void alac_decode(short *dest, uint8_t *buf, int len) {
|
||||
static int alac_decode(short *dest, uint8_t *buf, int len) {
|
||||
unsigned char packet[MAX_PACKET];
|
||||
unsigned char packetp[MAX_PACKET];
|
||||
assert(len <= MAX_PACKET);
|
||||
int outsize;
|
||||
int reply = 0; //everything okay
|
||||
int outsize=FRAME_BYTES(frame_size); // the size it should be
|
||||
|
||||
if (encrypted) {
|
||||
unsigned char iv[16];
|
||||
@@ -244,11 +245,13 @@ static void alac_decode(short *dest, uint8_t *buf, int len) {
|
||||
}
|
||||
if (outsize!=FRAME_BYTES(frame_size)) {
|
||||
if(outsize<FRAME_BYTES(frame_size)) {
|
||||
debug(1,"Output from alac_decode is smaller than expected. Encrypted = %d.",encrypted);
|
||||
debug(2,"Output from alac_decode is smaller than expected. Encrypted = %d.",encrypted);
|
||||
} else {
|
||||
debug(1,"OUtput from alac_decode larger than expected -- truncated, but buffer overflow possible! Encrypted = %d.",encrypted);
|
||||
debug(2,"Output from alac_decode larger than expected -- truncated, but buffer overflow possible! Encrypted = %d.",encrypted);
|
||||
}
|
||||
reply = -1; // output frame is the wrong size
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
static int init_decoder(int32_t fmtp[12]) {
|
||||
@@ -363,10 +366,16 @@ void player_put_packet(seq_t seqno, uint32_t timestamp, uint8_t *data, int len)
|
||||
// pthread_mutex_unlock(&ab_mutex);
|
||||
|
||||
if (abuf) {
|
||||
alac_decode(abuf->data, data, len);
|
||||
abuf->ready = 1;
|
||||
abuf->timestamp = timestamp;
|
||||
abuf->sequence_number = seqno;
|
||||
if (alac_decode(abuf->data, data, len)==0) {
|
||||
abuf->ready = 1;
|
||||
abuf->timestamp = timestamp;
|
||||
abuf->sequence_number = seqno;
|
||||
} else {
|
||||
debug(1,"Bad audio packet detected and discarded.");
|
||||
abuf->ready = 0;
|
||||
abuf->timestamp = 0;
|
||||
abuf->sequence_number = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// pthread_mutex_lock(&ab_mutex);
|
||||
@@ -893,13 +902,12 @@ typedef struct stats { // statistics for running averages
|
||||
} stats_t;
|
||||
|
||||
static void *player_thread_func(void *arg) {
|
||||
struct inter_threads_record itr;
|
||||
itr.please_stop = 0; // this will be used to signal to the subsidiary threads
|
||||
int threads_stop = 0;
|
||||
// create and start the timing, control and audio receiver threads
|
||||
pthread_t rtp_audio_thread, rtp_control_thread, rtp_timing_thread;
|
||||
pthread_create(&rtp_audio_thread, NULL, &rtp_audio_receiver, (void *)&itr);
|
||||
pthread_create(&rtp_control_thread, NULL, &rtp_control_receiver, (void *)&itr);
|
||||
pthread_create(&rtp_timing_thread, NULL, &rtp_timing_receiver, (void *)&itr);
|
||||
pthread_create(&rtp_audio_thread, NULL, &rtp_audio_receiver, (void *)&threads_stop);
|
||||
pthread_create(&rtp_control_thread, NULL, &rtp_control_receiver, (void *)&threads_stop);
|
||||
pthread_create(&rtp_timing_thread, NULL, &rtp_timing_receiver, (void *)&threads_stop);
|
||||
|
||||
session_corrections = 0;
|
||||
play_segment_reference_frame = 0; // zero signals that we are not in a play segment
|
||||
@@ -1233,7 +1241,7 @@ static void *player_thread_func(void *arg) {
|
||||
free(silence);
|
||||
debug(1,"Shut down audio, control and timing threads");
|
||||
// usleep(1000000);
|
||||
itr.please_stop = 1;
|
||||
threads_stop = 1;
|
||||
pthread_kill(rtp_audio_thread, SIGUSR1);
|
||||
pthread_kill(rtp_control_thread, SIGUSR1);
|
||||
pthread_kill(rtp_timing_thread, SIGUSR1);
|
||||
|
||||
Reference in New Issue
Block a user