[FFmpeg-devel] libavcodec : add psd image file decoder

Michael Niedermayer michael at niedermayer.cc
Fri Aug 5 13:25:46 EEST 2016


On Thu, Aug 04, 2016 at 05:00:27PM +0200, Martin Vignali wrote:
> >
> > I think you should fail probe with less than 26 bytes
> > or are there smaller files that can be valid ?
> >
> >
> > Fix
> 
> >
> > this is not based on git master
> >
> 
> New patch in attach
> 
> Martin

[...]

> +static int decode_header(PSDContext * s)
> +{
> +    int signature, version, color_mode, len_section, compression;
> +    int ret = 0;
> +
> +    if (bytestream2_get_bytes_left(&s->gb) < 30) {/* File header section + color map data section length */
> +        av_log(s->avctx, AV_LOG_ERROR, "Header too short to parse.\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    signature = bytestream2_get_le32(&s->gb);
> +    if (signature != MKTAG('8','B','P','S')) {
> +        av_log(s->avctx, AV_LOG_ERROR, "Wrong signature %d.\n", signature);
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    version = bytestream2_get_be16(&s->gb);
> +    if (version != 1) {
> +        av_log(s->avctx, AV_LOG_ERROR, "Wrong version %d.\n", version);
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    bytestream2_skip(&s->gb, 6);/* reserved */
> +
> +    s->channel_count = bytestream2_get_be16(&s->gb);
> +    if ((s->channel_count < 1) || (s->channel_count > 56)) {
> +        av_log(s->avctx, AV_LOG_ERROR, "Invalid channel count %d.\n", s->channel_count);
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    s->height = bytestream2_get_be32(&s->gb);
> +
> +    if ((s->height < 1) || (s->height > 30000)) {
> +        av_log(s->avctx, AV_LOG_ERROR, "Invalid height %d.\n", s->height);
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    s->width = bytestream2_get_be32(&s->gb);
> +    if ((s->width < 1) || (s->width > 30000)) {
> +        av_log(s->avctx, AV_LOG_ERROR, "Invalid width %d.\n", s->width);
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    if ((ret = ff_set_dimensions(s->avctx, s->width, s->height)) < 0)
> +        return ret;
> +
> +    s->channel_depth = bytestream2_get_be16(&s->gb);
> +
> +    color_mode = bytestream2_get_be16(&s->gb);
> +    switch (color_mode) {
> +    case 0:
> +        s->color_mode = PSD_BITMAP;
> +        break;
> +    case 1:
> +        s->color_mode = PSD_GRAYSCALE;
> +        break;
> +    case 2:
> +        s->color_mode = PSD_INDEXED;
> +        break;
> +    case 3:
> +        s->color_mode = PSD_RGB;
> +        break;
> +    case 4:
> +        s->color_mode = PSD_CMYK;
> +        break;
> +    case 7:
> +        s->color_mode = PSD_MULTICHANNEL;
> +        break;
> +    case 8:
> +        s->color_mode = PSD_DUOTONE;
> +        break;
> +    case 9:
> +        s->color_mode = PSD_LAB;
> +        break;
> +    default:
> +        av_log(s->avctx, AV_LOG_ERROR, "Unknown color mode %d.\n", color_mode);
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    /* color map data */
> +    len_section = bytestream2_get_be32(&s->gb);
> +    if (bytestream2_get_bytes_left(&s->gb) < (len_section + 4)) { /* section and len next section */

len_section + 4 can overflow, len_section is signed here so can be
negative too


[...]
> +static int decode_frame(AVCodecContext *avctx, void *data,
> +                        int *got_frame, AVPacket *avpkt)
> +{
> +    int ret;
> +    uint8_t *ptr;
> +    const uint8_t * ptr_data;
> +    int index_out, c, y, x, p;
> +
> +    AVFrame *picture = data;
> +
> +    PSDContext *s = avctx->priv_data;
> +    s->avctx     = avctx;
> +    s->channel_count = 0;
> +    s->channel_depth = 0;
> +    s->tmp           = NULL;
> +    s->line_size     = 0;
> +
> +    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
> +
> +    if ((ret = decode_header(s)) < 0)
> +        return ret;
> +
> +    s->pixel_size = s->channel_depth >> 3;/* in byte */

> +    s->line_size = s->width * s->pixel_size;
> +    s->uncompressed_size = s->line_size * s->height * s->channel_count;

cant these multplications overflow ?

did you test this code with a fuzzer ?

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

No human being will ever know the Truth, for even if they happen to say it
by chance, they would not even known they had done so. -- Xenophanes
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20160805/6239d61c/attachment.sig>


More information about the ffmpeg-devel mailing list