static int parse_object_segment(AVCodecContext *avctx, const uint8_t *buf, int buf_size) { PGSSubContext *ctx = avctx->priv_data; PGSSubObject *object; uint8_t sequence_desc; unsigned int rle_bitmap_len, width, height; int id; if (buf_size <= 4) return AVERROR_INVALIDDATA; buf_size -= 4; id = bytestream_get_be16(&buf); object = find_object(id, &ctx->objects); if (!object) { if (ctx->objects.count >= MAX_EPOCH_OBJECTS) { av_log(avctx, AV_LOG_ERROR, "Too many objects in epoch\n"); return AVERROR_INVALIDDATA; } object = &ctx->objects.object[ctx->objects.count++]; object->id = id; } /* skip object version number */ buf += 1; /* Read the Sequence Description to determine if start of RLE data or appended to previous RLE */ sequence_desc = bytestream_get_byte(&buf); if (!(sequence_desc & 0x80)) { /* Additional RLE data */ if (buf_size > object->rle_remaining_len) return AVERROR_INVALIDDATA; memcpy(object->rle + object->rle_data_len, buf, buf_size); object->rle_data_len += buf_size; object->rle_remaining_len -= buf_size; return 0; } if (buf_size <= 7) return AVERROR_INVALIDDATA; buf_size -= 7; /* Decode rle bitmap length, stored size includes width/height data */ rle_bitmap_len = bytestream_get_be24(&buf) - 2*2; if (buf_size > rle_bitmap_len) { av_log(avctx, AV_LOG_ERROR, "Buffer dimension %d larger than the expected RLE data %d\n", buf_size, rle_bitmap_len); return AVERROR_INVALIDDATA; } /* Get bitmap dimensions from data */ width = bytestream_get_be16(&buf); height = bytestream_get_be16(&buf); /* Make sure the bitmap is not too large */ if (avctx->width < width || avctx->height < height || !width || !height) { av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions (%dx%d) invalid.\n", width, height); return AVERROR_INVALIDDATA; } object->w = width; object->h = height; av_fast_padded_malloc(&object->rle, &object->rle_buffer_size, rle_bitmap_len); if (!object->rle) return AVERROR(ENOMEM); memcpy(object->rle, buf, buf_size); object->rle_data_len = buf_size; object->rle_remaining_len = rle_bitmap_len - buf_size; return 0; }