Merge commit 'e8c4db0d4d07738fed716b1d2f20c85aac944641'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 30 Apr 2015 20:15:16 +0000 (22:15 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 30 Apr 2015 20:15:22 +0000 (22:15 +0200)
* commit 'e8c4db0d4d07738fed716b1d2f20c85aac944641':
  xcbgrab: Validate the capture area

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavdevice/xcbgrab.c

diff --combined libavdevice/xcbgrab.c
index 287899541212673d8a82b901b1c73cede1ff73f2,3de4b00a54006062ee43e2572dace9afb722bc00..15512cd15fa33e53fb3feb0059967f83e279dfe9
@@@ -2,20 -2,20 +2,20 @@@
   * XCB input grabber
   * Copyright (C) 2014 Luca Barbato <lu_zero@gentoo.org>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include <xcb/shm.h>
  #endif
  
 +#if CONFIG_LIBXCB_SHAPE
 +#include <xcb/shape.h>
 +#endif
 +
  #include "libavutil/internal.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/opt.h"
@@@ -100,7 -96,6 +100,7 @@@ static const AVClass xcbgrab_class = 
      .item_name  = av_default_item_name,
      .option     = options,
      .version    = LIBAVUTIL_VERSION_INT,
 +    .category   = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
  };
  
  static int xcbgrab_reposition(AVFormatContext *s,
@@@ -473,11 -468,11 +473,11 @@@ static int pixfmt_from_pixmap_format(AV
              switch (depth) {
              case 32:
                  if (fmt->bits_per_pixel == 32)
 -                    *pix_fmt = AV_PIX_FMT_ARGB;
 +                    *pix_fmt = AV_PIX_FMT_0RGB;
                  break;
              case 24:
                  if (fmt->bits_per_pixel == 32)
 -                    *pix_fmt = AV_PIX_FMT_RGB32;
 +                    *pix_fmt = AV_PIX_FMT_0RGB32;
                  else if (fmt->bits_per_pixel == 24)
                      *pix_fmt = AV_PIX_FMT_RGB24;
                  break;
@@@ -533,8 -528,17 +533,17 @@@ static int create_stream(AVFormatContex
      gc  = xcb_get_geometry(c->conn, c->screen->root);
      geo = xcb_get_geometry_reply(c->conn, gc, NULL);
  
-     c->width      = FFMIN(geo->width, c->width);
-     c->height     = FFMIN(geo->height, c->height);
+     if (c->x + c->width >= geo->width ||
+         c->y + c->height >= geo->height) {
+         av_log(s, AV_LOG_ERROR,
+                "Capture area %dx%d at position %d.%d "
+                "outside the screen size %dx%d\n",
+                c->width, c->height,
+                c->x, c->y,
+                geo->width, geo->height);
+         return AVERROR(EINVAL);
+     }
      c->time_base  = (AVRational){ st->avg_frame_rate.den,
                                    st->avg_frame_rate.num };
      c->time_frame = av_gettime();
@@@ -598,13 -602,11 +607,13 @@@ static void setup_window(AVFormatContex
                        XCB_COPY_FROM_PARENT,
                        mask, values);
  
 +#if CONFIG_LIBXCB_SHAPE
      xcb_shape_rectangles(c->conn, XCB_SHAPE_SO_SUBTRACT,
                           XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
                           c->window,
                           c->region_border, c->region_border,
                           1, &rect);
 +#endif
  
      xcb_map_window(c->conn, c->window);
  
@@@ -616,25 -618,30 +625,25 @@@ static av_cold int xcbgrab_read_header(
      XCBGrabContext *c = s->priv_data;
      int screen_num, ret;
      const xcb_setup_t *setup;
 -    char *host        = s->filename[0] ? s->filename : NULL;
 -    const char *opts  = strchr(s->filename, '+');
 -
 -    if (opts) {
 -        sscanf(opts, "%d,%d", &c->x, &c->y);
 -        host = av_strdup(s->filename);
 -        if (!host)
 -            return AVERROR(ENOMEM);
 -        host[opts - s->filename] = '\0';
 +    char *display_name = av_strdup(s->filename);
 +
 +    if (!display_name)
 +        return AVERROR(ENOMEM);
 +
 +    if (!sscanf(s->filename, "%[^+]+%d,%d", display_name, &c->x, &c->y)) {
 +        *display_name = 0;
 +        sscanf(s->filename, "+%d,%d", &c->x, &c->y);
      }
  
 -    c->conn = xcb_connect(host, &screen_num);
 +    c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num);
 +    av_freep(&display_name);
  
      if ((ret = xcb_connection_has_error(c->conn))) {
          av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n",
 -               s->filename[0] ? host : "default", ret);
 -        if (opts)
 -            av_freep(&host);
 +               s->filename[0] ? s->filename : "default", ret);
          return AVERROR(EIO);
      }
  
 -    if (opts)
 -        av_freep(&host);
 -
      setup = xcb_get_setup(c->conn);
  
      c->screen = get_screen(setup, screen_num);