[HarfBuzz] [PATCH] hb-old: the allocated scratch memory contains non-zero values that end up interpolated with real offset values
Harshula
harshula at gmail.com
Thu Sep 6 11:26:23 PDT 2012
On Thu, 2012-07-26 at 15:10 -0400, Behdad Esfahbod wrote:
> On 07/26/2012 09:17 AM, Harshula wrote:
> >> > [hb-old] Fix clusters
> >> >
> >> > Unlike its "documentation", hb-old's log_clusters are, well, indeed
> >> > logical, not visual. Fixup. Adapted / copied from hb-uniscribe.
> > This commit seems to have broken Sinhala rendering with FreeSerif font
> > for the following file:
>
> I have a hard time believing that that commit can break shaping at all.
> Specially if you say hb-shape output is the same.
From: Harshula Jayasuriya <harshula at redhat.com>
Date: Fri, 7 Sep 2012 04:04:03 +1000
Subject: [PATCH] hb-old: the allocated scratch memory contains non-zero
values that end up interpolated with real offset values
Reproducer string: ක්යෝ
Reproducer font: FreeSerif.ttf.
In _hb_old_shape(), after HB_ShapeItem() has completed, variable item's
allocated arrays contain the following values for i < num_glyphs:
Bug
---
scratch_size = 640
non-zero int32_t values in scratch (address:index,value): (0x1ecf228:78,36321)
------------------------------------------------------------
i = 0 , glyphs = 2485, attributes = 16 , advances = 707 , x = 0 (0x1ecf220), y = 0 (0x1ecf224)
i = 1 , glyphs = 2435, attributes = 0 , advances = 915 , x = 36321 (0x1ecf228), y = 0 (0x1ecf22c)
i = 2 , glyphs = 9500, attributes = 0 , advances = 508 , x = 0 (0x1ecf230), y = 0 (0x1ecf234)
i = 3 , glyphs = 2477, attributes = 0 , advances = 336 , x = 0 (0x1ecf238), y = 0 (0x1ecf23c)
i = 4 , glyphs = 2476, attributes = 0 , advances = 0 , x = 0 (0x1ecf240), y = 0 (0x1ecf244)
------------------------------------------------------------
=> For i = 1, item.offsets[i].x = 36321.
Working
-------
=> Add a memset(scratch, 0, scratch_size);
scratch_size = 640
non-zero int32_t values in scratch (address:index,value): (0xd6b228:78,36321)
------------------------------------------------------------
i = 0 , glyphs = 2485, attributes = 16 , advances = 707 , x = 0 (0xd6b220), y = 0 (0xd6b224)
i = 1 , glyphs = 2435, attributes = 0 , advances = 915 , x = 0 (0xd6b228), y = 0 (0xd6b22c)
i = 2 , glyphs = 9500, attributes = 0 , advances = 508 , x = 0 (0xd6b230), y = 0 (0xd6b234)
i = 3 , glyphs = 2477, attributes = 0 , advances = 336 , x = 0 (0xd6b238), y = 0 (0xd6b23c)
i = 4 , glyphs = 2476, attributes = 0 , advances = 0 , x = 0 (0xd6b240), y = 0 (0xd6b244)
------------------------------------------------------------
=> For 0 <= i < num_glyphs, item.offsets[i].x and item.offsets[i].y are
zero.
Explanation
-----------
The bug seems to have been inadvertently introduced by commit
91e721ea8693205f4f738bca97a5055ee75cf463. In particular the following
change:
------------------------------------------------------------
+ ALLOCATE_ARRAY (unsigned short, item.log_clusters, chars_len + 2);
- ALLOCATE_ARRAY (unsigned short, item.log_clusters, num_glyphs);
------------------------------------------------------------
The change exposed a non-zero value at a critical memory location.
Without the aforementioned change, the picture looks like:
scratch_size = 640
non-zero int32_t values in scratch (address:index,value): (0xd45228:78,36321)
------------------------------------------------------------
i = 0 , glyphs = 2485, attributes = 16 , advances = 707 , x = 0 (0xd4524a), y = 0 (0xd4524e)
i = 1 , glyphs = 2435, attributes = 0 , advances = 915 , x = 0 (0xd45252), y = 0 (0xd45256)
i = 2 , glyphs = 9500, attributes = 0 , advances = 508 , x = 0 (0xd4525a), y = 0 (0xd4525e)
i = 3 , glyphs = 2477, attributes = 0 , advances = 336 , x = 0 (0xd45262), y = 0 (0xd45266)
i = 4 , glyphs = 2476, attributes = 0 , advances = 0 , x = 0 (0xd4526a), y = 0 (0xd4526e)
------------------------------------------------------------
=> For 0 <= i < num_glyphs, item.offsets[i].x and item.offsets[i].y are
zero.
=> The non-zero value is at address 0xd45228, but item.offsets array
starts only at 0xd4524a.
=> The value of num_glyphs before HB_ShapeItem() is not equal to
num_glyphs afterwards. In this example num_glyphs before HB_ShapeItem()
is 28 and thus the length of the item.offsets array is 28. However,
since the real number of glyphs is 5, the code only cares about the
first 5 elements of the 28 element array.
=> The memset() is added to src/hb-old.cc to avoid it being added to
get_scratch_buffer() in src/hb-buffer.cc because this bug may be
isolated to only the old shaper.
Signed-off-by: Harshula Jayasuriya <harshula at redhat.com>
---
src/hb-old.cc | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/hb-old.cc b/src/hb-old.cc
index 197e620..3410e3b 100644
--- a/src/hb-old.cc
+++ b/src/hb-old.cc
@@ -285,6 +285,7 @@ retry:
unsigned int scratch_size;
char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+ memset(scratch, 0, scratch_size);
#define utf16_index() var1.u32
HB_UChar16 *pchars = (HB_UChar16 *) scratch;
--
1.7.10.4
More information about the HarfBuzz
mailing list