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 | 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)); |