From 0ae3271814982524dfd210dee09031c2430d473f Mon Sep 17 00:00:00 2001 From: suzuki toshiya Date: Sun, 4 Jul 2010 20:14:18 +0900 Subject: [PATCH] Restrict the number of the charmaps in a rogue-compatible mode. Fix for Savannah bug #30059. * src/cache/ftccmap.c (FTC_CMapCache_Lookup): Replace `16' the minimum character code passed by a legacy rogue client by... * include/freetype/config/ftoption.h (FT_MAX_CHARMAP_CACHEABLE): This. It is undefined when FT_CONFIG_OPTION_OLD_INTERNALS is undefined (thus the rogue client compatibility is not required). * src/cff/cffobjs.c (cff_face_init): Abort the automatic selection or synthesis of Unicode cmap subtable when the charmap index exceeds FT_MAX_CHARMAP_CACHEABLE. * src/sfnt/ttcmap.c (tt_face_build_cmaps): Issue error message when the charmap index exceeds FT_MAX_CHARMAP_CACHEABLE. * src/base/ftobjs.c (find_unicode_charmap): When Unicode charmap is found after FT_MAX_CHARMAP_CACHEABLE, ignore it and search earlier one. (find_variant_selector_charmap): When UVS charmap is found after FT_MAX_CHARMAP_CACHEABLE, ignore it and search earlier one. (FT_Select_Charmap): When a charmap matching with requested encoding but after FT_MAX_CHARMAP_CACHEABLE, ignore and search earlier one. (FT_Set_Charmap): When a charmap matching with requested charmap but after FT_MAX_CHARMAP_CACHEABLE, ignore and search earlier one. (FT_Get_Charmap_Index): When a requested charmap is found after FT_MAX_CHARMAP_CACHEABLE, return the inverted charmap index. --- ChangeLog | 32 +++++++++++++++++++ include/freetype/config/ftoption.h | 21 ++++++++++++ src/base/ftobjs.c | 51 ++++++++++++++++++++++++++++++ src/cache/ftccmap.c | 24 +++++++------- src/cff/cffobjs.c | 19 +++++++++++ src/sfnt/ttcmap.c | 6 ++++ 6 files changed, 140 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3ec4eaec1..888788fc7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2010-07-04 suzuki toshiya + + Restrict the number of the charmaps in a rogue-compatible mode. + Fix for Savannah bug #30059. + + * src/cache/ftccmap.c (FTC_CMapCache_Lookup): Replace `16' the + minimum character code passed by a legacy rogue client by... + * include/freetype/config/ftoption.h (FT_MAX_CHARMAP_CACHEABLE): + This. It is undefined when FT_CONFIG_OPTION_OLD_INTERNALS is + undefined (thus the rogue client compatibility is not required). + + * src/cff/cffobjs.c (cff_face_init): Abort the automatic + selection or synthesis of Unicode cmap subtable when the charmap + index exceeds FT_MAX_CHARMAP_CACHEABLE. + * src/sfnt/ttcmap.c (tt_face_build_cmaps): Issue error message + when the charmap index exceeds FT_MAX_CHARMAP_CACHEABLE. + + * src/base/ftobjs.c (find_unicode_charmap): When Unicode charmap + is found after FT_MAX_CHARMAP_CACHEABLE, ignore it and search + earlier one. + (find_variant_selector_charmap): When UVS charmap is found after + FT_MAX_CHARMAP_CACHEABLE, ignore it and search earlier one. + (FT_Select_Charmap): When a charmap matching with requested + encoding but after FT_MAX_CHARMAP_CACHEABLE, ignore and search + earlier one. + (FT_Set_Charmap): When a charmap matching with requested + charmap but after FT_MAX_CHARMAP_CACHEABLE, ignore and search + earlier one. + (FT_Get_Charmap_Index): When a requested charmap is found + after FT_MAX_CHARMAP_CACHEABLE, return the inverted charmap + index. + 2010-07-04 Werner Lemberg TrueType hinting is no longer patented. diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h index 2db0c12e6..2b46259c1 100644 --- a/include/freetype/config/ftoption.h +++ b/include/freetype/config/ftoption.h @@ -692,6 +692,27 @@ FT_BEGIN_HEADER #define FT_CONFIG_OPTION_OLD_INTERNALS + /* + * To detect legacy cache-lookup call from a rogue client (<= 2.1.7), + * we restrict the number of charmaps in a font. The current API of + * FTC_CMapCache_Lookup() takes cmap_index & charcode, but old API + * takes charcode only. To determine the passed value is for cmap_index + * or charcode, the possible cmap_index is restricted not to exceed + * the minimum possible charcode by a rogue client. It is also very + * unlikely that a rogue client is interested in Unicode values 0 to 15. + * + * NOTE: The original threshold was 4 deduced from popular number of + * cmap subtables in UCS-4 TrueType fonts, but now it is not + * irregular for OpenType fonts to have more than 4 subtables, + * because variation selector subtables are available for Apple + * and Microsoft platforms. + */ + +#ifdef FT_CONFIG_OPTION_OLD_INTERNALS +#define FT_MAX_CHARMAP_CACHEABLE 15 +#endif + + /* * This macro is defined if either unpatented or native TrueType * hinting is requested by the definitions above. diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 11efc75f7..855169364 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -991,6 +991,14 @@ ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) ) { +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found " + "at too late position (%d)\n", cur - first )); + continue; + } +#endif face->charmap = cur[0]; return FT_Err_Ok; } @@ -1005,6 +1013,14 @@ { if ( cur[0]->encoding == FT_ENCODING_UNICODE ) { +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found " + "at too late position (%d)\n", cur - first )); + continue; + } +#endif face->charmap = cur[0]; return FT_Err_Ok; } @@ -1046,6 +1062,14 @@ if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR && FT_Get_CMap_Format( cur[0] ) == 14 ) +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "find_unicode_charmap: UVS cmap is found " + "at too late position (%d)\n", cur - first )); + continue; + } +#endif return cur[0]; } @@ -2922,6 +2946,15 @@ { if ( cur[0]->encoding == encoding ) { +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), " + "but in too late position to cache\n", + cur - face->charmaps )); + continue; + } +#endif face->charmap = cur[0]; return 0; } @@ -2956,6 +2989,15 @@ { if ( cur[0] == charmap ) { +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), " + "but in too late position to cache\n", + cur - face->charmaps )); + continue; + } +#endif face->charmap = cur[0]; return 0; } @@ -2981,6 +3023,15 @@ FT_ASSERT( i < charmap->face->num_charmaps ); +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( i > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), " + "but in too late position to cache\n", + i )); + return -i; + } +#endif return i; } diff --git a/src/cache/ftccmap.c b/src/cache/ftccmap.c index a802b0557..e0d3e2435 100644 --- a/src/cache/ftccmap.c +++ b/src/cache/ftccmap.c @@ -310,19 +310,11 @@ #ifdef FT_CONFIG_OPTION_OLD_INTERNALS /* - * Detect a call from a rogue client that thinks it is linking - * to FreeType 2.1.7. This is possible because the third parameter - * is then a character code, and we have never seen any font with - * more than a few charmaps, so if the index is very large... - * - * It is also very unlikely that a rogue client is interested - * in Unicode values 0 to 15. - * - * NOTE: The original threshold was 4, but we found a font from the - * Adobe Acrobat Reader Pack, named `KozMinProVI-Regular.otf', - * which contains more than 5 charmaps. + * If cmap_index is greater than the maximum number of cachable + * charmaps, we assume the request is from a legacy rogue client + * using old internal header. See include/config/ftoption.h. */ - if ( cmap_index >= 16 && !no_cmap_change ) + if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE && !no_cmap_change ) { FTC_OldCMapDesc desc = (FTC_OldCMapDesc) face_id; @@ -384,7 +376,7 @@ /* something rotten can happen with rogue clients */ if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >= FTC_CMAP_INDICES_MAX ) ) - return 0; + return 0; /* XXX: should return appropriate error */ gindex = FTC_CMAP_NODE( node )->indices[char_code - FTC_CMAP_NODE( node )->first]; @@ -401,6 +393,12 @@ if ( error ) goto Exit; +#ifdef FT_MAX_CHARMAP_CACHEABLE + /* something rotten can happen with rogue clients */ + if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE ) + return 0; /* XXX: should return appropriate error */ +#endif + if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps ) { FT_CharMap old, cmap = NULL; diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c index f7b5e8b12..3d50ddec6 100644 --- a/src/cff/cffobjs.c +++ b/src/cff/cffobjs.c @@ -879,6 +879,16 @@ if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) goto Exit; +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "cff_face_init: no Unicode cmap is found, " + "and too many subtables (%d) to add synthesized cmap\n", + nn )); + goto Exit; + } +#endif + /* we didn't find a Unicode charmap -- synthesize one */ cmaprec.face = cffface; cmaprec.platform_id = 3; @@ -897,6 +907,15 @@ cffface->charmap = cffface->charmaps[nn]; Skip_Unicode: +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( nn > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "cff_face_init: Unicode cmap is found, " + "but too many preceding subtables (%d) to access\n", + nn - 1 )); + goto Exit; + } +#endif if ( encoding->count > 0 ) { FT_CMap_Class clazz; diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c index 1df682f7b..544750ab1 100644 --- a/src/sfnt/ttcmap.c +++ b/src/sfnt/ttcmap.c @@ -3411,6 +3411,12 @@ } num_cmaps = TT_NEXT_USHORT( p ); +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE ) + FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables(%d) " + "subtable#%d and later are loaded but cannot be searched\n", + num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 )); +#endif for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) {