mirror of
https://github.com/califio/publications.git
synced 2026-10-16 14:59:54 +00:00
Fixing images
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
@@ -33,7 +33,7 @@ Given these changes, we decided to dig deeper into how the Apple system uses the
|
||||
Imagine drawing a big “`d`” on the screen. The shape of the letter is called a glyph, and its outline can be described by a set of vector paths made up of lines and curves. To render a glyph to the screen, the scalable vector paths must undergo rasterization: deciding which pixels on the screen to fill. This is also called scanline conversion, named after the horizontal CRT scan path. If you don’t want your text to look like an Atari game score screen, your rendering engine must support anti-aliasing, which smooths jagged edges by partially coloring pixels along the outline. Anti-aliased rasterization uses a sub-pixel representation to estimate the alpha (or transparency) value of a rendered pixel to effectively blend partial pixels along the border of a shape with the background colors. The larger the percentage of a pixel the path and fill covers, the less transparent the pixel. The CoreGraphics code uses the same underlying code and algorithms to render a font glyph as it would any other path in the rendering engine.
|
||||
|
||||

|
||||
The stages of an anti-aliasing rasterization pipeline when rendering the “d” glyph
|
||||
*The stages of an anti-aliasing rasterization pipeline when rendering the “d” glyph*
|
||||
|
||||
When rendering a glyph to a bitmap, the rasterizer will walk across each scanline (horizontal line of pixels), collect the edges of each path that cross that scanline, and then accumulate the alpha value at each pixel based on how each edge crosses the pixel (including which side of the edge is the filled side). Notice that the rasterizer, to be able to support anti-aliasing, must keep track of the path at a resolution higher than the pixel resolution. It is during this process, computing the alpha mask, that those `aa_*` CoreGraphics functions are used.
|
||||
|
||||
@@ -85,7 +85,7 @@ To reach the patched vulnerable code, we have to ensure the functions are reache
|
||||
|
||||
The first, `ripr_Acquire`, creates the context with the flags set and initializes a device coordinate clipping rectangle via a call to `aa_clipping`. The second, `CGGlyphBitmapCreateWithPathAndDilation`, creates a context with flags clear and never sets up a device coordinate clipping rectangle. In other words, to reach the vulnerable code, we must trigger the rendering of our glyph via `CGGlyphBitmapCreateWithPathAndDilation`.
|
||||
|
||||

|
||||

|
||||
|
||||
After some work with our friendly agent, we found a path between the CoreGraphics font rendering entrypoint and the patched rasterization functions (under macOS for ease of testing). For the harness, we can use `CGContextShowGlyphsAtPositions` to render a glyph from a loaded font file:
|
||||
|
||||
@@ -139,9 +139,10 @@ So far, we’ve proven that we can reach the patched code using CoreGraphics fon
|
||||
|
||||
## Turning the Integer Overflow into Memory Unsafety
|
||||
|
||||
As discussed earlier, one step of the full glyph rendering process includes rendering the glyph path components into an alpha mask bitmap. This process is done via the `aa_cache_render` call. The glyph’s CGPath is constructed inside `CGGlyphBitmapCreateWithPathAndDilation` prior to the aa\_cache\_render call. The rendering call walks the list of edges for each scanline storing an alpha value for each column. After all edges for a single scanline are processed, the alpha mask of the row is used to render the bitmap row.
|
||||
![][image4]
|
||||
Computing the alpha mask for a single scanline of the “d” glyph
|
||||
As discussed earlier, one step of the full glyph rendering process includes rendering the glyph path components into an alpha mask bitmap. This process is done via the `aa_cache_render` call. The glyph’s CGPath is constructed inside `CGGlyphBitmapCreateWithPathAndDilation` prior to the aa\_cache\_render call. The rendering call walks the list of edges for each scanline storing an alpha value for each column. After all edges for a single scanline are processed, the alpha mask of the row is used to render the bitmap row.
|
||||
|
||||

|
||||
*Computing the alpha mask for a single scanline of the “d” glyph*
|
||||
|
||||
The temporary “coverage buffer” is used to track the current scanline’s alpha values across all row intersecting edges. This buffer is allocated early in `aa_cache_render` and reused for each row. The buffer is sized based on the CGPath’s bounding box:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user