From: Michał Janiszewski janisozaur@gmail.com
Some fonts (e.g. Courier) may cause sfnt2fon try reading past end of heap-allocated buffer. Rather than reading from uninitialised memory, return 0 in such case.
Visual tests on .fon render of this font (using FontForge) shown no artifacts. --- tools/sfnt2fon/sfnt2fon.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/tools/sfnt2fon/sfnt2fon.c b/tools/sfnt2fon/sfnt2fon.c index 25f0763872..fb125bbeaf 100644 --- a/tools/sfnt2fon/sfnt2fon.c +++ b/tools/sfnt2fon/sfnt2fon.c @@ -570,11 +570,14 @@ static struct fontinfo *fill_fontinfo( const char *face_name, int ppem, int enc, else left_byte = face->glyph->bitmap.buffer[(y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off - 1];
+ int x_idx = (y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off; + // FreeType allocates that many bytes for bitmap, but some fonts (e.g. Courier) might try reading past the buffer + int x_limit = face->glyph->bitmap.rows * face->glyph->bitmap.pitch; /* On the last non-trivial output byte (x == x_end) have we got one or two input bytes */ - if(x == x_end && (face->glyph->bitmap_left % 8 != 0) && ((face->glyph->bitmap.width % 8 == 0) || (x != (((face->glyph->bitmap.width) & ~0x7) + face->glyph->bitmap_left) / 8))) + if((x_idx >= x_limit) || (x == x_end && (face->glyph->bitmap_left % 8 != 0) && ((face->glyph->bitmap.width % 8 == 0) || (x != (((face->glyph->bitmap.width) & ~0x7) + face->glyph->bitmap_left) / 8)))) right_byte = 0; else - right_byte = face->glyph->bitmap.buffer[(y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off]; + right_byte = face->glyph->bitmap.buffer[x_idx];
byte = (left_byte << (8 - (face->glyph->bitmap_left & 7))) & 0xff; byte |= ((right_byte >> (face->glyph->bitmap_left & 7)) & 0xff);
On Tue, Jul 24, 2018 at 1:03 PM, janisozaur@gmail.com wrote:
From: Michał Janiszewski janisozaur@gmail.com
Some fonts (e.g. Courier) may cause sfnt2fon try reading past end of heap-allocated buffer. Rather than reading from uninitialised memory, return 0 in such case.
Visual tests on .fon render of this font (using FontForge) shown no artifacts.
tools/sfnt2fon/sfnt2fon.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/tools/sfnt2fon/sfnt2fon.c b/tools/sfnt2fon/sfnt2fon.c index 25f0763872..fb125bbeaf 100644 --- a/tools/sfnt2fon/sfnt2fon.c +++ b/tools/sfnt2fon/sfnt2fon.c @@ -570,11 +570,14 @@ static struct fontinfo *fill_fontinfo( const char *face_name, int ppem, int enc, else left_byte = face->glyph->bitmap.buffer[(y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off - 1];
int x_idx = (y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off;
// FreeType allocates that many bytes for bitmap, but some fonts (e.g. Courier) might try reading past the buffer
int x_limit = face->glyph->bitmap.rows * face->glyph->bitmap.pitch; /* On the last non-trivial output byte (x == x_end) have we got one or two input bytes */
if(x == x_end && (face->glyph->bitmap_left % 8 != 0) && ((face->glyph->bitmap.width % 8 == 0) || (x != (((face->glyph->bitmap.width) & ~0x7) + face->glyph->bitmap_left) / 8)))
if((x_idx >= x_limit) || (x == x_end && (face->glyph->bitmap_left % 8 != 0) && ((face->glyph->bitmap.width % 8 == 0) || (x != (((face->glyph->bitmap.width) & ~0x7) + face->glyph->bitmap_left) / 8)))) right_byte = 0; else
right_byte = face->glyph->bitmap.buffer[(y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off];
right_byte = face->glyph->bitmap.buffer[x_idx]; byte = (left_byte << (8 - (face->glyph->bitmap_left & 7))) & 0xff; byte |= ((right_byte >> (face->glyph->bitmap_left & 7)) & 0xff);
-- 2.18.0
Hi Michal,
Thanks for the patch. A couple things: A) It's causing a warning when building: sfnt2fon.c: In function 'fill_fontinfo': sfnt2fon.c:573:17: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] int x_idx = (y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off; ^~~ B) C++ style comments (//) aren't used in wine, please use C89 (/* comment */)
BTW, I thought that code looked familiar. It turns out this also fixes a bug that AddressSanitizer/Valgrind report, https://bugs.winehq.org/show_bug.cgi?id=45422. With it, I can build wine's fonts under AddressSanitizer, thanks!