Avoid undefined pointer overflow in neon mask opts
When blitting out of a mask with nine patch, the nine patch code may call the blitters with a mask row bytes of zero, with the intention of blitting the same row out of the mask into many rows of the destination. In D32_A8_Opaque_Color_neon and blit_mask_d32_a8_black when SK_ARM_HAS_NEON it is assumed that the maskRB >= width. If the maskRB are less than the width, the maskRB -= width underflows, which is defined, but the later mask += maskRB is not, as this wil be the addition of a very large integer to the mask pointer, which is definitely larger than the mask allocation. In practice on a twos compliment machine with sizeof(size_t) == sizeof(void*) with a flat address space this works out, but it is undefined behavior. When calculating the mask adjustment instead calculate and store it as ptrdiff_t. After ssa, this is effectively the same code but with a signed add to the mask pointer instead of unsigned. Discovered with dm with ASAN (with UBSAN) on arm64 Mac. Change-Id: I4c8967730c802039e192750927e10f13282258b8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/508680 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
c94eb30c6e
commit
b9b550e9bb
@ -50,7 +50,8 @@ namespace SK_OPTS_NS {
|
||||
const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;
|
||||
uint8x8x4_t vpmc;
|
||||
|
||||
maskRB -= width;
|
||||
// Nine patch may set maskRB to 0 to blit the same row repeatedly.
|
||||
ptrdiff_t mask_adjust = (ptrdiff_t)maskRB - width;
|
||||
dstRB -= (width << 2);
|
||||
|
||||
if (width >= 8) {
|
||||
@ -100,7 +101,7 @@ namespace SK_OPTS_NS {
|
||||
}
|
||||
|
||||
device = (uint32_t*)((char*)device + dstRB);
|
||||
mask += maskRB;
|
||||
mask += mask_adjust;
|
||||
|
||||
} while (--height != 0);
|
||||
}
|
||||
@ -125,7 +126,8 @@ namespace SK_OPTS_NS {
|
||||
SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
|
||||
const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;
|
||||
|
||||
maskRB -= width;
|
||||
// Nine patch may set maskRB to 0 to blit the same row repeatedly.
|
||||
ptrdiff_t mask_adjust = (ptrdiff_t)maskRB - width;
|
||||
dstRB -= (width << 2);
|
||||
do {
|
||||
int w = width;
|
||||
@ -150,7 +152,7 @@ namespace SK_OPTS_NS {
|
||||
device += 1;
|
||||
}
|
||||
device = (uint32_t*)((char*)device + dstRB);
|
||||
mask += maskRB;
|
||||
mask += mask_adjust;
|
||||
} while (--height != 0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user