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:
Urvang Joshi 2013-07-26 14:35:46 -07:00
parent 8dcae8b3cf
commit 1693fd9b16
2 changed files with 26 additions and 12 deletions

View File

@ -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);

View File

@ -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);