summaryrefslogtreecommitdiffstats
path: root/gfx/thebes/gfxFontUtils.cpp
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-07-02 17:51:09 +0200
committerwolfbeast <mcwerewolf@gmail.com>2018-07-02 17:51:09 +0200
commit4c9914227ed9e675d65ad16e0bb899e8107a0ee5 (patch)
treed4c542f51b5155eb3f3627c628686cfc0d648a2f /gfx/thebes/gfxFontUtils.cpp
parentde01f1e7fce43d5919e6adcd73dfa617a9087520 (diff)
parentaa6329b694a981dccd5b0fd124936c4b54fb94a4 (diff)
downloadUXP-4c9914227ed9e675d65ad16e0bb899e8107a0ee5.tar
UXP-4c9914227ed9e675d65ad16e0bb899e8107a0ee5.tar.gz
UXP-4c9914227ed9e675d65ad16e0bb899e8107a0ee5.tar.lz
UXP-4c9914227ed9e675d65ad16e0bb899e8107a0ee5.tar.xz
UXP-4c9914227ed9e675d65ad16e0bb899e8107a0ee5.zip
Merge branch 'ported-upstream'
Diffstat (limited to 'gfx/thebes/gfxFontUtils.cpp')
-rw-r--r--gfx/thebes/gfxFontUtils.cpp89
1 files changed, 50 insertions, 39 deletions
diff --git a/gfx/thebes/gfxFontUtils.cpp b/gfx/thebes/gfxFontUtils.cpp
index cb505e87b..54ca03ff6 100644
--- a/gfx/thebes/gfxFontUtils.cpp
+++ b/gfx/thebes/gfxFontUtils.cpp
@@ -575,55 +575,64 @@ typedef struct {
#pragma pack()
uint32_t
-gfxFontUtils::MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh)
+gfxFontUtils::MapCharToGlyphFormat4(const uint8_t* aBuf, uint32_t aLength,
+ char16_t aCh)
{
const Format4Cmap *cmap4 = reinterpret_cast<const Format4Cmap*>(aBuf);
- uint16_t segCount;
- const AutoSwap_PRUint16 *endCodes;
- const AutoSwap_PRUint16 *startCodes;
- const AutoSwap_PRUint16 *idDelta;
- const AutoSwap_PRUint16 *idRangeOffset;
- uint16_t probe;
- uint16_t rangeShiftOver2;
- uint16_t index;
-
- segCount = (uint16_t)(cmap4->segCountX2) / 2;
-
- endCodes = &cmap4->arrays[0];
- startCodes = &cmap4->arrays[segCount + 1]; // +1 for reserved word between arrays
- idDelta = &startCodes[segCount];
- idRangeOffset = &idDelta[segCount];
-
- probe = 1 << (uint16_t)(cmap4->entrySelector);
- rangeShiftOver2 = (uint16_t)(cmap4->rangeShift) / 2;
-
- if ((uint16_t)(startCodes[rangeShiftOver2]) <= aCh) {
- index = rangeShiftOver2;
- } else {
- index = 0;
- }
-
- while (probe > 1) {
- probe >>= 1;
- if ((uint16_t)(startCodes[index + probe]) <= aCh) {
- index += probe;
+
+ uint16_t segCount = (uint16_t)(cmap4->segCountX2) / 2;
+
+ const AutoSwap_PRUint16* endCodes = &cmap4->arrays[0];
+ const AutoSwap_PRUint16* startCodes = &cmap4->arrays[segCount + 1];
+ const AutoSwap_PRUint16* idDelta = &startCodes[segCount];
+ const AutoSwap_PRUint16* idRangeOffset = &idDelta[segCount];
+
+ // Sanity-check that the fixed-size arrays don't exceed the buffer.
+ const uint8_t* const limit = aBuf + aLength;
+ if ((const uint8_t*)(&idRangeOffset[segCount]) > limit) {
+ return 0; // broken font, just bail out safely
+ }
+
+ // For most efficient binary search, we want to work on a range of segment
+ // indexes that is a power of 2 so that we can always halve it by shifting.
+ // So we find the largest power of 2 that is <= segCount.
+ // We will offset this range by segOffset so as to reach the end
+ // of the table, provided that doesn't put us beyond the target
+ // value from the outset.
+ uint32_t powerOf2 = mozilla::FindHighestBit(segCount);
+ uint32_t segOffset = segCount - powerOf2;
+ uint32_t idx = 0;
+
+ if (uint16_t(startCodes[segOffset]) <= aCh) {
+ idx = segOffset;
+ }
+
+ // Repeatedly halve the size of the range until we find the target group
+ while (powerOf2 > 1) {
+ powerOf2 >>= 1;
+ if (uint16_t(startCodes[idx + powerOf2]) <= aCh) {
+ idx += powerOf2;
}
}
- if (aCh >= (uint16_t)(startCodes[index]) && aCh <= (uint16_t)(endCodes[index])) {
+ if (aCh >= uint16_t(startCodes[idx]) && aCh <= uint16_t(endCodes[idx])) {
uint16_t result;
- if ((uint16_t)(idRangeOffset[index]) == 0) {
+ if (uint16_t(idRangeOffset[idx]) == 0) {
result = aCh;
} else {
- uint16_t offset = aCh - (uint16_t)(startCodes[index]);
- const AutoSwap_PRUint16 *glyphIndexTable =
- (const AutoSwap_PRUint16*)((const char*)&idRangeOffset[index] +
- (uint16_t)(idRangeOffset[index]));
+ uint16_t offset = aCh - uint16_t(startCodes[idx]);
+ const AutoSwap_PRUint16* glyphIndexTable =
+ (const AutoSwap_PRUint16*)((const char*)&idRangeOffset[idx] +
+ uint16_t(idRangeOffset[idx]));
+ if ((const uint8_t*)(glyphIndexTable + offset + 1) > limit) {
+ return 0; // broken font, just bail out safely
+ }
result = glyphIndexTable[offset];
}
- // note that this is unsigned 16-bit arithmetic, and may wrap around
- result += (uint16_t)(idDelta[index]);
+ // Note that this is unsigned 16-bit arithmetic, and may wrap around
+ // (which is required behavior per spec)
+ result += uint16_t(idDelta[idx]);
return result;
}
@@ -761,7 +770,8 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength,
switch (format) {
case 4:
gid = aUnicode < UNICODE_BMP_LIMIT ?
- MapCharToGlyphFormat4(aCmapBuf + offset, char16_t(aUnicode)) : 0;
+ MapCharToGlyphFormat4(aCmapBuf + offset, aBufLength - offset,
+ char16_t(aUnicode)) : 0;
break;
case 10:
gid = MapCharToGlyphFormat10(aCmapBuf + offset, aUnicode);
@@ -785,6 +795,7 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength,
case 4:
if (aUnicode < UNICODE_BMP_LIMIT) {
varGID = MapCharToGlyphFormat4(aCmapBuf + offset,
+ aBufLength - offset,
char16_t(aUnicode));
}
break;