Skips to the next VP8/VP8L chunk header in the data given the size of the RIFF chunk 'riff_size'. Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and VP8_STATUS_OK otherwise. If an alpha chunk is found, *alpha_data and *alpha_size are set appropriately.
| 118 | // If an alpha chunk is found, *alpha_data and *alpha_size are set |
| 119 | // appropriately. |
| 120 | static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, size_t* const data_size, |
| 121 | size_t const riff_size, const uint8_t** const alpha_data, |
| 122 | size_t* const alpha_size) { |
| 123 | const uint8_t* buf; |
| 124 | size_t buf_size; |
| 125 | uint32_t total_size = TAG_SIZE + // "WEBP". |
| 126 | CHUNK_HEADER_SIZE + // "VP8Xnnnn". |
| 127 | VP8X_CHUNK_SIZE; // data. |
| 128 | assert(data != nullptr); |
| 129 | assert(data_size != nullptr); |
| 130 | buf = *data; |
| 131 | buf_size = *data_size; |
| 132 | |
| 133 | assert(alpha_data != nullptr); |
| 134 | assert(alpha_size != nullptr); |
| 135 | *alpha_data = nullptr; |
| 136 | *alpha_size = 0; |
| 137 | |
| 138 | while (1) { |
| 139 | uint32_t chunk_size; |
| 140 | uint32_t disk_chunk_size; // chunk_size with padding |
| 141 | |
| 142 | *data = buf; |
| 143 | *data_size = buf_size; |
| 144 | |
| 145 | if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. |
| 146 | return VP8_STATUS_NOT_ENOUGH_DATA; |
| 147 | } |
| 148 | |
| 149 | chunk_size = GetLE32(buf + TAG_SIZE); |
| 150 | if (chunk_size > MAX_CHUNK_PAYLOAD) { |
| 151 | return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. |
| 152 | } |
| 153 | // For odd-sized chunk-payload, there's one byte padding at the end. |
| 154 | disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; |
| 155 | total_size += disk_chunk_size; |
| 156 | |
| 157 | // Check that total bytes skipped so far does not exceed riff_size. |
| 158 | if (riff_size > 0 && (total_size > riff_size)) { |
| 159 | return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. |
| 160 | } |
| 161 | |
| 162 | // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have |
| 163 | // parsed all the optional chunks. |
| 164 | // Note: This check must occur before the check 'buf_size < disk_chunk_size' |
| 165 | // below to allow incomplete VP8/VP8L chunks. |
| 166 | if (!memcmp(buf, "VP8 ", TAG_SIZE) || !memcmp(buf, "VP8L", TAG_SIZE)) { |
| 167 | return VP8_STATUS_OK; |
| 168 | } |
| 169 | |
| 170 | if (buf_size < disk_chunk_size) { // Insufficient data. |
| 171 | return VP8_STATUS_NOT_ENOUGH_DATA; |
| 172 | } |
| 173 | |
| 174 | if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. |
| 175 | *alpha_data = buf + CHUNK_HEADER_SIZE; |
| 176 | *alpha_size = chunk_size; |
| 177 | } |
no test coverage detected