mirror of
https://github.com/webmproject/libwebp.git
synced 2025-02-13 07:22:52 +01:00
WebP Decoding error handling:
- Don't allow any extended chunks (except ALPH) without RIFF & VP8X chunks. - Also, don't allow VP8X without RIFF. Change-Id: I1beba43e617ec637901aeeb93f2f484ec086a75d
This commit is contained in:
parent
fcc69923b9
commit
3ba81bbe8b
@ -245,26 +245,22 @@ static VP8StatusCode ParseVP8Header(const uint8_t** data_ptr, size_t* data_size,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Returns true if 'fourcc' matches a chunk that can appear in a 'VP8X' file.
|
|
||||||
// Image chunks are dealt with separately so are not included here.
|
|
||||||
static int IsExtendedFormatChunk(const uint8_t fourcc[4]) {
|
|
||||||
return (!memcmp(fourcc, "ALPH", TAG_SIZE) ||
|
|
||||||
!memcmp(fourcc, "FRM ", TAG_SIZE) ||
|
|
||||||
!memcmp(fourcc, "ICCP", TAG_SIZE) ||
|
|
||||||
!memcmp(fourcc, "LOOP", TAG_SIZE) ||
|
|
||||||
!memcmp(fourcc, "META", TAG_SIZE) ||
|
|
||||||
!memcmp(fourcc, "TILE", TAG_SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch 'width', 'height', 'has_alpha' and fill out 'headers' based on 'data'.
|
// Fetch 'width', 'height', 'has_alpha' and fill out 'headers' based on 'data'.
|
||||||
// All the output parameters may be NULL. If 'headers' is NULL only the minimal
|
// All the output parameters may be NULL. If 'headers' is NULL only the minimal
|
||||||
// amount will be read to fetch the remaining parameters.
|
// amount will be read to fetch the remaining parameters.
|
||||||
// If 'headers' is non-NULL this function will attempt to locate both alpha
|
// If 'headers' is non-NULL this function will attempt to locate both alpha
|
||||||
// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L).
|
// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L).
|
||||||
|
// Note: The following chunk sequences (before the raw VP8/VP8L data) are
|
||||||
|
// considered valid by this function:
|
||||||
|
// RIFF + VP8(L)
|
||||||
|
// RIFF + VP8X + (optional chunks) + VP8(L)
|
||||||
|
// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
|
||||||
|
// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
|
||||||
static VP8StatusCode ParseHeadersInternal(
|
static VP8StatusCode ParseHeadersInternal(
|
||||||
const uint8_t* data, size_t data_size,
|
const uint8_t* data, size_t data_size,
|
||||||
int* const width, int* const height, int* const has_alpha,
|
int* const width, int* const height, int* const has_alpha,
|
||||||
WebPHeaderStructure* const headers) {
|
WebPHeaderStructure* const headers) {
|
||||||
|
int found_riff = 0;
|
||||||
int found_vp8x = 0;
|
int found_vp8x = 0;
|
||||||
VP8StatusCode status;
|
VP8StatusCode status;
|
||||||
WebPHeaderStructure hdrs;
|
WebPHeaderStructure hdrs;
|
||||||
@ -281,6 +277,7 @@ static VP8StatusCode ParseHeadersInternal(
|
|||||||
if (status != VP8_STATUS_OK) {
|
if (status != VP8_STATUS_OK) {
|
||||||
return status; // Wrong RIFF header / insufficient data.
|
return status; // Wrong RIFF header / insufficient data.
|
||||||
}
|
}
|
||||||
|
found_riff = (hdrs.riff_size > 0);
|
||||||
|
|
||||||
// Skip over VP8X.
|
// Skip over VP8X.
|
||||||
{
|
{
|
||||||
@ -289,6 +286,11 @@ static VP8StatusCode ParseHeadersInternal(
|
|||||||
if (status != VP8_STATUS_OK) {
|
if (status != VP8_STATUS_OK) {
|
||||||
return status; // Wrong VP8X / insufficient data.
|
return status; // Wrong VP8X / insufficient data.
|
||||||
}
|
}
|
||||||
|
if (!found_riff && found_vp8x) {
|
||||||
|
// Note: This restriction may be removed in the future, if it becomes
|
||||||
|
// necessary to send VP8X chunk to the decoder.
|
||||||
|
return VP8_STATUS_BITSTREAM_ERROR;
|
||||||
|
}
|
||||||
if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG_BIT);
|
if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG_BIT);
|
||||||
if (found_vp8x && headers == NULL) {
|
if (found_vp8x && headers == NULL) {
|
||||||
return VP8_STATUS_OK; // Return features from VP8X header.
|
return VP8_STATUS_OK; // Return features from VP8X header.
|
||||||
@ -297,10 +299,9 @@ static VP8StatusCode ParseHeadersInternal(
|
|||||||
|
|
||||||
if (data_size < TAG_SIZE) return VP8_STATUS_NOT_ENOUGH_DATA;
|
if (data_size < TAG_SIZE) return VP8_STATUS_NOT_ENOUGH_DATA;
|
||||||
|
|
||||||
// Skip over optional chunks.
|
// Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH".
|
||||||
// If a VP8X chunk was not found look for chunks that may be contained within
|
if ((found_riff && found_vp8x) ||
|
||||||
// one to initiate the parse.
|
(!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) {
|
||||||
if (found_vp8x || IsExtendedFormatChunk(data)) {
|
|
||||||
status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size,
|
status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size,
|
||||||
&hdrs.alpha_data, &hdrs.alpha_data_size);
|
&hdrs.alpha_data, &hdrs.alpha_data_size);
|
||||||
if (status != VP8_STATUS_OK) {
|
if (status != VP8_STATUS_OK) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user