/src/freetype/src/gxvalid/gxvmort2.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 311 lines · 211 code · 63 blank · 37 comment · 11 complexity · 2e44d40e897a796227c73fe3d984b265 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* gxvmort2.c */
  4. /* */
  5. /* TrueTypeGX/AAT mort table validation */
  6. /* body for type2 (Ligature Substitution) subtable. */
  7. /* */
  8. /* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
  9. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  10. /* */
  11. /* This file is part of the FreeType project, and may only be used, */
  12. /* modified, and distributed under the terms of the FreeType project */
  13. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  14. /* this file you indicate that you have read the license and */
  15. /* understand and accept it fully. */
  16. /* */
  17. /***************************************************************************/
  18. /***************************************************************************/
  19. /* */
  20. /* gxvalid is derived from both gxlayout module and otvalid module. */
  21. /* Development of gxlayout is supported by the Information-technology */
  22. /* Promotion Agency(IPA), Japan. */
  23. /* */
  24. /***************************************************************************/
  25. #include "gxvmort.h"
  26. /*************************************************************************/
  27. /* */
  28. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  29. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  30. /* messages during execution. */
  31. /* */
  32. #undef FT_COMPONENT
  33. #define FT_COMPONENT trace_gxvmort
  34. typedef struct GXV_mort_subtable_type2_StateOptRec_
  35. {
  36. FT_UShort ligActionTable;
  37. FT_UShort componentTable;
  38. FT_UShort ligatureTable;
  39. FT_UShort ligActionTable_length;
  40. FT_UShort componentTable_length;
  41. FT_UShort ligatureTable_length;
  42. } GXV_mort_subtable_type2_StateOptRec,
  43. *GXV_mort_subtable_type2_StateOptRecData;
  44. #define GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE \
  45. ( GXV_STATETABLE_HEADER_SIZE + 2 + 2 + 2 )
  46. static void
  47. gxv_mort_subtable_type2_opttable_load( FT_Bytes table,
  48. FT_Bytes limit,
  49. GXV_Validator valid )
  50. {
  51. FT_Bytes p = table;
  52. GXV_mort_subtable_type2_StateOptRecData optdata =
  53. (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
  54. GXV_LIMIT_CHECK( 2 + 2 + 2 );
  55. optdata->ligActionTable = FT_NEXT_USHORT( p );
  56. optdata->componentTable = FT_NEXT_USHORT( p );
  57. optdata->ligatureTable = FT_NEXT_USHORT( p );
  58. GXV_TRACE(( "offset to ligActionTable=0x%04x\n",
  59. optdata->ligActionTable ));
  60. GXV_TRACE(( "offset to componentTable=0x%04x\n",
  61. optdata->componentTable ));
  62. GXV_TRACE(( "offset to ligatureTable=0x%04x\n",
  63. optdata->ligatureTable ));
  64. }
  65. static void
  66. gxv_mort_subtable_type2_subtable_setup( FT_UShort table_size,
  67. FT_UShort classTable,
  68. FT_UShort stateArray,
  69. FT_UShort entryTable,
  70. FT_UShort *classTable_length_p,
  71. FT_UShort *stateArray_length_p,
  72. FT_UShort *entryTable_length_p,
  73. GXV_Validator valid )
  74. {
  75. FT_UShort o[6];
  76. FT_UShort *l[6];
  77. FT_UShort buff[7];
  78. GXV_mort_subtable_type2_StateOptRecData optdata =
  79. (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
  80. GXV_NAME_ENTER( "subtable boundaries setup" );
  81. o[0] = classTable;
  82. o[1] = stateArray;
  83. o[2] = entryTable;
  84. o[3] = optdata->ligActionTable;
  85. o[4] = optdata->componentTable;
  86. o[5] = optdata->ligatureTable;
  87. l[0] = classTable_length_p;
  88. l[1] = stateArray_length_p;
  89. l[2] = entryTable_length_p;
  90. l[3] = &(optdata->ligActionTable_length);
  91. l[4] = &(optdata->componentTable_length);
  92. l[5] = &(optdata->ligatureTable_length);
  93. gxv_set_length_by_ushort_offset( o, l, buff, 6, table_size, valid );
  94. GXV_TRACE(( "classTable: offset=0x%04x length=0x%04x\n",
  95. classTable, *classTable_length_p ));
  96. GXV_TRACE(( "stateArray: offset=0x%04x length=0x%04x\n",
  97. stateArray, *stateArray_length_p ));
  98. GXV_TRACE(( "entryTable: offset=0x%04x length=0x%04x\n",
  99. entryTable, *entryTable_length_p ));
  100. GXV_TRACE(( "ligActionTable: offset=0x%04x length=0x%04x\n",
  101. optdata->ligActionTable,
  102. optdata->ligActionTable_length ));
  103. GXV_TRACE(( "componentTable: offset=0x%04x length=0x%04x\n",
  104. optdata->componentTable,
  105. optdata->componentTable_length ));
  106. GXV_TRACE(( "ligatureTable: offset=0x%04x length=0x%04x\n",
  107. optdata->ligatureTable,
  108. optdata->ligatureTable_length ));
  109. GXV_EXIT;
  110. }
  111. static void
  112. gxv_mort_subtable_type2_ligActionOffset_validate(
  113. FT_Bytes table,
  114. FT_UShort ligActionOffset,
  115. GXV_Validator valid )
  116. {
  117. /* access ligActionTable */
  118. GXV_mort_subtable_type2_StateOptRecData optdata =
  119. (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
  120. FT_Bytes lat_base = table + optdata->ligActionTable;
  121. FT_Bytes p = table + ligActionOffset;
  122. FT_Bytes lat_limit = lat_base + optdata->ligActionTable;
  123. GXV_32BIT_ALIGNMENT_VALIDATE( ligActionOffset );
  124. if ( p < lat_base )
  125. {
  126. GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%d byte rewind)\n",
  127. ligActionOffset, lat_base - p ));
  128. /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
  129. GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  130. }
  131. else if ( lat_limit < p )
  132. {
  133. GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%d byte overrun)\n",
  134. ligActionOffset, p - lat_limit ));
  135. /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
  136. GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  137. }
  138. else
  139. {
  140. /* validate entry in ligActionTable */
  141. FT_ULong lig_action;
  142. #ifdef GXV_LOAD_UNUSED_VARS
  143. FT_UShort last;
  144. FT_UShort store;
  145. #endif
  146. FT_ULong offset;
  147. lig_action = FT_NEXT_ULONG( p );
  148. #ifdef GXV_LOAD_UNUSED_VARS
  149. last = (FT_UShort)( ( lig_action >> 31 ) & 1 );
  150. store = (FT_UShort)( ( lig_action >> 30 ) & 1 );
  151. #endif
  152. /* Apple spec defines this offset as a word offset */
  153. offset = lig_action & 0x3FFFFFFFUL;
  154. if ( offset * 2 < optdata->ligatureTable )
  155. {
  156. GXV_TRACE(( "too short offset 0x%08x:"
  157. " 2 x offset < ligatureTable (%d byte rewind)\n",
  158. offset, optdata->ligatureTable - offset * 2 ));
  159. GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  160. } else if ( offset * 2 >
  161. optdata->ligatureTable + optdata->ligatureTable_length )
  162. {
  163. GXV_TRACE(( "too long offset 0x%08x:"
  164. " 2 x offset > ligatureTable + ligatureTable_length"
  165. " (%d byte overrun)\n",
  166. offset,
  167. optdata->ligatureTable + optdata->ligatureTable_length
  168. - offset * 2 ));
  169. GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  170. }
  171. }
  172. }
  173. static void
  174. gxv_mort_subtable_type2_entry_validate(
  175. FT_Byte state,
  176. FT_UShort flags,
  177. GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
  178. FT_Bytes table,
  179. FT_Bytes limit,
  180. GXV_Validator valid )
  181. {
  182. #ifdef GXV_LOAD_UNUSED_VARS
  183. FT_UShort setComponent;
  184. FT_UShort dontAdvance;
  185. #endif
  186. FT_UShort offset;
  187. FT_UNUSED( state );
  188. FT_UNUSED( glyphOffset_p );
  189. FT_UNUSED( limit );
  190. #ifdef GXV_LOAD_UNUSED_VARS
  191. setComponent = (FT_UShort)( ( flags >> 15 ) & 1 );
  192. dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
  193. #endif
  194. offset = (FT_UShort)( flags & 0x3FFFU );
  195. if ( 0 < offset )
  196. gxv_mort_subtable_type2_ligActionOffset_validate( table, offset,
  197. valid );
  198. }
  199. static void
  200. gxv_mort_subtable_type2_ligatureTable_validate( FT_Bytes table,
  201. GXV_Validator valid )
  202. {
  203. GXV_mort_subtable_type2_StateOptRecData optdata =
  204. (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
  205. FT_Bytes p = table + optdata->ligatureTable;
  206. FT_Bytes limit = table + optdata->ligatureTable
  207. + optdata->ligatureTable_length;
  208. GXV_NAME_ENTER( "mort chain subtable type2 - substitutionTable" );
  209. if ( 0 != optdata->ligatureTable )
  210. {
  211. /* Apple does not give specification of ligatureTable format */
  212. while ( p < limit )
  213. {
  214. FT_UShort lig_gid;
  215. GXV_LIMIT_CHECK( 2 );
  216. lig_gid = FT_NEXT_USHORT( p );
  217. if ( valid->face->num_glyphs < lig_gid )
  218. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  219. }
  220. }
  221. GXV_EXIT;
  222. }
  223. FT_LOCAL_DEF( void )
  224. gxv_mort_subtable_type2_validate( FT_Bytes table,
  225. FT_Bytes limit,
  226. GXV_Validator valid )
  227. {
  228. FT_Bytes p = table;
  229. GXV_mort_subtable_type2_StateOptRec lig_rec;
  230. GXV_NAME_ENTER( "mort chain subtable type2 (Ligature Substitution)" );
  231. GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE );
  232. valid->statetable.optdata =
  233. &lig_rec;
  234. valid->statetable.optdata_load_func =
  235. gxv_mort_subtable_type2_opttable_load;
  236. valid->statetable.subtable_setup_func =
  237. gxv_mort_subtable_type2_subtable_setup;
  238. valid->statetable.entry_glyphoffset_fmt =
  239. GXV_GLYPHOFFSET_NONE;
  240. valid->statetable.entry_validate_func =
  241. gxv_mort_subtable_type2_entry_validate;
  242. gxv_StateTable_validate( p, limit, valid );
  243. p += valid->subtable_length;
  244. gxv_mort_subtable_type2_ligatureTable_validate( table, valid );
  245. valid->subtable_length = p - table;
  246. GXV_EXIT;
  247. }
  248. /* END */