GlyphPatch is a MobileSubstrate tweak which patches a CoreText rendering bug on iOS which makes every app to crash when it encounters a particular sequence of characters.
You can find a debian package file under the releases tab.
As explained in the
characterRangeCodePath() implementation in
Font.cpp, the range from
U+109F includes Arabic characters, among others.
If one of our characters is in that range, we override the original function to return Auto instead of Complex, from the CodePath enum.
Font::drawText() to call
Font::drawSimpleText() instead of
Font::drawComplexText(): this function (implemented in
Font::getGlyphsAndAdvancesForSimpleText() to work and advance with the GlyphBuffer.
On the other end, the original return value of the function would have required
Font::drawText() to call
Font::drawComplexText(), which needs to call
This last function makes use of a
ComplexTextController object: the bug resides in the
ComplexTextController::adjustGlyphsAndAdvances() function, which is called in the initialization of ComplexTextController. (
ComplexTextController::ComplexTextController(const Font*, const TextRun&, bool, HashSet<const SimpleFontData*>*, bool))
Ok, so while the "new approach" described above was a better solution than the first one, it actually made Arabic characters look weird (larger).
That was caused by the fact that the new "rendering path" followed by WebCore was not actually meant for that range of characters and did not include all the details required to rendered that set properly.
The only way this could be avoided was to isolate the malicious character sequence and hijack the rendering path only in that case. This is exactly what I'm doing now.
The following code can be read as follows: "render everything as normal, except if the sequence of characters is the malicious one".
WebCore-1640.27/platform/graphics/mac/ComplexTextController.cpp we find the implementation of void
ComplexTextController::adjustGlyphsAndAdvances(), the function we can see in the crash logs related to the malicious sequence bug. The former approach, explained above, relied on avoiding to call
adjustGlyphsAndAdvances(), hijacking the original rendering behaviour.
But if we dig deeper into
adjustGlyphsAndAdvances(), we get a better understanding of the bug and we also find what's actually causing the memory violation.
Since we're actually speaking of a memory violation, the first thing that came to my mind while looking for an alternative approach (I should have done that from the start) was to look for an "out of bounds" access to an array: in our function, there are 2 main loops through 2 different arrays.
The first one is
m_complexTextRuns, but the bounds are obtained just by asking the number of elements to the
Vector. The second loop iterates over the characters of the
ComplexTextRun& complexTextRun object. The number of characters is given by
ComplexTextRun::glyphCount(), which just returns the
unsigned m_glyphCount variable. Where is this variable set?
By grepping the WebCore source (available on opensource.apple.com) we find out that m_glyphCount is set in
ComplexTextControllerCoreText.mm and it is set as the return value of
Since the m_glyphCount is unsigned, a negative return value would be treated as a huge number: in fact, using particular sequences of characters,
-1, which is actually treated as
4294967295. This makes the loop run over the limit of the array.
Hope this makes sense; if anyone notices there is something wrong, just let me know! :)