Bug 906521. Part 6: Make gfxSVGGlyphs understand the new table format. r=jfkthame

This also adds a bunch of buffer sanity checks to the code. This may not be
strictly necessary, thanks to OTS, but I think we should code defensively here
too.

--HG--
extra : rebase_source : 26b11505aa143fae6f63cd5858c87a259bb54b50
This commit is contained in:
Robert O'Callahan 2013-08-20 01:08:43 +12:00
parent fc5637dc25
commit 8bdab20fd7
2 changed files with 35 additions and 13 deletions

View File

@ -46,9 +46,21 @@ gfxSVGGlyphs::gfxSVGGlyphs(hb_blob_t *aSVGTable)
{ {
mSVGData = aSVGTable; mSVGData = aSVGTable;
const char* svgData = hb_blob_get_data(mSVGData, nullptr); unsigned int length;
const char* svgData = hb_blob_get_data(mSVGData, &length);
mHeader = reinterpret_cast<const Header*>(svgData); mHeader = reinterpret_cast<const Header*>(svgData);
mIndex = reinterpret_cast<const IndexEntry*>(svgData + sizeof(Header)); mDocIndex = nullptr;
if (sizeof(Header) <= length && uint16_t(mHeader->mVersion) == 0 &&
uint64_t(mHeader->mDocIndexOffset) + 2 <= length) {
const DocIndex* docIndex = reinterpret_cast<const DocIndex*>
(svgData + mHeader->mDocIndexOffset);
// Limit the number of documents to avoid overflow
if (uint64_t(mHeader->mDocIndexOffset) + 2 +
uint16_t(docIndex->mNumEntries) * sizeof(IndexEntry) <= length) {
mDocIndex = docIndex;
}
}
mGlyphDocs.Init(); mGlyphDocs.Init();
mGlyphIdMap.Init(); mGlyphIdMap.Init();
@ -88,13 +100,13 @@ gfxSVGGlyphs::CompareIndexEntries(const void *aKey, const void *aEntry)
gfxSVGGlyphsDocument * gfxSVGGlyphsDocument *
gfxSVGGlyphs::FindOrCreateGlyphsDocument(uint32_t aGlyphId) gfxSVGGlyphs::FindOrCreateGlyphsDocument(uint32_t aGlyphId)
{ {
if (uint16_t(mHeader->mVersion) != 0) { if (!mDocIndex) {
// Version not understood // Invalid table
return nullptr; return nullptr;
} }
IndexEntry *entry = (IndexEntry*)bsearch(&aGlyphId, mIndex, IndexEntry *entry = (IndexEntry*)bsearch(&aGlyphId, mDocIndex->mEntries,
uint16_t(mHeader->mIndexLength), uint16_t(mDocIndex->mNumEntries),
sizeof(IndexEntry), sizeof(IndexEntry),
CompareIndexEntries); CompareIndexEntries);
if (!entry) { if (!entry) {
@ -104,11 +116,15 @@ gfxSVGGlyphs::FindOrCreateGlyphsDocument(uint32_t aGlyphId)
gfxSVGGlyphsDocument *result = mGlyphDocs.Get(entry->mDocOffset); gfxSVGGlyphsDocument *result = mGlyphDocs.Get(entry->mDocOffset);
if (!result) { if (!result) {
const uint8_t *data = (const uint8_t*)hb_blob_get_data(mSVGData, nullptr); unsigned int length;
result = new gfxSVGGlyphsDocument(data + entry->mDocOffset, const uint8_t *data = (const uint8_t*)hb_blob_get_data(mSVGData, &length);
if (entry->mDocOffset > 0 &&
uint64_t(mHeader->mDocIndexOffset) + entry->mDocOffset + entry->mDocLength <= length) {
result = new gfxSVGGlyphsDocument(data + mHeader->mDocIndexOffset + entry->mDocOffset,
entry->mDocLength); entry->mDocLength);
mGlyphDocs.Put(entry->mDocOffset, result); mGlyphDocs.Put(entry->mDocOffset, result);
} }
}
return result; return result;
} }

View File

@ -127,15 +127,21 @@ private:
const struct Header { const struct Header {
mozilla::AutoSwap_PRUint16 mVersion; mozilla::AutoSwap_PRUint16 mVersion;
mozilla::AutoSwap_PRUint16 mIndexLength; mozilla::AutoSwap_PRUint32 mDocIndexOffset;
mozilla::AutoSwap_PRUint32 mColorPalettesOffset;
} *mHeader; } *mHeader;
const struct IndexEntry { struct IndexEntry {
mozilla::AutoSwap_PRUint16 mStartGlyph; mozilla::AutoSwap_PRUint16 mStartGlyph;
mozilla::AutoSwap_PRUint16 mEndGlyph; mozilla::AutoSwap_PRUint16 mEndGlyph;
mozilla::AutoSwap_PRUint32 mDocOffset; mozilla::AutoSwap_PRUint32 mDocOffset;
mozilla::AutoSwap_PRUint32 mDocLength; mozilla::AutoSwap_PRUint32 mDocLength;
} *mIndex; };
const struct DocIndex {
mozilla::AutoSwap_PRUint16 mNumEntries;
IndexEntry mEntries[1]; /* actual length = mNumEntries */
} *mDocIndex;
static int CompareIndexEntries(const void *_a, const void *_b); static int CompareIndexEntries(const void *_a, const void *_b);
}; };