static int alac_set_info(ALACContext *alac) { const unsigned char *ptr = alac->avctx->extradata; ptr += 4; /* size */ ptr += 4; /* alac */ ptr += 4; /* 0 ? */ if(AV_RB32(ptr) >= UINT_MAX/4){ av_log(alac->avctx, AV_LOG_ERROR, "setinfo_max_samples_per_frame too large\n"); return -1; } /* buffer size / 2 ? */ alac->setinfo_max_samples_per_frame = bytestream_get_be32(&ptr); alac->setinfo_7a = *ptr++; alac->setinfo_sample_size = *ptr++; alac->setinfo_rice_historymult = *ptr++; alac->setinfo_rice_initialhistory = *ptr++; alac->setinfo_rice_kmodifier = *ptr++; /* channels? */ alac->setinfo_7f = *ptr++; alac->setinfo_80 = bytestream_get_be16(&ptr); /* max coded frame size */ alac->setinfo_82 = bytestream_get_be32(&ptr); /* bitrate ? */ alac->setinfo_86 = bytestream_get_be32(&ptr); /* samplerate */ alac->setinfo_8a_rate = bytestream_get_be32(&ptr); allocate_buffers(alac); return 0; }
static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end) { unsigned int size; char buf[1024]; if (data >= data_end) return; switch (*data++) { case AMF_DATA_TYPE_NUMBER: av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2dbl(AV_RB64(data))); return; case AMF_DATA_TYPE_BOOL: av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data); return; case AMF_DATA_TYPE_STRING: case AMF_DATA_TYPE_LONG_STRING: if (data[-1] == AMF_DATA_TYPE_STRING) { size = bytestream_get_be16(&data); } else { size = bytestream_get_be32(&data); } size = FFMIN(size, sizeof(buf) - 1); memcpy(buf, data, size); buf[size] = 0; av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf); return; case AMF_DATA_TYPE_NULL: av_log(ctx, AV_LOG_DEBUG, " NULL\n"); return; case AMF_DATA_TYPE_ARRAY: data += 4; case AMF_DATA_TYPE_OBJECT: av_log(ctx, AV_LOG_DEBUG, " {\n"); for (;;) { int t; size = bytestream_get_be16(&data); av_strlcpy(buf, data, FFMIN(sizeof(buf), size + 1)); if (!size) { av_log(ctx, AV_LOG_DEBUG, " }\n"); data++; break; } if (size >= data_end - data) return; data += size; av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); ff_amf_tag_contents(ctx, data, data_end); t = ff_amf_tag_size(data, data_end); if (t < 0 || t >= data_end - data) return; data += t; } return; case AMF_DATA_TYPE_OBJECT_END: av_log(ctx, AV_LOG_DEBUG, " }\n"); return; default: return; } }
/** * Read a run length encoded SGI image. * @param out_buf output buffer * @param in_buf input buffer * @param in_end end of input buffer * @param s the current image state * @return 0 if no error, else return error number. */ static int read_rle_sgi(unsigned char* out_buf, const uint8_t *in_buf, const uint8_t *in_end, SgiState* s) { uint8_t *dest_row; unsigned int len = s->height * s->depth * 4; const uint8_t *start_table = in_buf; unsigned int y, z; unsigned int start_offset; /* size of RLE offset and length tables */ if(len * 2 > in_end - in_buf) { return AVERROR_INVALIDDATA; } in_buf -= SGI_HEADER_SIZE; for (z = 0; z < s->depth; z++) { dest_row = out_buf; for (y = 0; y < s->height; y++) { dest_row -= s->linesize; start_offset = bytestream_get_be32(&start_table); if(start_offset > in_end - in_buf) { return AVERROR_INVALIDDATA; } if (expand_rle_row(in_buf + start_offset, in_end, dest_row + z, dest_row + FFABS(s->linesize), s->depth) != s->width) return AVERROR_INVALIDDATA; } } return 0; }
int ff_amf_match_string(const uint8_t *data, int size, const char *str) { int len = strlen(str); int amf_len, type; if (size < 1) return 0; type = *data++; if (type != AMF_DATA_TYPE_LONG_STRING && type != AMF_DATA_TYPE_STRING) return 0; if (type == AMF_DATA_TYPE_LONG_STRING) { if ((size -= 4 + 1) < 0) return 0; amf_len = bytestream_get_be32(&data); } else { if ((size -= 2 + 1) < 0) return 0; amf_len = bytestream_get_be16(&data); } if (amf_len > size) return 0; if (amf_len != len) return 0; return !memcmp(data, str, len); }
int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end) { const uint8_t *base = data; AMFDataType type; unsigned nb = -1; int parse_key = 1; if (data >= data_end) return -1; switch ((type = *data++)) { case AMF_DATA_TYPE_NUMBER: return 9; case AMF_DATA_TYPE_BOOL: return 2; case AMF_DATA_TYPE_STRING: return 3 + AV_RB16(data); case AMF_DATA_TYPE_LONG_STRING: return 5 + AV_RB32(data); case AMF_DATA_TYPE_NULL: return 1; case AMF_DATA_TYPE_ARRAY: parse_key = 0; case AMF_DATA_TYPE_MIXEDARRAY: nb = bytestream_get_be32(&data); case AMF_DATA_TYPE_OBJECT: while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) { int t; if (parse_key) { int size = bytestream_get_be16(&data); if (!size) { data++; break; } if (size < 0 || size >= data_end - data) return -1; data += size; } t = ff_amf_tag_size(data, data_end); if (t < 0 || t >= data_end - data) return -1; data += t; } return data - base; case AMF_DATA_TYPE_OBJECT_END: return 1; default: return -1; } }
/** * Cook initialization * * @param avctx pointer to the AVCodecContext */ static av_cold int cook_decode_init(AVCodecContext *avctx) { COOKContext *q = avctx->priv_data; const uint8_t *edata_ptr = avctx->extradata; const uint8_t *edata_ptr_end = edata_ptr + avctx->extradata_size; int extradata_size = avctx->extradata_size; int s = 0; unsigned int channel_mask = 0; int samples_per_frame = 0; int ret; q->avctx = avctx; /* Take care of the codec specific extradata. */ if (extradata_size <= 0) { av_log(avctx, AV_LOG_ERROR, "Necessary extradata missing!\n"); return AVERROR_INVALIDDATA; } av_log(avctx, AV_LOG_DEBUG, "codecdata_length=%d\n", avctx->extradata_size); /* Take data from the AVCodecContext (RM container). */ if (!avctx->channels) { av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); return AVERROR_INVALIDDATA; } /* Initialize RNG. */ av_lfg_init(&q->random_state, 0); ff_dsputil_init(&q->dsp, avctx); while (edata_ptr < edata_ptr_end) { /* 8 for mono, 16 for stereo, ? for multichannel Swap to right endianness so we don't need to care later on. */ if (extradata_size >= 8) { q->subpacket[s].cookversion = bytestream_get_be32(&edata_ptr); samples_per_frame = bytestream_get_be16(&edata_ptr); q->subpacket[s].subbands = bytestream_get_be16(&edata_ptr); extradata_size -= 8; } if (extradata_size >= 8) { bytestream_get_be32(&edata_ptr); // Unknown unused q->subpacket[s].js_subband_start = bytestream_get_be16(&edata_ptr); q->subpacket[s].js_vlc_bits = bytestream_get_be16(&edata_ptr); extradata_size -= 8; } /* Initialize extradata related variables. */ q->subpacket[s].samples_per_channel = samples_per_frame / avctx->channels; q->subpacket[s].bits_per_subpacket = avctx->block_align * 8; /* Initialize default data states. */ q->subpacket[s].log2_numvector_size = 5; q->subpacket[s].total_subbands = q->subpacket[s].subbands; q->subpacket[s].num_channels = 1; /* Initialize version-dependent variables */ av_log(avctx, AV_LOG_DEBUG, "subpacket[%i].cookversion=%x\n", s, q->subpacket[s].cookversion); q->subpacket[s].joint_stereo = 0; switch (q->subpacket[s].cookversion) { case MONO: if (avctx->channels != 1) { av_log_ask_for_sample(avctx, "Container channels != 1.\n"); return AVERROR_PATCHWELCOME; } av_log(avctx, AV_LOG_DEBUG, "MONO\n"); break; case STEREO: if (avctx->channels != 1) { q->subpacket[s].bits_per_subpdiv = 1; q->subpacket[s].num_channels = 2; } av_log(avctx, AV_LOG_DEBUG, "STEREO\n"); break; case JOINT_STEREO: if (avctx->channels != 2) { av_log_ask_for_sample(avctx, "Container channels != 2.\n"); return AVERROR_PATCHWELCOME; } av_log(avctx, AV_LOG_DEBUG, "JOINT_STEREO\n"); if (avctx->extradata_size >= 16) { q->subpacket[s].total_subbands = q->subpacket[s].subbands + q->subpacket[s].js_subband_start; q->subpacket[s].joint_stereo = 1; q->subpacket[s].num_channels = 2; } if (q->subpacket[s].samples_per_channel > 256) { q->subpacket[s].log2_numvector_size = 6; } if (q->subpacket[s].samples_per_channel > 512) { q->subpacket[s].log2_numvector_size = 7; } break; case MC_COOK: av_log(avctx, AV_LOG_DEBUG, "MULTI_CHANNEL\n"); if (extradata_size >= 4) channel_mask |= q->subpacket[s].channel_mask = bytestream_get_be32(&edata_ptr); if (av_get_channel_layout_nb_channels(q->subpacket[s].channel_mask) > 1) { q->subpacket[s].total_subbands = q->subpacket[s].subbands + q->subpacket[s].js_subband_start; q->subpacket[s].joint_stereo = 1; q->subpacket[s].num_channels = 2; q->subpacket[s].samples_per_channel = samples_per_frame >> 1; if (q->subpacket[s].samples_per_channel > 256) { q->subpacket[s].log2_numvector_size = 6; } if (q->subpacket[s].samples_per_channel > 512) { q->subpacket[s].log2_numvector_size = 7; } } else q->subpacket[s].samples_per_channel = samples_per_frame; break; default: av_log_ask_for_sample(avctx, "Unknown Cook version.\n"); return AVERROR_PATCHWELCOME; }
static int cook_decode_init(AVCodecContext *avctx) { COOKContext *q = avctx->priv_data; const uint8_t *edata_ptr = avctx->extradata; /* Take care of the codec specific extradata. */ if (avctx->extradata_size <= 0) { av_log(avctx,AV_LOG_ERROR,"Necessary extradata missing!\n"); return -1; } else { /* 8 for mono, 16 for stereo, ? for multichannel Swap to right endianness so we don't need to care later on. */ av_log(avctx,AV_LOG_DEBUG,"codecdata_length=%d\n",avctx->extradata_size); if (avctx->extradata_size >= 8){ q->cookversion = bytestream_get_be32(&edata_ptr); q->samples_per_frame = bytestream_get_be16(&edata_ptr); q->subbands = bytestream_get_be16(&edata_ptr); } if (avctx->extradata_size >= 16){ bytestream_get_be32(&edata_ptr); //Unknown unused q->js_subband_start = bytestream_get_be16(&edata_ptr); q->js_vlc_bits = bytestream_get_be16(&edata_ptr); } } /* Take data from the AVCodecContext (RM container). */ q->sample_rate = avctx->sample_rate; q->nb_channels = avctx->channels; q->bit_rate = avctx->bit_rate; /* Initialize RNG. */ av_init_random(1, &q->random_state); /* Initialize extradata related variables. */ q->samples_per_channel = q->samples_per_frame / q->nb_channels; q->bits_per_subpacket = avctx->block_align * 8; /* Initialize default data states. */ q->log2_numvector_size = 5; q->total_subbands = q->subbands; /* Initialize version-dependent variables */ av_log(NULL,AV_LOG_DEBUG,"q->cookversion=%x\n",q->cookversion); q->joint_stereo = 0; switch (q->cookversion) { case MONO: if (q->nb_channels != 1) { av_log(avctx,AV_LOG_ERROR,"Container channels != 1, report sample!\n"); return -1; } av_log(avctx,AV_LOG_DEBUG,"MONO\n"); break; case STEREO: if (q->nb_channels != 1) { q->bits_per_subpacket = q->bits_per_subpacket/2; } av_log(avctx,AV_LOG_DEBUG,"STEREO\n"); break; case JOINT_STEREO: if (q->nb_channels != 2) { av_log(avctx,AV_LOG_ERROR,"Container channels != 2, report sample!\n"); return -1; } av_log(avctx,AV_LOG_DEBUG,"JOINT_STEREO\n"); if (avctx->extradata_size >= 16){ q->total_subbands = q->subbands + q->js_subband_start; q->joint_stereo = 1; } if (q->samples_per_channel > 256) { q->log2_numvector_size = 6; } if (q->samples_per_channel > 512) { q->log2_numvector_size = 7; } break; case MC_COOK: av_log(avctx,AV_LOG_ERROR,"MC_COOK not supported!\n"); return -1; break; default: av_log(avctx,AV_LOG_ERROR,"Unknown Cook version, report sample!\n"); return -1; break; } /* Initialize variable relations */ q->numvector_size = (1 << q->log2_numvector_size); /* Generate tables */ init_pow2table(); init_gain_table(q); init_cplscales_table(q); if (init_cook_vlc_tables(q) != 0) return -1; if(avctx->block_align >= UINT_MAX/2) return -1; /* Pad the databuffer with: DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(), FF_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */ if (q->nb_channels==2 && q->joint_stereo==0) { q->decoded_bytes_buffer = av_mallocz(avctx->block_align/2 + DECODE_BYTES_PAD2(avctx->block_align/2) + FF_INPUT_BUFFER_PADDING_SIZE); } else { q->decoded_bytes_buffer = av_mallocz(avctx->block_align + DECODE_BYTES_PAD1(avctx->block_align) + FF_INPUT_BUFFER_PADDING_SIZE); } if (q->decoded_bytes_buffer == NULL) return -1; q->gains1.now = q->gain_1; q->gains1.previous = q->gain_2; q->gains2.now = q->gain_3; q->gains2.previous = q->gain_4; /* Initialize transform. */ if ( init_cook_mlt(q) != 0 ) return -1; /* Initialize COOK signal arithmetic handling */ if (1) { q->scalar_dequant = scalar_dequant_float; q->decouple = decouple_float; q->imlt_window = imlt_window_float; q->interpolate = interpolate_float; q->saturate_output = saturate_output_float; } /* Try to catch some obviously faulty streams, othervise it might be exploitable */ if (q->total_subbands > 53) { av_log(avctx,AV_LOG_ERROR,"total_subbands > 53, report sample!\n"); return -1; } if (q->subbands > 50) { av_log(avctx,AV_LOG_ERROR,"subbands > 50, report sample!\n"); return -1; } if ((q->samples_per_channel == 256) || (q->samples_per_channel == 512) || (q->samples_per_channel == 1024)) { } else { av_log(avctx,AV_LOG_ERROR,"unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel); return -1; } if ((q->js_vlc_bits > 6) || (q->js_vlc_bits < 0)) { av_log(avctx,AV_LOG_ERROR,"q->js_vlc_bits = %d, only >= 0 and <= 6 allowed!\n",q->js_vlc_bits); return -1; } avctx->sample_fmt = SAMPLE_FMT_S16; #ifdef COOKDEBUG dump_cook_context(q); #endif return 0; }
static void amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end) { unsigned int size, nb = -1; char buf[1024]; AMFDataType type; int parse_key = 1; if (data >= data_end) return; switch ((type = *data++)) { case AMF_DATA_TYPE_NUMBER: av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2double(AV_RB64(data))); return; case AMF_DATA_TYPE_BOOL: av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data); return; case AMF_DATA_TYPE_STRING: case AMF_DATA_TYPE_LONG_STRING: if (type == AMF_DATA_TYPE_STRING) { size = bytestream_get_be16(&data); } else { size = bytestream_get_be32(&data); } size = FFMIN(size, sizeof(buf) - 1); memcpy(buf, data, size); buf[size] = 0; av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf); return; case AMF_DATA_TYPE_NULL: av_log(ctx, AV_LOG_DEBUG, " NULL\n"); return; case AMF_DATA_TYPE_ARRAY: parse_key = 0; case AMF_DATA_TYPE_MIXEDARRAY: nb = bytestream_get_be32(&data); case AMF_DATA_TYPE_OBJECT: av_log(ctx, AV_LOG_DEBUG, " {\n"); while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) { int t; if (parse_key) { size = bytestream_get_be16(&data); size = FFMIN(size, sizeof(buf) - 1); if (!size) { av_log(ctx, AV_LOG_DEBUG, " }\n"); data++; break; } memcpy(buf, data, size); buf[size] = 0; if (size >= data_end - data) return; data += size; av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); } amf_tag_contents(ctx, data, data_end); t = ff_amf_tag_size(data, data_end); if (t < 0 || t >= data_end - data) return; data += t; } return; case AMF_DATA_TYPE_OBJECT_END: av_log(ctx, AV_LOG_DEBUG, " }\n"); return; default: return; } }