mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-30 01:53:34 +01:00 
			
		
		
		
	Merge changes I48968468,I181bc736
* changes: demux: split chunk parsing from ParseVP8X demux: add a tail pointer for chunks
This commit is contained in:
		| @@ -75,6 +75,7 @@ struct WebPDemuxer { | |||||||
|   Frame* frames_; |   Frame* frames_; | ||||||
|   Frame** frames_tail_; |   Frame** frames_tail_; | ||||||
|   Chunk* chunks_;  // non-image chunks |   Chunk* chunks_;  // non-image chunks | ||||||
|  |   Chunk** chunks_tail_; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
| @@ -179,10 +180,9 @@ static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { | |||||||
| // Secondary chunk parsing | // Secondary chunk parsing | ||||||
|  |  | ||||||
| static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { | static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { | ||||||
|   Chunk** c = &dmux->chunks_; |   *dmux->chunks_tail_ = chunk; | ||||||
|   while (*c != NULL) c = &(*c)->next_; |  | ||||||
|   *c = chunk; |  | ||||||
|   chunk->next_ = NULL; |   chunk->next_ = NULL; | ||||||
|  |   dmux->chunks_tail_ = &chunk->next_; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Add a frame to the end of the list, ensuring the last frame is complete. | // Add a frame to the end of the list, ensuring the last frame is complete. | ||||||
| @@ -466,36 +466,12 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { | |||||||
|   return status; |   return status; | ||||||
| } | } | ||||||
|  |  | ||||||
| static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { | static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) { | ||||||
|  |   const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); | ||||||
|   MemBuffer* const mem = &dmux->mem_; |   MemBuffer* const mem = &dmux->mem_; | ||||||
|   int anim_chunks = 0; |   int anim_chunks = 0; | ||||||
|   uint32_t vp8x_size; |  | ||||||
|   ParseStatus status = PARSE_OK; |   ParseStatus status = PARSE_OK; | ||||||
|  |  | ||||||
|   if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; |  | ||||||
|  |  | ||||||
|   dmux->is_ext_format_ = 1; |  | ||||||
|   Skip(mem, TAG_SIZE);  // VP8X |  | ||||||
|   vp8x_size = ReadLE32(mem); |  | ||||||
|   if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; |  | ||||||
|   if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; |  | ||||||
|   vp8x_size += vp8x_size & 1; |  | ||||||
|   if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; |  | ||||||
|   if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; |  | ||||||
|  |  | ||||||
|   dmux->feature_flags_ = ReadByte(mem); |  | ||||||
|   Skip(mem, 3);  // Reserved. |  | ||||||
|   dmux->canvas_width_  = 1 + ReadLE24s(mem); |  | ||||||
|   dmux->canvas_height_ = 1 + ReadLE24s(mem); |  | ||||||
|   if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { |  | ||||||
|     return PARSE_ERROR;  // image final dimension is too large |  | ||||||
|   } |  | ||||||
|   Skip(mem, vp8x_size - VP8X_CHUNK_SIZE);  // skip any trailing data. |  | ||||||
|   dmux->state_ = WEBP_DEMUX_PARSED_HEADER; |  | ||||||
|  |  | ||||||
|   if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR; |  | ||||||
|   if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; |  | ||||||
|  |  | ||||||
|   do { |   do { | ||||||
|     int store_chunk = 1; |     int store_chunk = 1; | ||||||
|     const size_t chunk_start_offset = mem->start_; |     const size_t chunk_start_offset = mem->start_; | ||||||
| @@ -513,7 +489,6 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { | |||||||
|       case MKFOURCC('A', 'L', 'P', 'H'): |       case MKFOURCC('A', 'L', 'P', 'H'): | ||||||
|       case MKFOURCC('V', 'P', '8', ' '): |       case MKFOURCC('V', 'P', '8', ' '): | ||||||
|       case MKFOURCC('V', 'P', '8', 'L'): { |       case MKFOURCC('V', 'P', '8', 'L'): { | ||||||
|         const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); |  | ||||||
|         // check that this isn't an animation (all frames should be in an ANMF). |         // check that this isn't an animation (all frames should be in an ANMF). | ||||||
|         if (anim_chunks > 0 || is_animation) return PARSE_ERROR; |         if (anim_chunks > 0 || is_animation) return PARSE_ERROR; | ||||||
|  |  | ||||||
| @@ -552,14 +527,14 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { | |||||||
|         store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); |         store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); | ||||||
|         goto Skip; |         goto Skip; | ||||||
|       } |       } | ||||||
|       case MKFOURCC('X', 'M', 'P', ' '): { |  | ||||||
|         store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); |  | ||||||
|         goto Skip; |  | ||||||
|       } |  | ||||||
|       case MKFOURCC('E', 'X', 'I', 'F'): { |       case MKFOURCC('E', 'X', 'I', 'F'): { | ||||||
|         store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); |         store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); | ||||||
|         goto Skip; |         goto Skip; | ||||||
|       } |       } | ||||||
|  |       case MKFOURCC('X', 'M', 'P', ' '): { | ||||||
|  |         store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); | ||||||
|  |         goto Skip; | ||||||
|  |       } | ||||||
|  Skip: |  Skip: | ||||||
|       default: { |       default: { | ||||||
|         if (chunk_size_padded <= MemDataSize(mem)) { |         if (chunk_size_padded <= MemDataSize(mem)) { | ||||||
| @@ -588,6 +563,37 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { | |||||||
|   return status; |   return status; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { | ||||||
|  |   MemBuffer* const mem = &dmux->mem_; | ||||||
|  |   uint32_t vp8x_size; | ||||||
|  |  | ||||||
|  |   if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; | ||||||
|  |  | ||||||
|  |   dmux->is_ext_format_ = 1; | ||||||
|  |   Skip(mem, TAG_SIZE);  // VP8X | ||||||
|  |   vp8x_size = ReadLE32(mem); | ||||||
|  |   if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; | ||||||
|  |   if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; | ||||||
|  |   vp8x_size += vp8x_size & 1; | ||||||
|  |   if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; | ||||||
|  |   if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; | ||||||
|  |  | ||||||
|  |   dmux->feature_flags_ = ReadByte(mem); | ||||||
|  |   Skip(mem, 3);  // Reserved. | ||||||
|  |   dmux->canvas_width_  = 1 + ReadLE24s(mem); | ||||||
|  |   dmux->canvas_height_ = 1 + ReadLE24s(mem); | ||||||
|  |   if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { | ||||||
|  |     return PARSE_ERROR;  // image final dimension is too large | ||||||
|  |   } | ||||||
|  |   Skip(mem, vp8x_size - VP8X_CHUNK_SIZE);  // skip any trailing data. | ||||||
|  |   dmux->state_ = WEBP_DEMUX_PARSED_HEADER; | ||||||
|  |  | ||||||
|  |   if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR; | ||||||
|  |   if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; | ||||||
|  |  | ||||||
|  |   return ParseVP8XChunks(dmux); | ||||||
|  | } | ||||||
|  |  | ||||||
| // ----------------------------------------------------------------------------- | // ----------------------------------------------------------------------------- | ||||||
| // Format validation | // Format validation | ||||||
|  |  | ||||||
| @@ -697,6 +703,7 @@ static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) { | |||||||
|   dmux->canvas_width_ = -1; |   dmux->canvas_width_ = -1; | ||||||
|   dmux->canvas_height_ = -1; |   dmux->canvas_height_ = -1; | ||||||
|   dmux->frames_tail_ = &dmux->frames_; |   dmux->frames_tail_ = &dmux->frames_; | ||||||
|  |   dmux->chunks_tail_ = &dmux->chunks_; | ||||||
|   dmux->mem_ = *mem; |   dmux->mem_ = *mem; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user