diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/gcx/gcbv/gcparser.c | 58 |
1 files changed, 41 insertions, 17 deletions
diff --git a/drivers/misc/gcx/gcbv/gcparser.c b/drivers/misc/gcx/gcbv/gcparser.c index 609c862..0f1a758 100644 --- a/drivers/misc/gcx/gcbv/gcparser.c +++ b/drivers/misc/gcx/gcbv/gcparser.c @@ -1270,6 +1270,7 @@ static inline bool valid_rect(struct bvsurfgeom *bvsurfgeom, static bool valid_geom(struct surfaceinfo *surfaceinfo) { unsigned int size; + unsigned int height; /* Compute the size of the surface. */ size = (surfaceinfo->geom->width * @@ -1290,6 +1291,29 @@ static bool valid_geom(struct surfaceinfo *surfaceinfo) return false; } + /* Determine the height of the image. */ + height = ((surfaceinfo->angle % 2) == 0) + ? surfaceinfo->geom->height + : surfaceinfo->geom->width; + + /* Compute the size using the stide. */ + size = surfaceinfo->geom->virtstride * height; + + /* Make sure the size is not greater then the surface. */ + if (size > surfaceinfo->buf.desc->length) { + GCERR("invalid geometry detected:\n"); + GCERR(" specified dimensions: %dx%d, %d bitspp\n", + surfaceinfo->geom->width, + surfaceinfo->geom->height, + surfaceinfo->format.bitspp); + GCERR(" physical image height = %d\n", height); + GCERR(" image stride = %d\n", surfaceinfo->geom->virtstride); + GCERR(" computed surface size = %d\n", size); + GCERR(" specified surface size: %lu\n", + surfaceinfo->buf.desc->length); + return false; + } + return true; } @@ -1379,13 +1403,6 @@ enum bverror parse_destination(struct bvbltparams *bvbltparams, goto exit; } - /* Validate geometry. */ - if (!valid_geom(dstinfo)) { - BVSETBLTERROR(BVERR_DSTGEOM, - "destination geom exceeds surface size"); - goto exit; - } - /* Destination stride must be 8 pixel aligned. */ if ((dstinfo->geom->virtstride & (dstinfo->format.bitspp - 1)) != 0) { @@ -1433,6 +1450,13 @@ enum bverror parse_destination(struct bvbltparams *bvbltparams, dstinfo->pixalign); GCDBG(GCZONE_DEST, " surface offset (bytes) = %d\n", dstinfo->bytealign); + + /* Validate geometry. */ + if (!valid_geom(dstinfo)) { + BVSETBLTERROR(BVERR_DSTGEOM, + "destination geom exceeds surface size"); + goto exit; + } } /* Did clipping/destination rects change? */ @@ -1737,16 +1761,6 @@ enum bverror parse_source(struct bvbltparams *bvbltparams, goto exit; } - /* Validate source geometry. */ - if (!valid_geom(srcinfo)) { - BVSETBLTERROR((srcinfo->index == 0) - ? BVERR_SRC1GEOM - : BVERR_SRC2GEOM, - "source%d geom exceeds surface size.", - srcinfo->index + 1); - goto exit; - } - /* Source must be 8 pixel aligned. */ if ((srcinfo->geom->virtstride & (srcinfo->format.bitspp - 1)) != 0) { @@ -1820,6 +1834,16 @@ enum bverror parse_source(struct bvbltparams *bvbltparams, srcinfo->geom->width, srcinfo->geom->height); GCDBG(GCZONE_SRC, " mirror = %d\n", srcinfo->mirror); + /* Validate source geometry. */ + if (!valid_geom(srcinfo)) { + BVSETBLTERROR((srcinfo->index == 0) + ? BVERR_SRC1GEOM + : BVERR_SRC2GEOM, + "source%d geom exceeds surface size.", + srcinfo->index + 1); + goto exit; + } + exit: return bverror; } |