[FFmpeg-devel] [PATCH] Add CPiA video decoder

Michael Niedermayer michaelni at gmx.at
Thu Aug 30 19:09:15 CEST 2012


On Thu, Aug 30, 2012 at 11:34:03AM +0200, Stephan Hilb wrote:
> My bad, I missed to remove the reference to the cpia_decode_end
> function, now fixed.
> 

[...]

> +static int cpia_decode_frame(AVCodecContext* avctx,
> +        void* data, int* data_size, AVPacket* avpkt)
> +{
> +    CpiaContext* const cpia = avctx->priv_data;
> +    int i,j;
> +
> +    uint8_t* const header = avpkt->data;
> +    uint8_t* src;
> +    int src_size;
> +    uint16_t linelength;
> +    uint8_t skip;
> +
> +    AVFrame* const frame = &cpia->frame;
> +    uint8_t *y, *u, *v;
> +
> +    // Get buffer filled with previous frame

> +    if (avctx->reget_buffer(avctx, frame)) {
> +        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed!\n");
> +        return -1;
> +    }

the error code from reget_buffer could be used as return


> +
> +    // Check header
> +    if (    avpkt->size < FRAME_HEADER_SIZE
> +        ||    header[0] != MAGIC_0 || header[1] != MAGIC_1
> +        ||    (header[17] != SUBSAMPLE_420 && header[17] != SUBSAMPLE_422)
> +        ||    (header[18] != YUVORDER_YUYV && header[18] != YUVORDER_UYVY)
> +        ||    (header[28] != NOT_COMPRESSED && header[28] != COMPRESSED)
> +        ||    (header[29] != NO_DECIMATION && header[29] != DECIMATION_ENAB)
> +    ) {
> +        av_log(avctx, AV_LOG_ERROR, "Invalid header!\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +

> +    // currently unsupported properties
> +    if (header[17] == SUBSAMPLE_422) {
> +        av_log(avctx, AV_LOG_ERROR, "Unsupported subsample!\n");
> +        return -1;
> +    }
> +    if (header[18] == YUVORDER_UYVY) {
> +        av_log(avctx, AV_LOG_ERROR, "Unsupported YUV byte order!\n");
> +        return -1;
> +    }
> +    if (header[29] == DECIMATION_ENAB) {
> +        av_log(avctx, AV_LOG_ERROR, "Decimation unsupported!\n");
> +        return -1;
> +    }

the return codes could be changed to AVERROR_PATCHWELCOME


> +
> +    src = header + FRAME_HEADER_SIZE;
> +    src_size = avpkt->size - FRAME_HEADER_SIZE;
> +
> +    if (header[28] == NOT_COMPRESSED) {
> +        frame->pict_type = AV_PICTURE_TYPE_I;
> +        frame->key_frame = 1;
> +    } else {
> +        frame->pict_type = AV_PICTURE_TYPE_P;
> +        frame->key_frame = 0;
> +    }
> +
> +
> +    for ( i = 0;
> +          i < frame->height;
> +          i++, src += linelength, src_size -= linelength
> +    ) {
> +        // Read line length, two byte little endian
> +        linelength = AV_RL16(src);
> +        src += 2;
> +
> +        if (src_size < linelength) {
> +            frame->decode_error_flags = FF_DECODE_ERROR_INVALID_BITSTREAM;
> +            av_log(avctx, AV_LOG_WARNING, "Frame ended enexpectedly!\n");
> +            break;
> +        }
> +        if (src[linelength - 1] != EOL) {
> +            frame->decode_error_flags = FF_DECODE_ERROR_INVALID_BITSTREAM;
> +            av_log(avctx, AV_LOG_WARNING, "Wrong line length %d or line not terminated properly (found 0x%02x)!\n", linelength, src[linelength - 1]);
> +            break;
> +        }
> +
> +        /* Update the data pointers. Y data is on every line.
> +         * U and V data on every second line
> +         */
> +        y = &frame->data[0][i * frame->linesize[0]];
> +        u = &frame->data[1][(i >> 1) * frame->linesize[1]];
> +        v = &frame->data[2][(i >> 1) * frame->linesize[2]];
> +

> +        if ((i & 1) && header[17] == SUBSAMPLE_420) {
> +            /* We are on a odd line and 420 subsample is used.
> +             * On this line only Y values are specified, one per pixel.
> +             */
> +            for (j = 0; j < linelength - 1; j++) {
> +                if (src[j] & 1 && header[28] == COMPRESSED) {
> +                    /* It seems that odd lines are always uncompressed, but
> +                     * we do it according to specification anyways.
> +                     */
> +                    skip = src[j] >> 1;
> +                    y += skip;
> +                } else {
> +                    *(y++) = src[j];
> +                }
> +            }

This looks exploitable, there is no check that  the writes are within
the picture
the same issue exists in the u/v code

also if you like to be the official maintainer of this, then add
yourself to MAINTAINERS

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

If a bugfix only changes things apparently unrelated to the bug with no
further explanation, that is a good sign that the bugfix is wrong.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120830/a12ce506/attachment.asc>


More information about the ffmpeg-devel mailing list