summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-11-02 00:48:04 +0100
committerwm4 <wm4@nowhere>2019-11-02 00:48:04 +0100
commit4b3666329e90bec6292566d0d447cefe035c039a (patch)
treeb9be2070e6d897ee1fbc314849e2df6cc6ed4b4e
parent871900f5624db8b6b11deab9932d898f776b10ae (diff)
downloadmpv-4b3666329e90bec6292566d0d447cefe035c039a.tar.bz2
mpv-4b3666329e90bec6292566d0d447cefe035c039a.tar.xz
zimg: fix out of bounds memory accesses due to broken zmask
We've set all planes to the same zmask. But for subsampled chroma, the zmask obviously needs to be smaller. This could lead to out of bounds memory read and write accesses. Move the align repacker to a single function, since this is now more convenient.
-rw-r--r--video/zimg.c76
1 files changed, 37 insertions, 39 deletions
diff --git a/video/zimg.c b/video/zimg.c
index 262e5bd50d..89c99b9f40 100644
--- a/video/zimg.c
+++ b/video/zimg.c
@@ -76,7 +76,7 @@ struct mp_zimg_repack {
struct mp_image_params fmt; // original mp format (possibly packed format)
int zimgfmt; // zimg equivalent unpacked format
int zplanes; // number of planes (zimgfmt)
- unsigned zmask; // zimg_image_buffer.mask
+ unsigned zmask[4]; // zmask[n] = zimg_image_buffer.plane[n].mask
int z_planes[4]; // z_planes[zimg_index] = mp_index
// If set, the pack/unpack callback to pass to zimg.
@@ -214,43 +214,32 @@ void mp_zimg_enable_cmdline_opts(struct mp_zimg_context *ctx,
mp_zimg_update_from_cmdline(ctx); // first update
}
-static void copy_rect(struct mp_image *dst, unsigned dst_mask,
- struct mp_image *src, unsigned src_mask,
- unsigned i, unsigned x0, unsigned x1)
+static int repack_align(void *user, unsigned i, unsigned x0, unsigned x1)
{
- for (int p = 0; p < dst->fmt.num_planes; p++) {
- int bpp = dst->fmt.bytes[p];
- int xs = dst->fmt.xs[p];
- int ys = dst->fmt.ys[p];
+ struct mp_zimg_repack *r = user;
+
+ for (int p = 0; p < r->mpi->fmt.num_planes; p++) {
+ int bpp = r->mpi->fmt.bytes[p];
+ int xs = r->mpi->fmt.xs[p];
+ int ys = r->mpi->fmt.ys[p];
// Number of lines on this plane.
- int h = (1 << dst->fmt.chroma_ys) - (1 << ys) + 1;
+ int h = (1 << r->mpi->fmt.chroma_ys) - (1 << ys) + 1;
for (int y = i; y < i + h; y++) {
- void *psrc = src->planes[p] +
- src->stride[p] * (ptrdiff_t)((y >> ys) & src_mask) +
- bpp * (x0 >> xs);
- void *pdst = dst->planes[p] +
- dst->stride[p] * (ptrdiff_t)((y >> ys) & dst_mask) +
- bpp * (x0 >> xs);
- memcpy(pdst, psrc, ((x1 - x0) >> xs) * bpp);
+ void *a = r->mpi->planes[p] +
+ r->mpi->stride[p] * (ptrdiff_t)(y >> ys) +
+ bpp * (x0 >> xs);
+ void *b = r->tmp->planes[p] +
+ r->tmp->stride[p] * (ptrdiff_t)((y >> ys) & r->zmask[p]) +
+ bpp * (x0 >> xs);
+ size_t size = ((x1 - x0) >> xs) * bpp;
+ if (r->pack) {
+ memcpy(a, b, size);
+ } else {
+ memcpy(b, a, size);
+ }
}
}
-}
-
-static int align_pack(void *user, unsigned i, unsigned x0, unsigned x1)
-{
- struct mp_zimg_repack *r = user;
-
- copy_rect(r->mpi, ZIMG_BUFFER_MAX, r->tmp, r->zmask, i, x0, x1);
-
- return 0;
-}
-
-static int align_unpack(void *user, unsigned i, unsigned x0, unsigned x1)
-{
- struct mp_zimg_repack *r = user;
-
- copy_rect(r->tmp, r->zmask, r->mpi, ZIMG_BUFFER_MAX, i, x0, x1);
return 0;
}
@@ -351,7 +340,8 @@ static int packed_repack(void *user, unsigned i, unsigned x0, unsigned x1)
void *p2[3];
for (int p = 0; p < 3; p++) {
int s = r->components[p];
- p2[p] = r->tmp->planes[s] + r->tmp->stride[s] * (ptrdiff_t)(i & r->zmask);
+ p2[p] = r->tmp->planes[s] +
+ r->tmp->stride[s] * (ptrdiff_t)(i & r->zmask[s]);
}
r->packed_repack_scanline(p1, p2, x0, x1);
@@ -379,7 +369,7 @@ static void wrap_buffer(struct mp_zimg_repack *r,
if (aligned) {
wrap_mpi = mpi;
} else {
- *cb = r->pack ? align_pack : align_unpack;
+ *cb = repack_align;
}
}
@@ -387,7 +377,7 @@ static void wrap_buffer(struct mp_zimg_repack *r,
int mplane = r->z_planes[n];
buf->plane[n].data = wrap_mpi->planes[mplane];
buf->plane[n].stride = wrap_mpi->stride[mplane];
- buf->plane[n].mask = wrap_mpi == mpi ? ZIMG_BUFFER_MAX : r->zmask;
+ buf->plane[n].mask = wrap_mpi == mpi ? ZIMG_BUFFER_MAX : r->zmask[n];
}
r->mpi = mpi;
@@ -584,20 +574,28 @@ static bool allocate_buffer(struct mp_zimg_context *ctx,
if (err)
return false;
- r->zmask = zimg_select_buffer_mask(lines);
+ r->zmask[0] = zimg_select_buffer_mask(lines);
// Either ZIMG_BUFFER_MAX, or a power-of-2 slice buffer.
- assert(r->zmask == ZIMG_BUFFER_MAX || MP_IS_POWER_OF_2(r->zmask + 1));
+ assert(r->zmask[0] == ZIMG_BUFFER_MAX || MP_IS_POWER_OF_2(r->zmask[0] + 1));
- int h = r->zmask == ZIMG_BUFFER_MAX ? r->fmt.h : r->zmask + 1;
+ int h = r->zmask[0] == ZIMG_BUFFER_MAX ? r->fmt.h : r->zmask[0] + 1;
if (h >= r->fmt.h) {
h = r->fmt.h;
- r->zmask = ZIMG_BUFFER_MAX;
+ r->zmask[0] = ZIMG_BUFFER_MAX;
}
r->tmp = mp_image_alloc(r->zimgfmt, r->fmt.w, h);
talloc_steal(r, r->tmp);
+ if (r->tmp) {
+ for (int n = 1; n < r->tmp->fmt.num_planes; n++) {
+ r->zmask[n] = r->zmask[0];
+ if (r->zmask[0] != ZIMG_BUFFER_MAX)
+ r->zmask[n] = r->zmask[n] >> r->tmp->fmt.ys[n];
+ }
+ }
+
return !!r->tmp;
}