video: check image parameters

Make sure every video filter has valid parameters for input and output.
(This also ensures we don't take possibly invalid decoder output, or
feed invalid decodr/filter output to VOs.)

Also, the updated image size check now (almost) works like the
corresponding check in FFmpeg.
This commit is contained in:
wm4 2014-06-17 22:44:13 +02:00
parent 72aac9ae8a
commit d107cae0e7
3 changed files with 38 additions and 4 deletions

View File

@ -568,6 +568,9 @@ static int vf_reconfig_wrapper(struct vf_instance *vf,
vf->fmt_out = vf->fmt_in = *p; vf->fmt_out = vf->fmt_in = *p;
if (!mp_image_params_valid(&vf->fmt_in))
return -2;
int r; int r;
if (vf->reconfig) { if (vf->reconfig) {
r = vf->reconfig(vf, &vf->fmt_in, &vf->fmt_out); r = vf->reconfig(vf, &vf->fmt_in, &vf->fmt_out);
@ -580,6 +583,9 @@ static int vf_reconfig_wrapper(struct vf_instance *vf,
if (!mp_image_params_equals(&vf->fmt_in, p)) if (!mp_image_params_equals(&vf->fmt_in, p))
r = -2; r = -2;
if (!mp_image_params_valid(&vf->fmt_out))
r = -2;
// Fix csp in case of pixel format change // Fix csp in case of pixel format change
if (r >= 0) if (r >= 0)
mp_image_params_guess_csp(&vf->fmt_out); mp_image_params_guess_csp(&vf->fmt_out);

View File

@ -21,6 +21,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include <pthread.h> #include <pthread.h>
#include <assert.h> #include <assert.h>
@ -121,6 +122,9 @@ static bool mp_image_alloc_planes(struct mp_image *mpi)
{ {
assert(!mpi->planes[0]); assert(!mpi->planes[0]);
if (!mp_image_params_valid(&mpi->params))
return false;
// Note: for non-mod-2 4:2:0 YUV frames, we have to allocate an additional // Note: for non-mod-2 4:2:0 YUV frames, we have to allocate an additional
// top/right border. This is needed for correct handling of such // top/right border. This is needed for correct handling of such
// images in filter and VO code (e.g. vo_vdpau or vo_opengl). // images in filter and VO code (e.g. vo_vdpau or vo_opengl).
@ -177,10 +181,7 @@ static int mp_chroma_div_up(int size, int shift)
// Caller has to make sure this doesn't exceed the allocated plane data/strides. // Caller has to make sure this doesn't exceed the allocated plane data/strides.
void mp_image_set_size(struct mp_image *mpi, int w, int h) void mp_image_set_size(struct mp_image *mpi, int w, int h)
{ {
// av_image_check_size has similar checks and triggers around 16000*16000 assert(w >= 0 && h >= 0);
if (w >= (1 << 14) || h >= (1 << 14) || w < 0 || h < 0)
abort();
mpi->w = mpi->params.w = mpi->params.d_w = w; mpi->w = mpi->params.w = mpi->params.d_w = w;
mpi->h = mpi->params.h = mpi->params.d_h = h; mpi->h = mpi->params.h = mpi->params.d_h = h;
for (int n = 0; n < mpi->num_planes; n++) { for (int n = 0; n < mpi->num_planes; n++) {
@ -450,6 +451,32 @@ void mp_image_vflip(struct mp_image *img)
} }
} }
// Return whether the image parameters are valid.
// Some non-essential fields are allowed to be unset (like colorspace flags).
bool mp_image_params_valid(const struct mp_image_params *p)
{
// av_image_check_size has similar checks and triggers around 16000*16000
// It's mostly needed to deal with the fact that offsets are sometimes
// ints. We also should (for now) do the same as FFmpeg, to be sure large
// images don't crash with libswscale or when wrapping with AVFrame and
// passing the result to filters.
// Unlike FFmpeg, consider 0x0 valid (might be needed for OSD/screenshots).
if (p->w < 0 || p->h < 0 || (p->w + 128LL) * (p->h + 128LL) >= INT_MAX / 8)
return false;
if (p->d_w < 0 || p->d_h < 0)
return false;
if (p->rotate < 0 || p->rotate >= 360)
return false;
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(p->imgfmt);
if (!desc.id)
return false;
return true;
}
bool mp_image_params_equals(const struct mp_image_params *p1, bool mp_image_params_equals(const struct mp_image_params *p1,
const struct mp_image_params *p2) const struct mp_image_params *p2)
{ {

View File

@ -139,6 +139,7 @@ struct mp_image *mp_image_new_external_ref(struct mp_image *img, void *arg,
void mp_image_params_guess_csp(struct mp_image_params *params); void mp_image_params_guess_csp(struct mp_image_params *params);
bool mp_image_params_valid(const struct mp_image_params *p);
bool mp_image_params_equals(const struct mp_image_params *p1, bool mp_image_params_equals(const struct mp_image_params *p1,
const struct mp_image_params *p2); const struct mp_image_params *p2);