[FFmpeg-devel] libavcodec : add psd image file decoder
Martin Vignali
martin.vignali at gmail.com
Fri Aug 5 14:05:38 EEST 2016
>
>
> > +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
>
Ok i will correct that.
>
>
> [...]
> > +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;
>
For this one i doesn't think there can be an overflow, width can't be > 30
000 (checked before), and pixel_size is 16bit
> > + s->uncompressed_size = s->line_size * s->height * s->channel_count;
>
> Does it seems ok, if i replace unsigned long by uint_64 ?
>
> did you test this code with a fuzzer ?
>
No i didn't know how to do that.
More information about the ffmpeg-devel
mailing list