demux.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. // Copyright 2012 Google Inc. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the COPYING file in the root of the source
  5. // tree. An additional intellectual property rights grant can be found
  6. // in the file PATENTS. All contributing project authors may
  7. // be found in the AUTHORS file in the root of the source tree.
  8. // -----------------------------------------------------------------------------
  9. //
  10. // WebP container demux.
  11. //
  12. #ifdef HAVE_CONFIG_H
  13. #include "../webp/config.h"
  14. #endif
  15. #include <assert.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include "../utils/utils.h"
  19. #include "../webp/decode.h" // WebPGetFeatures
  20. #include "../webp/demux.h"
  21. #include "../webp/format_constants.h"
  22. #define DMUX_MAJ_VERSION 1
  23. #define DMUX_MIN_VERSION 2
  24. #define DMUX_REV_VERSION 2
  25. typedef struct {
  26. size_t start_; // start location of the data
  27. size_t end_; // end location
  28. size_t riff_end_; // riff chunk end location, can be > end_.
  29. size_t buf_size_; // size of the buffer
  30. const uint8_t* buf_;
  31. } MemBuffer;
  32. typedef struct {
  33. size_t offset_;
  34. size_t size_;
  35. } ChunkData;
  36. typedef struct Frame {
  37. int x_offset_, y_offset_;
  38. int width_, height_;
  39. int has_alpha_;
  40. int duration_;
  41. WebPMuxAnimDispose dispose_method_;
  42. WebPMuxAnimBlend blend_method_;
  43. int frame_num_;
  44. int complete_; // img_components_ contains a full image.
  45. ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH
  46. struct Frame* next_;
  47. } Frame;
  48. typedef struct Chunk {
  49. ChunkData data_;
  50. struct Chunk* next_;
  51. } Chunk;
  52. struct WebPDemuxer {
  53. MemBuffer mem_;
  54. WebPDemuxState state_;
  55. int is_ext_format_;
  56. uint32_t feature_flags_;
  57. int canvas_width_, canvas_height_;
  58. int loop_count_;
  59. uint32_t bgcolor_;
  60. int num_frames_;
  61. Frame* frames_;
  62. Frame** frames_tail_;
  63. Chunk* chunks_; // non-image chunks
  64. Chunk** chunks_tail_;
  65. };
  66. typedef enum {
  67. PARSE_OK,
  68. PARSE_NEED_MORE_DATA,
  69. PARSE_ERROR
  70. } ParseStatus;
  71. typedef struct ChunkParser {
  72. uint8_t id[4];
  73. ParseStatus (*parse)(WebPDemuxer* const dmux);
  74. int (*valid)(const WebPDemuxer* const dmux);
  75. } ChunkParser;
  76. static ParseStatus ParseSingleImage(WebPDemuxer* const dmux);
  77. static ParseStatus ParseVP8X(WebPDemuxer* const dmux);
  78. static int IsValidSimpleFormat(const WebPDemuxer* const dmux);
  79. static int IsValidExtendedFormat(const WebPDemuxer* const dmux);
  80. static const ChunkParser kMasterChunks[] = {
  81. { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat },
  82. { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat },
  83. { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat },
  84. { { '0', '0', '0', '0' }, NULL, NULL },
  85. };
  86. //------------------------------------------------------------------------------
  87. int WebPGetDemuxVersion(void) {
  88. return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION;
  89. }
  90. // -----------------------------------------------------------------------------
  91. // MemBuffer
  92. static int RemapMemBuffer(MemBuffer* const mem,
  93. const uint8_t* data, size_t size) {
  94. if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
  95. mem->buf_ = data;
  96. mem->end_ = mem->buf_size_ = size;
  97. return 1;
  98. }
  99. static int InitMemBuffer(MemBuffer* const mem,
  100. const uint8_t* data, size_t size) {
  101. memset(mem, 0, sizeof(*mem));
  102. return RemapMemBuffer(mem, data, size);
  103. }
  104. // Return the remaining data size available in 'mem'.
  105. static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) {
  106. return (mem->end_ - mem->start_);
  107. }
  108. // Return true if 'size' exceeds the end of the RIFF chunk.
  109. static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) {
  110. return (size > mem->riff_end_ - mem->start_);
  111. }
  112. static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) {
  113. mem->start_ += size;
  114. }
  115. static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) {
  116. mem->start_ -= size;
  117. }
  118. static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) {
  119. return mem->buf_ + mem->start_;
  120. }
  121. // Read from 'mem' and skip the read bytes.
  122. static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) {
  123. const uint8_t byte = mem->buf_[mem->start_];
  124. Skip(mem, 1);
  125. return byte;
  126. }
  127. static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) {
  128. const uint8_t* const data = mem->buf_ + mem->start_;
  129. const int val = GetLE16(data);
  130. Skip(mem, 2);
  131. return val;
  132. }
  133. static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) {
  134. const uint8_t* const data = mem->buf_ + mem->start_;
  135. const int val = GetLE24(data);
  136. Skip(mem, 3);
  137. return val;
  138. }
  139. static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) {
  140. const uint8_t* const data = mem->buf_ + mem->start_;
  141. const uint32_t val = GetLE32(data);
  142. Skip(mem, 4);
  143. return val;
  144. }
  145. // -----------------------------------------------------------------------------
  146. // Secondary chunk parsing
  147. static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) {
  148. *dmux->chunks_tail_ = chunk;
  149. chunk->next_ = NULL;
  150. dmux->chunks_tail_ = &chunk->next_;
  151. }
  152. // Add a frame to the end of the list, ensuring the last frame is complete.
  153. // Returns true on success, false otherwise.
  154. static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
  155. const Frame* const last_frame = *dmux->frames_tail_;
  156. if (last_frame != NULL && !last_frame->complete_) return 0;
  157. *dmux->frames_tail_ = frame;
  158. frame->next_ = NULL;
  159. dmux->frames_tail_ = &frame->next_;
  160. return 1;
  161. }
  162. static void SetFrameInfo(size_t start_offset, size_t size,
  163. int frame_num, int complete,
  164. const WebPBitstreamFeatures* const features,
  165. Frame* const frame) {
  166. frame->img_components_[0].offset_ = start_offset;
  167. frame->img_components_[0].size_ = size;
  168. frame->width_ = features->width;
  169. frame->height_ = features->height;
  170. frame->has_alpha_ |= features->has_alpha;
  171. frame->frame_num_ = frame_num;
  172. frame->complete_ = complete;
  173. }
  174. // Store image bearing chunks to 'frame'. 'min_size' is an optional size
  175. // requirement, it may be zero.
  176. static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
  177. MemBuffer* const mem, Frame* const frame) {
  178. int alpha_chunks = 0;
  179. int image_chunks = 0;
  180. int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE ||
  181. MemDataSize(mem) < min_size);
  182. ParseStatus status = PARSE_OK;
  183. if (done) return PARSE_NEED_MORE_DATA;
  184. do {
  185. const size_t chunk_start_offset = mem->start_;
  186. const uint32_t fourcc = ReadLE32(mem);
  187. const uint32_t payload_size = ReadLE32(mem);
  188. uint32_t payload_size_padded;
  189. size_t payload_available;
  190. size_t chunk_size;
  191. if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
  192. payload_size_padded = payload_size + (payload_size & 1);
  193. payload_available = (payload_size_padded > MemDataSize(mem))
  194. ? MemDataSize(mem) : payload_size_padded;
  195. chunk_size = CHUNK_HEADER_SIZE + payload_available;
  196. if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR;
  197. if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA;
  198. switch (fourcc) {
  199. case MKFOURCC('A', 'L', 'P', 'H'):
  200. if (alpha_chunks == 0) {
  201. ++alpha_chunks;
  202. frame->img_components_[1].offset_ = chunk_start_offset;
  203. frame->img_components_[1].size_ = chunk_size;
  204. frame->has_alpha_ = 1;
  205. frame->frame_num_ = frame_num;
  206. Skip(mem, payload_available);
  207. } else {
  208. goto Done;
  209. }
  210. break;
  211. case MKFOURCC('V', 'P', '8', 'L'):
  212. if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha
  213. // fall through
  214. case MKFOURCC('V', 'P', '8', ' '):
  215. if (image_chunks == 0) {
  216. // Extract the bitstream features, tolerating failures when the data
  217. // is incomplete.
  218. WebPBitstreamFeatures features;
  219. const VP8StatusCode vp8_status =
  220. WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size,
  221. &features);
  222. if (status == PARSE_NEED_MORE_DATA &&
  223. vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) {
  224. return PARSE_NEED_MORE_DATA;
  225. } else if (vp8_status != VP8_STATUS_OK) {
  226. // We have enough data, and yet WebPGetFeatures() failed.
  227. return PARSE_ERROR;
  228. }
  229. ++image_chunks;
  230. SetFrameInfo(chunk_start_offset, chunk_size, frame_num,
  231. status == PARSE_OK, &features, frame);
  232. Skip(mem, payload_available);
  233. } else {
  234. goto Done;
  235. }
  236. break;
  237. Done:
  238. default:
  239. // Restore fourcc/size when moving up one level in parsing.
  240. Rewind(mem, CHUNK_HEADER_SIZE);
  241. done = 1;
  242. break;
  243. }
  244. if (mem->start_ == mem->riff_end_) {
  245. done = 1;
  246. } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
  247. status = PARSE_NEED_MORE_DATA;
  248. }
  249. } while (!done && status == PARSE_OK);
  250. return status;
  251. }
  252. // Creates a new Frame if 'actual_size' is within bounds and 'mem' contains
  253. // enough data ('min_size') to parse the payload.
  254. // Returns PARSE_OK on success with *frame pointing to the new Frame.
  255. // Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise.
  256. static ParseStatus NewFrame(const MemBuffer* const mem,
  257. uint32_t min_size, uint32_t actual_size,
  258. Frame** frame) {
  259. if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
  260. if (actual_size < min_size) return PARSE_ERROR;
  261. if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
  262. *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame));
  263. return (*frame == NULL) ? PARSE_ERROR : PARSE_OK;
  264. }
  265. // Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
  266. // 'frame_chunk_size' is the previously validated, padded chunk size.
  267. static ParseStatus ParseAnimationFrame(
  268. WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
  269. const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
  270. const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
  271. int added_frame = 0;
  272. int bits;
  273. MemBuffer* const mem = &dmux->mem_;
  274. Frame* frame;
  275. size_t start_offset;
  276. ParseStatus status =
  277. NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
  278. if (status != PARSE_OK) return status;
  279. frame->x_offset_ = 2 * ReadLE24s(mem);
  280. frame->y_offset_ = 2 * ReadLE24s(mem);
  281. frame->width_ = 1 + ReadLE24s(mem);
  282. frame->height_ = 1 + ReadLE24s(mem);
  283. frame->duration_ = ReadLE24s(mem);
  284. bits = ReadByte(mem);
  285. frame->dispose_method_ =
  286. (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
  287. frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
  288. if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) {
  289. WebPSafeFree(frame);
  290. return PARSE_ERROR;
  291. }
  292. // Store a frame only if the animation flag is set there is some data for
  293. // this frame is available.
  294. start_offset = mem->start_;
  295. status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame);
  296. if (status != PARSE_ERROR && mem->start_ - start_offset > anmf_payload_size) {
  297. status = PARSE_ERROR;
  298. }
  299. if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) {
  300. added_frame = AddFrame(dmux, frame);
  301. if (added_frame) {
  302. ++dmux->num_frames_;
  303. } else {
  304. status = PARSE_ERROR;
  305. }
  306. }
  307. if (!added_frame) WebPSafeFree(frame);
  308. return status;
  309. }
  310. // General chunk storage, starting with the header at 'start_offset', allowing
  311. // the user to request the payload via a fourcc string. 'size' includes the
  312. // header and the unpadded payload size.
  313. // Returns true on success, false otherwise.
  314. static int StoreChunk(WebPDemuxer* const dmux,
  315. size_t start_offset, uint32_t size) {
  316. Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk));
  317. if (chunk == NULL) return 0;
  318. chunk->data_.offset_ = start_offset;
  319. chunk->data_.size_ = size;
  320. AddChunk(dmux, chunk);
  321. return 1;
  322. }
  323. // -----------------------------------------------------------------------------
  324. // Primary chunk parsing
  325. static ParseStatus ReadHeader(MemBuffer* const mem) {
  326. const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE;
  327. uint32_t riff_size;
  328. // Basic file level validation.
  329. if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
  330. if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) ||
  331. memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) {
  332. return PARSE_ERROR;
  333. }
  334. riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE);
  335. if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR;
  336. if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
  337. // There's no point in reading past the end of the RIFF chunk
  338. mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE;
  339. if (mem->buf_size_ > mem->riff_end_) {
  340. mem->buf_size_ = mem->end_ = mem->riff_end_;
  341. }
  342. Skip(mem, RIFF_HEADER_SIZE);
  343. return PARSE_OK;
  344. }
  345. static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
  346. const size_t min_size = CHUNK_HEADER_SIZE;
  347. MemBuffer* const mem = &dmux->mem_;
  348. Frame* frame;
  349. ParseStatus status;
  350. int image_added = 0;
  351. if (dmux->frames_ != NULL) return PARSE_ERROR;
  352. if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
  353. if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
  354. frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame));
  355. if (frame == NULL) return PARSE_ERROR;
  356. // For the single image case we allow parsing of a partial frame, so no
  357. // minimum size is imposed here.
  358. status = StoreFrame(1, 0, &dmux->mem_, frame);
  359. if (status != PARSE_ERROR) {
  360. const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG);
  361. // Clear any alpha when the alpha flag is missing.
  362. if (!has_alpha && frame->img_components_[1].size_ > 0) {
  363. frame->img_components_[1].offset_ = 0;
  364. frame->img_components_[1].size_ = 0;
  365. frame->has_alpha_ = 0;
  366. }
  367. // Use the frame width/height as the canvas values for non-vp8x files.
  368. // Also, set ALPHA_FLAG if this is a lossless image with alpha.
  369. if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) {
  370. dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
  371. dmux->canvas_width_ = frame->width_;
  372. dmux->canvas_height_ = frame->height_;
  373. dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0;
  374. }
  375. if (!AddFrame(dmux, frame)) {
  376. status = PARSE_ERROR; // last frame was left incomplete
  377. } else {
  378. image_added = 1;
  379. dmux->num_frames_ = 1;
  380. }
  381. }
  382. if (!image_added) WebPSafeFree(frame);
  383. return status;
  384. }
  385. static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) {
  386. const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
  387. MemBuffer* const mem = &dmux->mem_;
  388. int anim_chunks = 0;
  389. ParseStatus status = PARSE_OK;
  390. do {
  391. int store_chunk = 1;
  392. const size_t chunk_start_offset = mem->start_;
  393. const uint32_t fourcc = ReadLE32(mem);
  394. const uint32_t chunk_size = ReadLE32(mem);
  395. uint32_t chunk_size_padded;
  396. if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
  397. chunk_size_padded = chunk_size + (chunk_size & 1);
  398. if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR;
  399. switch (fourcc) {
  400. case MKFOURCC('V', 'P', '8', 'X'): {
  401. return PARSE_ERROR;
  402. }
  403. case MKFOURCC('A', 'L', 'P', 'H'):
  404. case MKFOURCC('V', 'P', '8', ' '):
  405. case MKFOURCC('V', 'P', '8', 'L'): {
  406. // check that this isn't an animation (all frames should be in an ANMF).
  407. if (anim_chunks > 0 || is_animation) return PARSE_ERROR;
  408. Rewind(mem, CHUNK_HEADER_SIZE);
  409. status = ParseSingleImage(dmux);
  410. break;
  411. }
  412. case MKFOURCC('A', 'N', 'I', 'M'): {
  413. if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR;
  414. if (MemDataSize(mem) < chunk_size_padded) {
  415. status = PARSE_NEED_MORE_DATA;
  416. } else if (anim_chunks == 0) {
  417. ++anim_chunks;
  418. dmux->bgcolor_ = ReadLE32(mem);
  419. dmux->loop_count_ = ReadLE16s(mem);
  420. Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE);
  421. } else {
  422. store_chunk = 0;
  423. goto Skip;
  424. }
  425. break;
  426. }
  427. case MKFOURCC('A', 'N', 'M', 'F'): {
  428. if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames.
  429. status = ParseAnimationFrame(dmux, chunk_size_padded);
  430. break;
  431. }
  432. case MKFOURCC('I', 'C', 'C', 'P'): {
  433. store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG);
  434. goto Skip;
  435. }
  436. case MKFOURCC('E', 'X', 'I', 'F'): {
  437. store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG);
  438. goto Skip;
  439. }
  440. case MKFOURCC('X', 'M', 'P', ' '): {
  441. store_chunk = !!(dmux->feature_flags_ & XMP_FLAG);
  442. goto Skip;
  443. }
  444. Skip:
  445. default: {
  446. if (chunk_size_padded <= MemDataSize(mem)) {
  447. if (store_chunk) {
  448. // Store only the chunk header and unpadded size as only the payload
  449. // will be returned to the user.
  450. if (!StoreChunk(dmux, chunk_start_offset,
  451. CHUNK_HEADER_SIZE + chunk_size)) {
  452. return PARSE_ERROR;
  453. }
  454. }
  455. Skip(mem, chunk_size_padded);
  456. } else {
  457. status = PARSE_NEED_MORE_DATA;
  458. }
  459. }
  460. }
  461. if (mem->start_ == mem->riff_end_) {
  462. break;
  463. } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
  464. status = PARSE_NEED_MORE_DATA;
  465. }
  466. } while (status == PARSE_OK);
  467. return status;
  468. }
  469. static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
  470. MemBuffer* const mem = &dmux->mem_;
  471. uint32_t vp8x_size;
  472. if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA;
  473. dmux->is_ext_format_ = 1;
  474. Skip(mem, TAG_SIZE); // VP8X
  475. vp8x_size = ReadLE32(mem);
  476. if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
  477. if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR;
  478. vp8x_size += vp8x_size & 1;
  479. if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR;
  480. if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA;
  481. dmux->feature_flags_ = ReadByte(mem);
  482. Skip(mem, 3); // Reserved.
  483. dmux->canvas_width_ = 1 + ReadLE24s(mem);
  484. dmux->canvas_height_ = 1 + ReadLE24s(mem);
  485. if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) {
  486. return PARSE_ERROR; // image final dimension is too large
  487. }
  488. Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data.
  489. dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
  490. if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR;
  491. if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA;
  492. return ParseVP8XChunks(dmux);
  493. }
  494. // -----------------------------------------------------------------------------
  495. // Format validation
  496. static int IsValidSimpleFormat(const WebPDemuxer* const dmux) {
  497. const Frame* const frame = dmux->frames_;
  498. if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1;
  499. if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0;
  500. if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0;
  501. if (frame->width_ <= 0 || frame->height_ <= 0) return 0;
  502. return 1;
  503. }
  504. // If 'exact' is true, check that the image resolution matches the canvas.
  505. // If 'exact' is false, check that the x/y offsets do not exceed the canvas.
  506. static int CheckFrameBounds(const Frame* const frame, int exact,
  507. int canvas_width, int canvas_height) {
  508. if (exact) {
  509. if (frame->x_offset_ != 0 || frame->y_offset_ != 0) {
  510. return 0;
  511. }
  512. if (frame->width_ != canvas_width || frame->height_ != canvas_height) {
  513. return 0;
  514. }
  515. } else {
  516. if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0;
  517. if (frame->width_ + frame->x_offset_ > canvas_width) return 0;
  518. if (frame->height_ + frame->y_offset_ > canvas_height) return 0;
  519. }
  520. return 1;
  521. }
  522. static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
  523. const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
  524. const Frame* f = dmux->frames_;
  525. if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1;
  526. if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0;
  527. if (dmux->loop_count_ < 0) return 0;
  528. if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0;
  529. if (dmux->feature_flags_ & ~ALL_VALID_FLAGS) return 0; // invalid bitstream
  530. while (f != NULL) {
  531. const int cur_frame_set = f->frame_num_;
  532. int frame_count = 0;
  533. // Check frame properties.
  534. for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) {
  535. const ChunkData* const image = f->img_components_;
  536. const ChunkData* const alpha = f->img_components_ + 1;
  537. if (!is_animation && f->frame_num_ > 1) return 0;
  538. if (f->complete_) {
  539. if (alpha->size_ == 0 && image->size_ == 0) return 0;
  540. // Ensure alpha precedes image bitstream.
  541. if (alpha->size_ > 0 && alpha->offset_ > image->offset_) {
  542. return 0;
  543. }
  544. if (f->width_ <= 0 || f->height_ <= 0) return 0;
  545. } else {
  546. // There shouldn't be a partial frame in a complete file.
  547. if (dmux->state_ == WEBP_DEMUX_DONE) return 0;
  548. // Ensure alpha precedes image bitstream.
  549. if (alpha->size_ > 0 && image->size_ > 0 &&
  550. alpha->offset_ > image->offset_) {
  551. return 0;
  552. }
  553. // There shouldn't be any frames after an incomplete one.
  554. if (f->next_ != NULL) return 0;
  555. }
  556. if (f->width_ > 0 && f->height_ > 0 &&
  557. !CheckFrameBounds(f, !is_animation,
  558. dmux->canvas_width_, dmux->canvas_height_)) {
  559. return 0;
  560. }
  561. ++frame_count;
  562. }
  563. }
  564. return 1;
  565. }
  566. // -----------------------------------------------------------------------------
  567. // WebPDemuxer object
  568. static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) {
  569. dmux->state_ = WEBP_DEMUX_PARSING_HEADER;
  570. dmux->loop_count_ = 1;
  571. dmux->bgcolor_ = 0xFFFFFFFF; // White background by default.
  572. dmux->canvas_width_ = -1;
  573. dmux->canvas_height_ = -1;
  574. dmux->frames_tail_ = &dmux->frames_;
  575. dmux->chunks_tail_ = &dmux->chunks_;
  576. dmux->mem_ = *mem;
  577. }
  578. static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem,
  579. WebPDemuxer** demuxer) {
  580. WebPBitstreamFeatures features;
  581. const VP8StatusCode status =
  582. WebPGetFeatures(mem->buf_, mem->buf_size_, &features);
  583. *demuxer = NULL;
  584. if (status != VP8_STATUS_OK) {
  585. return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA
  586. : PARSE_ERROR;
  587. }
  588. {
  589. WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux));
  590. Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame));
  591. if (dmux == NULL || frame == NULL) goto Error;
  592. InitDemux(dmux, mem);
  593. SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features,
  594. frame);
  595. if (!AddFrame(dmux, frame)) goto Error;
  596. dmux->state_ = WEBP_DEMUX_DONE;
  597. dmux->canvas_width_ = frame->width_;
  598. dmux->canvas_height_ = frame->height_;
  599. dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0;
  600. dmux->num_frames_ = 1;
  601. assert(IsValidSimpleFormat(dmux));
  602. *demuxer = dmux;
  603. return PARSE_OK;
  604. Error:
  605. WebPSafeFree(dmux);
  606. WebPSafeFree(frame);
  607. return PARSE_ERROR;
  608. }
  609. }
  610. WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial,
  611. WebPDemuxState* state, int version) {
  612. const ChunkParser* parser;
  613. int partial;
  614. ParseStatus status = PARSE_ERROR;
  615. MemBuffer mem;
  616. WebPDemuxer* dmux;
  617. if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR;
  618. if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL;
  619. if (data == NULL || data->bytes == NULL || data->size == 0) return NULL;
  620. if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL;
  621. status = ReadHeader(&mem);
  622. if (status != PARSE_OK) {
  623. // If parsing of the webp file header fails attempt to handle a raw
  624. // VP8/VP8L frame. Note 'allow_partial' is ignored in this case.
  625. if (status == PARSE_ERROR) {
  626. status = CreateRawImageDemuxer(&mem, &dmux);
  627. if (status == PARSE_OK) {
  628. if (state != NULL) *state = WEBP_DEMUX_DONE;
  629. return dmux;
  630. }
  631. }
  632. if (state != NULL) {
  633. *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER
  634. : WEBP_DEMUX_PARSE_ERROR;
  635. }
  636. return NULL;
  637. }
  638. partial = (mem.buf_size_ < mem.riff_end_);
  639. if (!allow_partial && partial) return NULL;
  640. dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux));
  641. if (dmux == NULL) return NULL;
  642. InitDemux(dmux, &mem);
  643. status = PARSE_ERROR;
  644. for (parser = kMasterChunks; parser->parse != NULL; ++parser) {
  645. if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) {
  646. status = parser->parse(dmux);
  647. if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE;
  648. if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR;
  649. if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR;
  650. if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR;
  651. break;
  652. }
  653. }
  654. if (state != NULL) *state = dmux->state_;
  655. if (status == PARSE_ERROR) {
  656. WebPDemuxDelete(dmux);
  657. return NULL;
  658. }
  659. return dmux;
  660. }
  661. void WebPDemuxDelete(WebPDemuxer* dmux) {
  662. Chunk* c;
  663. Frame* f;
  664. if (dmux == NULL) return;
  665. for (f = dmux->frames_; f != NULL;) {
  666. Frame* const cur_frame = f;
  667. f = f->next_;
  668. WebPSafeFree(cur_frame);
  669. }
  670. for (c = dmux->chunks_; c != NULL;) {
  671. Chunk* const cur_chunk = c;
  672. c = c->next_;
  673. WebPSafeFree(cur_chunk);
  674. }
  675. WebPSafeFree(dmux);
  676. }
  677. // -----------------------------------------------------------------------------
  678. uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) {
  679. if (dmux == NULL) return 0;
  680. switch (feature) {
  681. case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_;
  682. case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_;
  683. case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_;
  684. case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_;
  685. case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_;
  686. case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_;
  687. }
  688. return 0;
  689. }
  690. // -----------------------------------------------------------------------------
  691. // Frame iteration
  692. static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) {
  693. const Frame* f;
  694. for (f = dmux->frames_; f != NULL; f = f->next_) {
  695. if (frame_num == f->frame_num_) break;
  696. }
  697. return f;
  698. }
  699. static const uint8_t* GetFramePayload(const uint8_t* const mem_buf,
  700. const Frame* const frame,
  701. size_t* const data_size) {
  702. *data_size = 0;
  703. if (frame != NULL) {
  704. const ChunkData* const image = frame->img_components_;
  705. const ChunkData* const alpha = frame->img_components_ + 1;
  706. size_t start_offset = image->offset_;
  707. *data_size = image->size_;
  708. // if alpha exists it precedes image, update the size allowing for
  709. // intervening chunks.
  710. if (alpha->size_ > 0) {
  711. const size_t inter_size = (image->offset_ > 0)
  712. ? image->offset_ - (alpha->offset_ + alpha->size_)
  713. : 0;
  714. start_offset = alpha->offset_;
  715. *data_size += alpha->size_ + inter_size;
  716. }
  717. return mem_buf + start_offset;
  718. }
  719. return NULL;
  720. }
  721. // Create a whole 'frame' from VP8 (+ alpha) or lossless.
  722. static int SynthesizeFrame(const WebPDemuxer* const dmux,
  723. const Frame* const frame,
  724. WebPIterator* const iter) {
  725. const uint8_t* const mem_buf = dmux->mem_.buf_;
  726. size_t payload_size = 0;
  727. const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size);
  728. if (payload == NULL) return 0;
  729. assert(frame != NULL);
  730. iter->frame_num = frame->frame_num_;
  731. iter->num_frames = dmux->num_frames_;
  732. iter->x_offset = frame->x_offset_;
  733. iter->y_offset = frame->y_offset_;
  734. iter->width = frame->width_;
  735. iter->height = frame->height_;
  736. iter->has_alpha = frame->has_alpha_;
  737. iter->duration = frame->duration_;
  738. iter->dispose_method = frame->dispose_method_;
  739. iter->blend_method = frame->blend_method_;
  740. iter->complete = frame->complete_;
  741. iter->fragment.bytes = payload;
  742. iter->fragment.size = payload_size;
  743. return 1;
  744. }
  745. static int SetFrame(int frame_num, WebPIterator* const iter) {
  746. const Frame* frame;
  747. const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
  748. if (dmux == NULL || frame_num < 0) return 0;
  749. if (frame_num > dmux->num_frames_) return 0;
  750. if (frame_num == 0) frame_num = dmux->num_frames_;
  751. frame = GetFrame(dmux, frame_num);
  752. if (frame == NULL) return 0;
  753. return SynthesizeFrame(dmux, frame, iter);
  754. }
  755. int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) {
  756. if (iter == NULL) return 0;
  757. memset(iter, 0, sizeof(*iter));
  758. iter->private_ = (void*)dmux;
  759. return SetFrame(frame, iter);
  760. }
  761. int WebPDemuxNextFrame(WebPIterator* iter) {
  762. if (iter == NULL) return 0;
  763. return SetFrame(iter->frame_num + 1, iter);
  764. }
  765. int WebPDemuxPrevFrame(WebPIterator* iter) {
  766. if (iter == NULL) return 0;
  767. if (iter->frame_num <= 1) return 0;
  768. return SetFrame(iter->frame_num - 1, iter);
  769. }
  770. void WebPDemuxReleaseIterator(WebPIterator* iter) {
  771. (void)iter;
  772. }
  773. // -----------------------------------------------------------------------------
  774. // Chunk iteration
  775. static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) {
  776. const uint8_t* const mem_buf = dmux->mem_.buf_;
  777. const Chunk* c;
  778. int count = 0;
  779. for (c = dmux->chunks_; c != NULL; c = c->next_) {
  780. const uint8_t* const header = mem_buf + c->data_.offset_;
  781. if (!memcmp(header, fourcc, TAG_SIZE)) ++count;
  782. }
  783. return count;
  784. }
  785. static const Chunk* GetChunk(const WebPDemuxer* const dmux,
  786. const char fourcc[4], int chunk_num) {
  787. const uint8_t* const mem_buf = dmux->mem_.buf_;
  788. const Chunk* c;
  789. int count = 0;
  790. for (c = dmux->chunks_; c != NULL; c = c->next_) {
  791. const uint8_t* const header = mem_buf + c->data_.offset_;
  792. if (!memcmp(header, fourcc, TAG_SIZE)) ++count;
  793. if (count == chunk_num) break;
  794. }
  795. return c;
  796. }
  797. static int SetChunk(const char fourcc[4], int chunk_num,
  798. WebPChunkIterator* const iter) {
  799. const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
  800. int count;
  801. if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0;
  802. count = ChunkCount(dmux, fourcc);
  803. if (count == 0) return 0;
  804. if (chunk_num == 0) chunk_num = count;
  805. if (chunk_num <= count) {
  806. const uint8_t* const mem_buf = dmux->mem_.buf_;
  807. const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num);
  808. iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE;
  809. iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE;
  810. iter->num_chunks = count;
  811. iter->chunk_num = chunk_num;
  812. return 1;
  813. }
  814. return 0;
  815. }
  816. int WebPDemuxGetChunk(const WebPDemuxer* dmux,
  817. const char fourcc[4], int chunk_num,
  818. WebPChunkIterator* iter) {
  819. if (iter == NULL) return 0;
  820. memset(iter, 0, sizeof(*iter));
  821. iter->private_ = (void*)dmux;
  822. return SetChunk(fourcc, chunk_num, iter);
  823. }
  824. int WebPDemuxNextChunk(WebPChunkIterator* iter) {
  825. if (iter != NULL) {
  826. const char* const fourcc =
  827. (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE;
  828. return SetChunk(fourcc, iter->chunk_num + 1, iter);
  829. }
  830. return 0;
  831. }
  832. int WebPDemuxPrevChunk(WebPChunkIterator* iter) {
  833. if (iter != NULL && iter->chunk_num > 1) {
  834. const char* const fourcc =
  835. (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE;
  836. return SetChunk(fourcc, iter->chunk_num - 1, iter);
  837. }
  838. return 0;
  839. }
  840. void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) {
  841. (void)iter;
  842. }