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.
Showing the changes to libavcodec (1 of 1 file). Show all
Unified · Split
| @@ -189,10 +189,12 @@ static int FUNC(frame_header)(CodedBitstreamContext *ctx, RWContext *rw, · 188 unmodified lines | |||
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | static int FUNC(tile_header)(CodedBitstreamContext *ctx, RWContext *rw, | 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 | const CodedBitstreamAPVContext *priv = ctx->priv_data; | 195 | const CodedBitstreamAPVContext *priv = ctx->priv_data; |
| 195 | uint16_t expected_tile_header_size; | 196 | uint16_t expected_tile_header_size; |
| 197 | uint32_t tile_size_remaining; | ||
| 196 | uint8_t max_qp; | 198 | uint8_t max_qp; |
| 197 | int err; | 199 | int err; |
| 198 | 200 | ||
| @@ -203,8 +205,10 @@ static int FUNC(tile_header)(CodedBitstreamContext *ctx, RWContext *rw, · 4 unmodified lines | |||
| 203 | 205 | ||
| 204 | u(16, tile_index, tile_idx, tile_idx); | 206 | u(16, tile_index, tile_idx, tile_idx); |
| 205 | 207 | ||
| 208 | tile_size_remaining = tile_size - current->tile_header_size; | ||
| 206 | for (int c = 0; c < priv->num_comp; c++) { | 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 | max_qp = 3 + priv->bit_depth * 6; | 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 | static int FUNC(tile)(CodedBitstreamContext *ctx, RWContext *rw, | 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 | const CodedBitstreamAPVContext *priv = ctx->priv_data; | 228 | const CodedBitstreamAPVContext *priv = ctx->priv_data; |
| 224 | int err; | 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 | for (int c = 0; c < priv->num_comp; c++) { | 234 | for (int c = 0; c < priv->num_comp; c++) { |
| 229 | uint32_t comp_size = current->tile_header.tile_data_size[c]; | 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 | for (int t = 0; t < priv->tile_info.num_tiles; t++) { | 263 | for (int t = 0; t < priv->tile_info.num_tiles; t++) { |
| 258 | us(32, tile_size[t], 10, MAX_UINT_BITS(32), 1, t); | 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 | CHECK(FUNC(filler)(ctx, rw, ¤t->filler)); | 270 | CHECK(FUNC(filler)(ctx, rw, ¤t->filler)); |