mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-20 04:18:26 +01:00
Demux: A new state WEBP_DEMUX_PARSE_ERROR
WebPDemuxPartial() returns NULL for both of the following cases: - There was a parsing error. - It doesn't have enough data to start parsing. Now, one can differentiate between these two cases by checking the value of 'state' returned by WebPDemuxPartial(). Change-Id: Ia2377f0c516b3fcfae475c0662c4932d2eddcd0b
This commit is contained in:
parent
8dcae8b3cf
commit
1693fd9b16
@ -390,20 +390,20 @@ static int StoreChunk(WebPDemuxer* const dmux,
|
||||
// -----------------------------------------------------------------------------
|
||||
// Primary chunk parsing
|
||||
|
||||
static int ReadHeader(MemBuffer* const mem) {
|
||||
static ParseStatus ReadHeader(MemBuffer* const mem) {
|
||||
const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE;
|
||||
uint32_t riff_size;
|
||||
|
||||
// Basic file level validation.
|
||||
if (MemDataSize(mem) < min_size) return 0;
|
||||
if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
|
||||
if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) ||
|
||||
memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) {
|
||||
return 0;
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
|
||||
riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE);
|
||||
if (riff_size < CHUNK_HEADER_SIZE) return 0;
|
||||
if (riff_size > MAX_CHUNK_PAYLOAD) return 0;
|
||||
if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR;
|
||||
if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
|
||||
|
||||
// There's no point in reading past the end of the RIFF chunk
|
||||
mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE;
|
||||
@ -412,7 +412,7 @@ static int ReadHeader(MemBuffer* const mem) {
|
||||
}
|
||||
|
||||
Skip(mem, RIFF_HEADER_SIZE);
|
||||
return 1;
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
|
||||
@ -692,11 +692,20 @@ WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial,
|
||||
MemBuffer mem;
|
||||
WebPDemuxer* dmux;
|
||||
|
||||
if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR;
|
||||
|
||||
if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL;
|
||||
if (data == NULL || data->bytes == NULL || data->size == 0) return NULL;
|
||||
|
||||
if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL;
|
||||
if (!ReadHeader(&mem)) return NULL;
|
||||
status = ReadHeader(&mem);
|
||||
if (status != PARSE_OK) {
|
||||
if (state != NULL) {
|
||||
*state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER
|
||||
: WEBP_DEMUX_PARSE_ERROR;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
partial = (mem.buf_size_ < mem.riff_end_);
|
||||
if (!allow_partial && partial) return NULL;
|
||||
@ -705,16 +714,18 @@ WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial,
|
||||
if (dmux == NULL) return NULL;
|
||||
InitDemux(dmux, &mem);
|
||||
|
||||
status = PARSE_ERROR;
|
||||
for (parser = kMasterChunks; parser->parse != NULL; ++parser) {
|
||||
if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) {
|
||||
status = parser->parse(dmux);
|
||||
if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE;
|
||||
if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR;
|
||||
if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR;
|
||||
if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (state) *state = dmux->state_;
|
||||
if (state != NULL) *state = dmux->state_;
|
||||
|
||||
if (status == PARSE_ERROR) {
|
||||
WebPDemuxDelete(dmux);
|
||||
|
@ -73,9 +73,11 @@ WEBP_EXTERN(int) WebPGetDemuxVersion(void);
|
||||
// Life of a Demux object
|
||||
|
||||
typedef enum WebPDemuxState {
|
||||
WEBP_DEMUX_PARSING_HEADER, // Not enough data to parse full header.
|
||||
WEBP_DEMUX_PARSED_HEADER, // Header parsing complete, data may be available.
|
||||
WEBP_DEMUX_DONE // Entire file has been parsed.
|
||||
WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing.
|
||||
WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header.
|
||||
WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete,
|
||||
// data may be available.
|
||||
WEBP_DEMUX_DONE = 2 // Entire file has been parsed.
|
||||
} WebPDemuxState;
|
||||
|
||||
// Internal, version-checked, entry point
|
||||
@ -90,7 +92,8 @@ static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
|
||||
|
||||
// Parses the possibly incomplete WebP file given by 'data'.
|
||||
// If 'state' is non-NULL it will be set to indicate the status of the demuxer.
|
||||
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
||||
// Returns NULL in case of error or if there isn't enough data to start parsing;
|
||||
// and a WebPDemuxer object on successful parse.
|
||||
static WEBP_INLINE WebPDemuxer* WebPDemuxPartial(
|
||||
const WebPData* data, WebPDemuxState* state) {
|
||||
return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION);
|
||||
|
Loading…
Reference in New Issue
Block a user