ICU-6011 Handle bad values in the scriptCount field in the ScriptList Table.

X-SVN-Rev: 23611
This commit is contained in:
Eric Mader 2008-03-18 20:04:14 +00:00
parent 3b646b385c
commit e0b48bc938
8 changed files with 147 additions and 15 deletions

View File

@ -1,7 +1,5 @@
/*
* %W% %E%
*
* (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
* (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
*
*/
@ -31,20 +29,45 @@ const LangSysTable *ScriptTable::findLanguage(LETag languageTag, le_bool exactMa
return (const LangSysTable *) ((char *)this + langSysTableOffset);
}
return 0;
return NULL;
}
const ScriptTable *ScriptListTable::findScript(LETag scriptTag) const
{
/*
* There are some fonts that have a large, bogus value for scriptCount. To try
* and protect against this, we use the offset in the first scriptRecord,
* which we know has to be past the end of the scriptRecordArray, to compute
* a value which is greater than or equal to the actual script count.
*
* Note: normally, the first offset will point to just after the scriptRecordArray,
* but there's no guarantee of this, only that it's *after* the scriptRecordArray.
* Because of this, a binary serach isn't safe, because the new count may include
* data that's not actually in the scriptRecordArray and hence the array will appear
* to be unsorted.
*/
le_uint16 count = SWAPW(scriptCount);
Offset scriptTableOffset =
OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArray, count);
le_uint16 limit = ((SWAPW(scriptRecordArray[0].offset) - sizeof(ScriptListTable)) / sizeof sizeof(scriptRecordArray)) + ANY_NUMBER;
Offset scriptTableOffset = 0;
if (count > limit) {
// the scriptCount value is bogus; do a linear search
// because limit may still be too large.
for(le_int32 s = 0; s < limit; s += 1) {
if (SWAPT(scriptRecordArray[s].tag) == scriptTag) {
scriptTableOffset = SWAPW(scriptRecordArray[s].offset);
break;
}
}
} else {
scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArray, count);
}
if (scriptTableOffset != 0) {
return (const ScriptTable *) ((char *)this + scriptTableOffset);
}
return 0;
return NULL;
}
const LangSysTable *ScriptListTable::findLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch) const
@ -52,7 +75,7 @@ const LangSysTable *ScriptListTable::findLanguage(LETag scriptTag, LETag languag
const ScriptTable *scriptTable = findScript(scriptTag);
if (scriptTable == 0) {
return 0;
return NULL;
}
return scriptTable->findLanguage(languageTag, exactMatch);

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2007, International Business Machines
* Copyright (C) 1999-2008, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
@ -276,7 +276,7 @@ const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 plat
for(le_int32 i = 0; i < fNameCount; i += 1) {
const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID == encodingID) &&
if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID &&
SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) {
char *name = ((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset);
le_uint16 length = SWAPW(nameRecord->length);
@ -292,11 +292,52 @@ const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 plat
return NULL;
}
const LEUnicode16 *PortableFontInstance::getUnicodeNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const
{
if (fNAMETable == NULL) {
LETag nameTag = LE_NAME_TABLE_TAG;
PortableFontInstance *realThis = (PortableFontInstance *) this;
realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag);
if (realThis->fNAMETable != NULL) {
realThis->fNameCount = SWAPW(realThis->fNAMETable->count);
realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset);
}
}
for(le_int32 i = 0; i < fNameCount; i += 1) {
const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID &&
SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) {
LEUnicode16 *name = (LEUnicode16 *) (((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset));
le_uint16 length = SWAPW(nameRecord->length) / 2;
LEUnicode16 *result = NEW_ARRAY(LEUnicode16, length + 2);
for (le_int32 c = 0; c < length; c += 1) {
result[c] = SWAPW(name[c]);
}
result[length] = 0;
return result;
}
}
return NULL;
}
void PortableFontInstance::deleteNameString(const char *name) const
{
DELETE_ARRAY(name);
}
void PortableFontInstance::deleteNameString(const LEUnicode16 *name) const
{
DELETE_ARRAY(name);
}
void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
{
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);

View File

@ -2,7 +2,7 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2007, International Business Machines
* Copyright (C) 1999-2008, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
@ -75,8 +75,12 @@ public:
virtual const char *getNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;
virtual const LEUnicode16 *getUnicodeNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;
virtual void deleteNameString(const char *name) const;
virtual void deleteNameString(const LEUnicode16 *name) const;
virtual le_int32 getUnitsPerEM() const;
virtual le_uint32 getFontChecksum() const;

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2006, International Business Machines
* Copyright (C) 1999-2008, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
@ -201,6 +201,19 @@ int main(int /*argc*/, char *argv[])
version = pfi->getNameString(NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
// The standard recommends that the Macintosh Roman/English name string be present, but
// if it's not, try the Microsoft Unicode/English string.
if (version == NULL) {
const LEUnicode16 *uversion = pfi->getUnicodeNameString(NAME_VERSION_STRING, PLATFORM_MICROSOFT, MICROSOFT_UNICODE_BMP, MICROSOFT_ENGLISH);
if (uversion != NULL) {
const UnicodeString usversion((const UChar *)uversion);
version = getCString(&usversion);
pfi->deleteNameString(uversion);
}
}
fprintf(outputFile, " <test-font name=\"%s\" version=\"%s\" checksum=\"0x%8.8X\"/>\n\n",
fontName, version, pfi->getFontChecksum());

View File

@ -108,4 +108,9 @@
<test-font name="lohit_ml.ttf"/>
<test-text>ണു്</test-text>
</test-case>
<test-case id="Broken Font Test" script="hani" lang="ZHT">
<test-font name="BMIN00M.TTF"/>
<test-text>中華人民共和國 臺灣</test-text>
</test-case>
</layout-tests>

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2007, International Business Machines
* Copyright (C) 1999-2008, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
@ -386,6 +386,19 @@ static void checkFontVersion(PortableFontInstance *fontInstance, const char *tes
const char *fontVersionString = fontInstance->getNameString(NAME_VERSION_STRING,
PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
// The standard recommends that the Macintosh Roman/English name string be present, but
// if it's not, try the Microsoft Unicode/English string.
if (fontVersionString == NULL) {
const LEUnicode16 *uversion = fontInstance->getUnicodeNameString(NAME_VERSION_STRING, PLATFORM_MICROSOFT, MICROSOFT_UNICODE_BMP, MICROSOFT_ENGLISH);
if (uversion != NULL) {
const UnicodeString usversion((const UChar *)uversion);
fontVersionString = getCString(&usversion);
fontInstance->deleteNameString(uversion);
}
}
log_info("Test %s: this may not be the same font used to generate the test data.\n", testID);
log_info("Your font's version string is \"%s\"\n", fontVersionString);
log_info("The expected version string is \"%s\"\n", testVersionString);

View File

@ -1,6 +1,6 @@
/***************************************************************************
*
* Copyright (C) 1998-2007, International Business Machines
* Copyright (C) 1998-2008, International Business Machines
* Corporation and others. All Rights Reserved.
*
************************************************************************/
@ -383,6 +383,17 @@ enum MacintoshLanguageID
MACINTOSH_ENGLISH = 0
};
enum MicrosoftEncodingID
{
MICROSOFT_UNICODE_BMP = 1,
MICROSOFT_UNICODE_FULL = 10
};
enum MicrosoftLanguageID
{
MICROSOFT_ENGLISH = 0x409
};
enum NameID
{
NAME_COPYRIGHT_NOTICE = 0,

View File

@ -8,7 +8,7 @@
UNLESS YOU REALLY KNOW WHAT YOU'RE DOING.
file name: letest.xml
generated on: 03/14/2008 01:04:15 PM Hawaiian Standard Time
generated on: 03/18/2008 10:01:39 AM Hawaiian Standard Time
generated by: gendata.cpp
-->
@ -1265,4 +1265,26 @@
</result-positions>
</test-case>
<test-case id="Broken Font Test" script="hani" lang="ZHT">
<test-font name="BMIN00M.TTF" version="Version 2.00" checksum="0xF16BE0C6"/>
<test-text>中華人民共和國 臺灣</test-text>
<result-glyphs>
0x00000292, 0x000024E8, 0x000002D1, 0x00001582, 0x000004A1, 0x00000650, 0x000007E2, 0x00000021,
0x00002395, 0x00001896
</result-glyphs>
<result-indices>
0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
0x00000008, 0x00000009
</result-indices>
<result-positions>
0.000000, 0.000000, 12.000000, 0.000000, 24.000000, 0.000000, 36.000000, 0.000000,
48.000000, 0.000000, 60.000000, 0.000000, 72.000000, 0.000000, 84.000000, 0.000000,
90.000000, 0.000000, 102.000000, 0.000000, 114.000000, 0.000000
</result-positions>
</test-case>
</layout-tests>