It was possible for the buffer pointers for the last tile to go over the end of the unit buffer leading to a read overflow during decode of the macroblock layer. Check all tile component sizes to prevent this case and also catch related tile size mismatch errors earlier.
Unified · Split
| @@ -189,10 +189,12 @@ static int FUNC(frame_header)(CodedBitstreamContext *ctx, RWContext *rw, · 188 unmodified lines | ||
| 189 | 189 | } |
| 190 | 190 | |
| 191 | 191 | static int FUNC(tile_header)(CodedBitstreamContext *ctx, RWContext *rw, |
| 192 | − APVRawTileHeader *current, int tile_idx) | |
| 192 | + APVRawTileHeader *current, | |
| 193 | + int tile_idx, uint32_t tile_size) | |
| 193 | 194 | { |
| 194 | 195 | const CodedBitstreamAPVContext *priv = ctx->priv_data; |
| 195 | 196 | uint16_t expected_tile_header_size; |
| 197 | + uint32_t tile_size_remaining; | |
| 196 | 198 | uint8_t max_qp; |
| 197 | 199 | int err; |
| 198 | 200 | |
| @@ -203,8 +205,10 @@ static int FUNC(tile_header)(CodedBitstreamContext *ctx, RWContext *rw, · 4 unmodified lines | ||
| 203 | 205 | |
| 204 | 206 | u(16, tile_index, tile_idx, tile_idx); |
| 205 | 207 | |
| 208 | + tile_size_remaining = tile_size - current->tile_header_size; | |
| 206 | 209 | for (int c = 0; c < priv->num_comp; c++) { |
| 207 | − us(32, tile_data_size[c], 1, MAX_UINT_BITS(32), 1, c); | |
| 210 | + us(32, tile_data_size[c], 1, tile_size_remaining, 1, c); | |
| 211 | + tile_size_remaining -= current->tile_data_size[c]; | |
| 208 | 212 | } |
| 209 | 213 | |
| 210 | 214 | max_qp = 3 + priv->bit_depth * 6; |
| @@ -218,12 +222,14 @@ static int FUNC(tile_header)(CodedBitstreamContext *ctx, RWContext *rw, · 7 unmodified lines | ||
| 218 | 222 | } |
| 219 | 223 | |
| 220 | 224 | static int FUNC(tile)(CodedBitstreamContext *ctx, RWContext *rw, |
| 221 | − APVRawTile *current, int tile_idx) | |
| 225 | + APVRawTile *current, | |
| 226 | + int tile_idx, uint32_t tile_size) | |
| 222 | 227 | { |
| 223 | 228 | const CodedBitstreamAPVContext *priv = ctx->priv_data; |
| 224 | 229 | int err; |
| 225 | 230 | |
| 226 | − CHECK(FUNC(tile_header)(ctx, rw, ¤t->tile_header, tile_idx)); | |
| 231 | + CHECK(FUNC(tile_header)(ctx, rw, ¤t->tile_header, | |
| 232 | + tile_idx, tile_size)); | |
| 227 | 233 | |
| 228 | 234 | for (int c = 0; c < priv->num_comp; c++) { |
| 229 | 235 | uint32_t comp_size = current->tile_header.tile_data_size[c]; |
| @@ -257,7 +263,8 @@ static int FUNC(frame)(CodedBitstreamContext *ctx, RWContext *rw, · 27 unmodified lines | ||
| 257 | 263 | for (int t = 0; t < priv->tile_info.num_tiles; t++) { |
| 258 | 264 | us(32, tile_size[t], 10, MAX_UINT_BITS(32), 1, t); |
| 259 | 265 | |
| 260 | − CHECK(FUNC(tile)(ctx, rw, ¤t->tile[t], t)); | |
| 266 | + CHECK(FUNC(tile)(ctx, rw, ¤t->tile[t], | |
| 267 | + t, current->tile_size[t])); | |
| 261 | 268 | } |
| 262 | 269 | |
| 263 | 270 | CHECK(FUNC(filler)(ctx, rw, ¤t->filler)); |