diff --git a/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.cpp b/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.cpp index 807a072410c..dabcf880ba8 100644 --- a/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.cpp +++ b/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.cpp @@ -26,7 +26,7 @@ /* * - * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved + * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved * */ @@ -152,17 +152,16 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l } UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success) - : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success) + : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags | LE_CHAR_FILTER_FEATURE_FLAG, success) { fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable; fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable; - - fSubstitutionFilter = new CharSubstitutionFilter(fontInstance); + /* OpenTypeLayoutEngine will allocate a substitution filter */ } UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine() { - delete fSubstitutionFilter; + /* OpenTypeLayoutEngine will cleanup the substitution filter */ } // "glyphs", "indices" -> glyphs, indices diff --git a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp index 1d7bc399a9b..0bd09752cc3 100644 --- a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp +++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp @@ -38,7 +38,6 @@ #include "ContextualGlyphSubstProc2.h" #include "LEGlyphStorage.h" #include "LESwaps.h" -#include U_NAMESPACE_BEGIN @@ -123,7 +122,7 @@ TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyp break; } case ltfSegmentArray: { - printf("Context Lookup Table Format4: specific interpretation needed!\n"); + //printf("Context Lookup Table Format4: specific interpretation needed!\n"); break; } case ltfSingleTable: diff --git a/jdk/src/share/native/sun/font/layout/LETypes.h b/jdk/src/share/native/sun/font/layout/LETypes.h index 26cbeb363f1..d3801fc2450 100644 --- a/jdk/src/share/native/sun/font/layout/LETypes.h +++ b/jdk/src/share/native/sun/font/layout/LETypes.h @@ -339,6 +339,35 @@ typedef struct LEPoint LEPoint; #ifndef U_HIDE_INTERNAL_API + +#ifndef LE_ASSERT_BAD_FONT +#define LE_ASSERT_BAD_FONT 0 +#endif + +#if LE_ASSERT_BAD_FONT +#include +#define LE_DEBUG_BAD_FONT(x) fprintf(stderr,"%s:%d: BAD FONT: %s\n", __FILE__, __LINE__, (x)); +#else +#define LE_DEBUG_BAD_FONT(x) +#endif + +/** + * Max value representable by a uintptr + */ +#ifndef UINTPTR_MAX +#ifndef UINT32_MAX +#define LE_UINTPTR_MAX 0xFFFFFFFFU +#else +#define LE_UINTPTR_MAX UINT32_MAX +#endif +#else +#define LE_UINTPTR_MAX UINTPTR_MAX +#endif + +/** + * Range check for overflow + */ +#define LE_RANGE_CHECK(type, count, ptrfn) (( (LE_UINTPTR_MAX / sizeof(type)) < count ) ? NULL : (ptrfn)) /** * A convenience macro to get the length of an array. * @@ -360,7 +389,7 @@ typedef struct LEPoint LEPoint; * * @internal */ -#define LE_NEW_ARRAY(type, count) (type *) uprv_malloc((count) * sizeof(type)) +#define LE_NEW_ARRAY(type, count) (type *) LE_RANGE_CHECK(type,count,uprv_malloc((count) * sizeof(type))) /** * Re-allocate an array of basic types. This is used to isolate the rest of @@ -403,7 +432,7 @@ typedef struct LEPoint LEPoint; * * @internal */ -#define LE_NEW_ARRAY(type, count) (type *) malloc((count) * sizeof(type)) +#define LE_NEW_ARRAY(type, count) LE_RANGE_CHECK(type,count,(type *) malloc((count) * sizeof(type))) /** * Re-allocate an array of basic types. This is used to isolate the rest of @@ -696,6 +725,8 @@ enum LEFeatureENUMs { #define LE_CHAR_FILTER_FEATURE_FLAG (1 << LE_CHAR_FILTER_FEATURE_ENUM) +#define LE_DEFAULT_FEATURE_FLAG (LE_Kerning_FEATURE_FLAG | LE_Ligatures_FEATURE_FLAG) /**< default features */ + /** * Error codes returned by the LayoutEngine. * diff --git a/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp b/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp index 689b85cd2e7..1fadbf9f792 100644 --- a/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp +++ b/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp @@ -428,7 +428,7 @@ void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success); - if (fTypoFlags & 0x1) { /* kerning enabled */ + if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */ static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG; KernTable kt(fFontInstance, getFontTable(kernTableTag)); @@ -571,8 +571,8 @@ void LayoutEngine::reset() LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success) { - // 3 -> kerning and ligatures - return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, 3, success); + //kerning and ligatures - by default + return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, LE_DEFAULT_FEATURE_FLAG, success); } LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success) @@ -660,11 +660,11 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan } } else { MorphTableHeader2 *morxTable = (MorphTableHeader2 *)fontInstance->getFontTable(morxTableTag); - if (morxTable != NULL) { + if (morxTable != NULL && SWAPL(morxTable->version)==0x00020000) { result = new GXLayoutEngine2(fontInstance, scriptCode, languageCode, morxTable, typoFlags, success); } else { const MorphTableHeader *mortTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag); - if (mortTable != NULL) { // mort + if (mortTable != NULL && SWAPL(mortTable->version)==0x00010000) { // mort result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, mortTable, success); } else { switch (scriptCode) { diff --git a/jdk/src/share/native/sun/font/layout/LigatureSubstProc.cpp b/jdk/src/share/native/sun/font/layout/LigatureSubstProc.cpp index 6fabb6e749d..842b095e085 100644 --- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc.cpp +++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc.cpp @@ -25,7 +25,7 @@ /* * - * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved + * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved * */ @@ -79,6 +79,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp } componentStack[m] = currGlyph; + } else if ( m == -1) { + // bad font- skip this glyph. + currGlyph++; + return newState; } ByteOffset actionOffset = flags & lsfActionOffsetMask; @@ -102,7 +106,21 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp offset = action & lafComponentOffsetMask; if (offset != 0) { const le_int16 *offsetTable = (const le_int16 *)((char *) &ligatureSubstitutionHeader->stHeader + 2 * SignExtend(offset, lafComponentOffsetMask)); + const le_int16 *tableEnd = (const le_int16 *)((char *) &ligatureSubstitutionHeader + 1 * SWAPW(ligatureSubstitutionHeader->length)); + // Check if the font is internally consistent + if(tableEnd < (const le_int16*)&ligatureSubstitutionHeader // stated end wrapped around? + || offsetTable > tableEnd) { // offset past end of stated length? + currGlyph++; + LE_DEBUG_BAD_FONT("off end of ligature substitution header"); + return newState; // get out! bad font + } + + if(componentGlyph > glyphStorage.getGlyphCount()) { + LE_DEBUG_BAD_FONT("preposterous componentGlyph"); + currGlyph++; + return newState; // get out! bad font + } i += SWAPW(offsetTable[LE_GET_GLYPH(glyphStorage[componentGlyph])]); if (action & (lafLast | lafStore)) { @@ -110,13 +128,22 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset); glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); + if(mm==nComponents) { + LE_DEBUG_BAD_FONT("exceeded nComponents"); + mm--; // don't overrun the stack. + } stack[++mm] = componentGlyph; i = 0; } else { glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF); } } - } while (!(action & lafLast)); +#if LE_ASSERT_BAD_FONT + if(m<0) { + LE_DEBUG_BAD_FONT("m<0") + } +#endif + } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items while (mm >= 0) { if (++m >= nComponents) { diff --git a/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp b/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp index c26442da723..f36be1b26ad 100644 --- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp +++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp @@ -79,6 +79,11 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp m = 0; } componentStack[m] = currGlyph; + } else if ( m == -1) { + // bad font- skip this glyph. + LE_DEBUG_BAD_FONT("m==-1") + currGlyph+= dir; + return nextStateIndex; } ByteOffset actionOffset = flags & lsfPerformAction; @@ -93,6 +98,16 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp const le_uint16 *componentTable = (const le_uint16 *)((char *) &ligatureSubstitutionHeader->stHeader + componentOffset); + const le_uint16 *tableEnd = (const le_uint16 *)((char *) &ligatureSubstitutionHeader + SWAPL(ligatureSubstitutionHeader->length)); + + // Check if the font is internally consistent + if(tableEnd < (const le_uint16*)&ligatureSubstitutionHeader // stated end wrapped around? + || componentTable > tableEnd) { // offset past end of stated length? + currGlyph+= dir; + LE_DEBUG_BAD_FONT("ligatureSubstHeader off end of table") + return nextStateIndex; // get out! bad font + } + do { le_uint32 componentGlyph = componentStack[m--]; // pop off @@ -104,19 +119,32 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp offset = action & lafComponentOffsetMask; if (offset != 0) { - + if(componentGlyph > glyphStorage.getGlyphCount()) { + LE_DEBUG_BAD_FONT("preposterous componentGlyph"); + currGlyph+= dir; + return nextStateIndex; // get out! bad font + } i += SWAPW(componentTable[LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask))]); if (action & (lafLast | lafStore)) { TTGlyphID ligatureGlyph = SWAPW(ligatureTable[i]); glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); + if(mm==nComponents) { + LE_DEBUG_BAD_FONT("exceeded nComponents"); + mm--; // don't overrun the stack. + } stack[++mm] = componentGlyph; i = 0; } else { glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF); } } - } while (!(action & lafLast)); +#if LE_ASSERT_BAD_FONT + if(m<0) { + LE_DEBUG_BAD_FONT("m<0") + } +#endif + } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items while (mm >= 0) { if (++m >= nComponents) { diff --git a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp index 6e74130989b..db672efb98b 100644 --- a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp +++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp @@ -208,7 +208,7 @@ LookupProcessor::LookupProcessor(const char *baseAddress, lookupSelectCount = lookupListCount; le_int32 count, order = 0; - le_int32 featureReferences = 0; + le_uint32 featureReferences = 0; const FeatureTable *featureTable = NULL; LETag featureTag; @@ -219,7 +219,7 @@ LookupProcessor::LookupProcessor(const char *baseAddress, // be the maximum number of entries in the lookupOrderArray. We can't use // lookupListCount because some lookups might be referenced by more than // one feature. - for (le_int32 feature = 0; feature < featureCount; feature += 1) { + for (le_uint32 feature = 0; feature < featureCount; feature += 1) { le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); diff --git a/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp b/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp index 375327b55da..a561a135182 100644 --- a/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp +++ b/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp @@ -123,7 +123,7 @@ static const FeatureMap featureMap[] = {ccmpFeatureTag, ccmpFeatureMask}, {ligaFeatureTag, ligaFeatureMask}, {cligFeatureTag, cligFeatureMask}, - {kernFeatureTag, kernFeatureMask}, + {kernFeatureTag, kernFeatureMask}, {paltFeatureTag, paltFeatureMask}, {markFeatureTag, markFeatureMask}, {mkmkFeatureTag, mkmkFeatureMask}, @@ -160,6 +160,23 @@ OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, l static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG; const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag); + applyTypoFlags(); + + setScriptAndLanguageTags(); + + fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag); + +// JK patch, 2008-05-30 - see Sinhala bug report and LKLUG font +// if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) { + if (gposTable != NULL && gposTable->coversScript(fScriptTag)) { + fGPOSTable = gposTable; + } +} + +void OpenTypeLayoutEngine::applyTypoFlags() { + const le_int32& typoFlags = fTypoFlags; + const LEFontInstance *fontInstance = fFontInstance; + switch (typoFlags & (LE_SS01_FEATURE_FLAG | LE_SS02_FEATURE_FLAG | LE_SS03_FEATURE_FLAG @@ -221,15 +238,6 @@ OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, l fSubstitutionFilter = new CharSubstitutionFilter(fontInstance); } - setScriptAndLanguageTags(); - - fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag); - -// JK patch, 2008-05-30 - see Sinhala bug report and LKLUG font -// if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) { - if (gposTable != NULL && gposTable->coversScript(fScriptTag)) { - fGPOSTable = gposTable; - } } void OpenTypeLayoutEngine::reset() @@ -246,13 +254,15 @@ OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, l : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureOrder(FALSE), fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { - setScriptAndLanguageTags(); + applyTypoFlags(); + setScriptAndLanguageTags(); } OpenTypeLayoutEngine::~OpenTypeLayoutEngine() { - if (fTypoFlags & 0x80000000L) { + if (fTypoFlags & LE_CHAR_FILTER_FEATURE_FLAG) { delete fSubstitutionFilter; + fSubstitutionFilter = NULL; } reset(); diff --git a/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.h b/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.h index cf257fb8131..7a89df46a4a 100644 --- a/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.h +++ b/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.h @@ -24,7 +24,7 @@ */ /* - * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved + * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved * */ @@ -184,6 +184,11 @@ private: */ static const LETag scriptTags[]; + /** + * apply the typoflags. Only called by the c'tors. + */ + void applyTypoFlags(); + protected: /** * A set of "default" features. The default characterProcessing method diff --git a/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp b/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp index c76086afd2a..3146cc53210 100644 --- a/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp +++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp @@ -65,6 +65,9 @@ StateTableProcessor::~StateTableProcessor() void StateTableProcessor::process(LEGlyphStorage &glyphStorage) { + + LE_STATE_PATIENCE_INIT(); + // Start at state 0 // XXX: How do we know when to start at state 1? ByteOffset currentState = stateArrayOffset; @@ -76,6 +79,7 @@ void StateTableProcessor::process(LEGlyphStorage &glyphStorage) beginStateTable(); while (currGlyph <= glyphCount) { + if(LE_STATE_PATIENCE_DECR()) break; // patience exceeded. ClassCode classCode = classCodeOOB; if (currGlyph == glyphCount) { // XXX: How do we handle EOT vs. EOL? @@ -92,8 +96,9 @@ void StateTableProcessor::process(LEGlyphStorage &glyphStorage) const EntryTableIndex *stateArray = (const EntryTableIndex *) ((char *) &stateTableHeader->stHeader + currentState); EntryTableIndex entryTableIndex = stateArray[(le_uint8)classCode]; - + LE_STATE_PATIENCE_CURR(le_int32, currGlyph); currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); + LE_STATE_PATIENCE_INCR(currGlyph); } endStateTable(); diff --git a/jdk/src/share/native/sun/font/layout/StateTableProcessor2.cpp b/jdk/src/share/native/sun/font/layout/StateTableProcessor2.cpp index d4766cb0bf3..5bd9c253012 100644 --- a/jdk/src/share/native/sun/font/layout/StateTableProcessor2.cpp +++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor2.cpp @@ -38,7 +38,6 @@ #include "LEGlyphStorage.h" #include "LESwaps.h" #include "LookupTables.h" -#include U_NAMESPACE_BEGIN @@ -72,6 +71,8 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) le_uint16 currentState = 0; le_int32 glyphCount = glyphStorage.getGlyphCount(); + LE_STATE_PATIENCE_INIT(); + le_int32 currGlyph = 0; if ((coverage & scfReverse2) != 0) { // process glyphs in descending order currGlyph = glyphCount - 1; @@ -86,6 +87,10 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) #ifdef TEST_FORMAT SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) classTable; while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { + if(LE_STATE_PATIENCE_DECR()) { + LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") + break; // patience exceeded. + } LookupValue classCode = classCodeOOB; if (currGlyph == glyphCount || currGlyph == -1) { // XXX: How do we handle EOT vs. EOL? @@ -101,7 +106,9 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) } } EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); + LE_STATE_PATIENCE_CURR(le_int32, currGlyph); currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset + LE_STATE_PATIENCE_INCR(currGlyph); } #endif break; @@ -109,6 +116,10 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) case ltfSegmentSingle: { SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) classTable; while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { + if(LE_STATE_PATIENCE_DECR()) { + LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") + break; // patience exceeded. + } LookupValue classCode = classCodeOOB; if (currGlyph == glyphCount || currGlyph == -1) { // XXX: How do we handle EOT vs. EOL? @@ -127,21 +138,31 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) } } EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); + LE_STATE_PATIENCE_CURR(le_int32, currGlyph); currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); + LE_STATE_PATIENCE_INCR(currGlyph); } break; } case ltfSegmentArray: { - printf("Lookup Table Format4: specific interpretation needed!\n"); + //printf("Lookup Table Format4: specific interpretation needed!\n"); break; } case ltfSingleTable: { SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) classTable; while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { + if(LE_STATE_PATIENCE_DECR()) { + LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") + break; // patience exceeded. + } LookupValue classCode = classCodeOOB; if (currGlyph == glyphCount || currGlyph == -1) { // XXX: How do we handle EOT vs. EOL? classCode = classCodeEOT; + } else if(currGlyph > glyphCount) { + // note if > glyphCount, we've run off the end (bad font) + currGlyph = glyphCount; + classCode = classCodeEOT; } else { LEGlyphID gid = glyphStorage[currGlyph]; TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); @@ -156,7 +177,9 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) } } EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); + LE_STATE_PATIENCE_CURR(le_int32, currGlyph); currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); + LE_STATE_PATIENCE_INCR(currGlyph); } break; } @@ -166,6 +189,11 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount); while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { + if(LE_STATE_PATIENCE_DECR()) { + LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") + break; // patience exceeded. + } + LookupValue classCode = classCodeOOB; if (currGlyph == glyphCount || currGlyph == -1) { // XXX: How do we handle EOT vs. EOL? @@ -179,7 +207,9 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) } } EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); + LE_STATE_PATIENCE_CURR(le_int32, currGlyph); currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); + LE_STATE_PATIENCE_INCR(currGlyph); } break; } diff --git a/jdk/src/share/native/sun/font/layout/StateTables.h b/jdk/src/share/native/sun/font/layout/StateTables.h index 13177f5498a..6c6fdced933 100644 --- a/jdk/src/share/native/sun/font/layout/StateTables.h +++ b/jdk/src/share/native/sun/font/layout/StateTables.h @@ -42,6 +42,41 @@ U_NAMESPACE_BEGIN + + + +/* + * State table loop detection. + * Detects if too many ( LE_STATE_PATIENCE_COUNT ) state changes occur without moving the glyph index 'g'. + * + * Usage (pseudocode): + * + * { + * LE_STATE_PATIENCE_INIT(); + * + * int g=0; // the glyph index - expect it to be moving + * + * for(;;) { + * if(LE_STATE_PATIENCE_DECR()) { // decrements the patience counter + * // ran out of patience, get out. + * break; + * } + * + * LE_STATE_PATIENCE_CURR(int, g); // store the 'current' + * state = newState(state,g); + * g+= ; + * LE_STATE_PATIENCE_INCR(g); // if g has moved, increment the patience counter. Otherwise leave it. + * } + * + */ + +#define LE_STATE_PATIENCE_COUNT 4096 /**< give up if a state table doesn't move the glyph after this many iterations */ +#define LE_STATE_PATIENCE_INIT() le_uint32 le_patience_count = LE_STATE_PATIENCE_COUNT +#define LE_STATE_PATIENCE_DECR() --le_patience_count==0 +#define LE_STATE_PATIENCE_CURR(type,x) type le_patience_curr=(x) +#define LE_STATE_PATIENCE_INCR(x) if((x)!=le_patience_curr) ++le_patience_count; + + struct StateTableHeader { le_int16 stateSize;