PageRenderTime 40ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/src/freetype/src/gxvalid/gxvcommn.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1744 lines | 1177 code | 374 blank | 193 comment | 187 complexity | 56e4f3f57fcacf9ec12898c411882920 MD5 | raw file
Possible License(s): LGPL-3.0, BSD-3-Clause, CPL-1.0, Unlicense, GPL-2.0, GPL-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, BSD-2-Clause, LGPL-2.1
  1. /***************************************************************************/
  2. /* */
  3. /* gxvcommn.c */
  4. /* */
  5. /* TrueTypeGX/AAT common tables validation (body). */
  6. /* */
  7. /* Copyright 2004, 2005, 2009, 2010 */
  8. /* 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 "gxvcommn.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_gxvcommon
  34. /*************************************************************************/
  35. /*************************************************************************/
  36. /***** *****/
  37. /***** 16bit offset sorter *****/
  38. /***** *****/
  39. /*************************************************************************/
  40. /*************************************************************************/
  41. static int
  42. gxv_compare_ushort_offset( FT_UShort* a,
  43. FT_UShort* b )
  44. {
  45. if ( *a < *b )
  46. return -1;
  47. else if ( *a > *b )
  48. return 1;
  49. else
  50. return 0;
  51. }
  52. FT_LOCAL_DEF( void )
  53. gxv_set_length_by_ushort_offset( FT_UShort* offset,
  54. FT_UShort** length,
  55. FT_UShort* buff,
  56. FT_UInt nmemb,
  57. FT_UShort limit,
  58. GXV_Validator valid )
  59. {
  60. FT_UInt i;
  61. for ( i = 0; i < nmemb; i++ )
  62. *(length[i]) = 0;
  63. for ( i = 0; i < nmemb; i++ )
  64. buff[i] = offset[i];
  65. buff[nmemb] = limit;
  66. ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ),
  67. ( int(*)(const void*, const void*) )gxv_compare_ushort_offset );
  68. if ( buff[nmemb] > limit )
  69. FT_INVALID_OFFSET;
  70. for ( i = 0; i < nmemb; i++ )
  71. {
  72. FT_UInt j;
  73. for ( j = 0; j < nmemb; j++ )
  74. if ( buff[j] == offset[i] )
  75. break;
  76. if ( j == nmemb )
  77. FT_INVALID_OFFSET;
  78. *(length[i]) = (FT_UShort)( buff[j + 1] - buff[j] );
  79. if ( 0 != offset[i] && 0 == *(length[i]) )
  80. FT_INVALID_OFFSET;
  81. }
  82. }
  83. /*************************************************************************/
  84. /*************************************************************************/
  85. /***** *****/
  86. /***** 32bit offset sorter *****/
  87. /***** *****/
  88. /*************************************************************************/
  89. /*************************************************************************/
  90. static int
  91. gxv_compare_ulong_offset( FT_ULong* a,
  92. FT_ULong* b )
  93. {
  94. if ( *a < *b )
  95. return -1;
  96. else if ( *a > *b )
  97. return 1;
  98. else
  99. return 0;
  100. }
  101. FT_LOCAL_DEF( void )
  102. gxv_set_length_by_ulong_offset( FT_ULong* offset,
  103. FT_ULong** length,
  104. FT_ULong* buff,
  105. FT_UInt nmemb,
  106. FT_ULong limit,
  107. GXV_Validator valid)
  108. {
  109. FT_UInt i;
  110. for ( i = 0; i < nmemb; i++ )
  111. *(length[i]) = 0;
  112. for ( i = 0; i < nmemb; i++ )
  113. buff[i] = offset[i];
  114. buff[nmemb] = limit;
  115. ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ),
  116. ( int(*)(const void*, const void*) )gxv_compare_ulong_offset );
  117. if ( buff[nmemb] > limit )
  118. FT_INVALID_OFFSET;
  119. for ( i = 0; i < nmemb; i++ )
  120. {
  121. FT_UInt j;
  122. for ( j = 0; j < nmemb; j++ )
  123. if ( buff[j] == offset[i] )
  124. break;
  125. if ( j == nmemb )
  126. FT_INVALID_OFFSET;
  127. *(length[i]) = buff[j + 1] - buff[j];
  128. if ( 0 != offset[i] && 0 == *(length[i]) )
  129. FT_INVALID_OFFSET;
  130. }
  131. }
  132. /*************************************************************************/
  133. /*************************************************************************/
  134. /***** *****/
  135. /***** scan value array and get min & max *****/
  136. /***** *****/
  137. /*************************************************************************/
  138. /*************************************************************************/
  139. FT_LOCAL_DEF( void )
  140. gxv_array_getlimits_byte( FT_Bytes table,
  141. FT_Bytes limit,
  142. FT_Byte* min,
  143. FT_Byte* max,
  144. GXV_Validator valid )
  145. {
  146. FT_Bytes p = table;
  147. *min = 0xFF;
  148. *max = 0x00;
  149. while ( p < limit )
  150. {
  151. FT_Byte val;
  152. GXV_LIMIT_CHECK( 1 );
  153. val = FT_NEXT_BYTE( p );
  154. *min = (FT_Byte)FT_MIN( *min, val );
  155. *max = (FT_Byte)FT_MAX( *max, val );
  156. }
  157. valid->subtable_length = p - table;
  158. }
  159. FT_LOCAL_DEF( void )
  160. gxv_array_getlimits_ushort( FT_Bytes table,
  161. FT_Bytes limit,
  162. FT_UShort* min,
  163. FT_UShort* max,
  164. GXV_Validator valid )
  165. {
  166. FT_Bytes p = table;
  167. *min = 0xFFFFU;
  168. *max = 0x0000;
  169. while ( p < limit )
  170. {
  171. FT_UShort val;
  172. GXV_LIMIT_CHECK( 2 );
  173. val = FT_NEXT_USHORT( p );
  174. *min = (FT_Byte)FT_MIN( *min, val );
  175. *max = (FT_Byte)FT_MAX( *max, val );
  176. }
  177. valid->subtable_length = p - table;
  178. }
  179. /*************************************************************************/
  180. /*************************************************************************/
  181. /***** *****/
  182. /***** BINSEARCHHEADER *****/
  183. /***** *****/
  184. /*************************************************************************/
  185. /*************************************************************************/
  186. typedef struct GXV_BinSrchHeader_
  187. {
  188. FT_UShort unitSize;
  189. FT_UShort nUnits;
  190. FT_UShort searchRange;
  191. FT_UShort entrySelector;
  192. FT_UShort rangeShift;
  193. } GXV_BinSrchHeader;
  194. static void
  195. gxv_BinSrchHeader_check_consistency( GXV_BinSrchHeader* binSrchHeader,
  196. GXV_Validator valid )
  197. {
  198. FT_UShort searchRange;
  199. FT_UShort entrySelector;
  200. FT_UShort rangeShift;
  201. if ( binSrchHeader->unitSize == 0 )
  202. FT_INVALID_DATA;
  203. if ( binSrchHeader->nUnits == 0 )
  204. {
  205. if ( binSrchHeader->searchRange == 0 &&
  206. binSrchHeader->entrySelector == 0 &&
  207. binSrchHeader->rangeShift == 0 )
  208. return;
  209. else
  210. FT_INVALID_DATA;
  211. }
  212. for ( searchRange = 1, entrySelector = 1;
  213. ( searchRange * 2 ) <= binSrchHeader->nUnits &&
  214. searchRange < 0x8000U;
  215. searchRange *= 2, entrySelector++ )
  216. ;
  217. entrySelector--;
  218. searchRange = (FT_UShort)( searchRange * binSrchHeader->unitSize );
  219. rangeShift = (FT_UShort)( binSrchHeader->nUnits * binSrchHeader->unitSize
  220. - searchRange );
  221. if ( searchRange != binSrchHeader->searchRange ||
  222. entrySelector != binSrchHeader->entrySelector ||
  223. rangeShift != binSrchHeader->rangeShift )
  224. {
  225. GXV_TRACE(( "Inconsistency found in BinSrchHeader\n" ));
  226. GXV_TRACE(( "originally: unitSize=%d, nUnits=%d, "
  227. "searchRange=%d, entrySelector=%d, "
  228. "rangeShift=%d\n",
  229. binSrchHeader->unitSize, binSrchHeader->nUnits,
  230. binSrchHeader->searchRange, binSrchHeader->entrySelector,
  231. binSrchHeader->rangeShift ));
  232. GXV_TRACE(( "calculated: unitSize=%d, nUnits=%d, "
  233. "searchRange=%d, entrySelector=%d, "
  234. "rangeShift=%d\n",
  235. binSrchHeader->unitSize, binSrchHeader->nUnits,
  236. searchRange, entrySelector, rangeShift ));
  237. GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
  238. }
  239. }
  240. /*
  241. * parser & validator of BinSrchHeader
  242. * which is used in LookupTable format 2, 4, 6.
  243. *
  244. * Essential parameters (unitSize, nUnits) are returned by
  245. * given pointer, others (searchRange, entrySelector, rangeShift)
  246. * can be calculated by essential parameters, so they are just
  247. * validated and discarded.
  248. *
  249. * However, wrong values in searchRange, entrySelector, rangeShift
  250. * won't cause fatal errors, because these parameters might be
  251. * only used in old m68k font driver in MacOS.
  252. * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
  253. */
  254. FT_LOCAL_DEF( void )
  255. gxv_BinSrchHeader_validate( FT_Bytes table,
  256. FT_Bytes limit,
  257. FT_UShort* unitSize_p,
  258. FT_UShort* nUnits_p,
  259. GXV_Validator valid )
  260. {
  261. FT_Bytes p = table;
  262. GXV_BinSrchHeader binSrchHeader;
  263. GXV_NAME_ENTER( "BinSrchHeader validate" );
  264. if ( *unitSize_p == 0 )
  265. {
  266. GXV_LIMIT_CHECK( 2 );
  267. binSrchHeader.unitSize = FT_NEXT_USHORT( p );
  268. }
  269. else
  270. binSrchHeader.unitSize = *unitSize_p;
  271. if ( *nUnits_p == 0 )
  272. {
  273. GXV_LIMIT_CHECK( 2 );
  274. binSrchHeader.nUnits = FT_NEXT_USHORT( p );
  275. }
  276. else
  277. binSrchHeader.nUnits = *nUnits_p;
  278. GXV_LIMIT_CHECK( 2 + 2 + 2 );
  279. binSrchHeader.searchRange = FT_NEXT_USHORT( p );
  280. binSrchHeader.entrySelector = FT_NEXT_USHORT( p );
  281. binSrchHeader.rangeShift = FT_NEXT_USHORT( p );
  282. GXV_TRACE(( "nUnits %d\n", binSrchHeader.nUnits ));
  283. gxv_BinSrchHeader_check_consistency( &binSrchHeader, valid );
  284. if ( *unitSize_p == 0 )
  285. *unitSize_p = binSrchHeader.unitSize;
  286. if ( *nUnits_p == 0 )
  287. *nUnits_p = binSrchHeader.nUnits;
  288. valid->subtable_length = p - table;
  289. GXV_EXIT;
  290. }
  291. /*************************************************************************/
  292. /*************************************************************************/
  293. /***** *****/
  294. /***** LOOKUP TABLE *****/
  295. /***** *****/
  296. /*************************************************************************/
  297. /*************************************************************************/
  298. #define GXV_LOOKUP_VALUE_LOAD( P, SIGNSPEC ) \
  299. ( P += 2, gxv_lookup_value_load( P - 2, SIGNSPEC ) )
  300. static GXV_LookupValueDesc
  301. gxv_lookup_value_load( FT_Bytes p,
  302. int signspec )
  303. {
  304. GXV_LookupValueDesc v;
  305. if ( signspec == GXV_LOOKUPVALUE_UNSIGNED )
  306. v.u = FT_NEXT_USHORT( p );
  307. else
  308. v.s = FT_NEXT_SHORT( p );
  309. return v;
  310. }
  311. #define GXV_UNITSIZE_VALIDATE( FORMAT, UNITSIZE, NUNITS, CORRECTSIZE ) \
  312. FT_BEGIN_STMNT \
  313. if ( UNITSIZE != CORRECTSIZE ) \
  314. { \
  315. FT_ERROR(( "unitSize=%d differs from" \
  316. " expected unitSize=%d" \
  317. " in LookupTable %s\n", \
  318. UNITSIZE, CORRECTSIZE, FORMAT )); \
  319. if ( UNITSIZE != 0 && NUNITS != 0 ) \
  320. { \
  321. FT_ERROR(( " cannot validate anymore\n" )); \
  322. FT_INVALID_FORMAT; \
  323. } \
  324. else \
  325. FT_ERROR(( " forcibly continues\n" )); \
  326. } \
  327. FT_END_STMNT
  328. /* ================= Simple Array Format 0 Lookup Table ================ */
  329. static void
  330. gxv_LookupTable_fmt0_validate( FT_Bytes table,
  331. FT_Bytes limit,
  332. GXV_Validator valid )
  333. {
  334. FT_Bytes p = table;
  335. FT_UShort i;
  336. GXV_LookupValueDesc value;
  337. GXV_NAME_ENTER( "LookupTable format 0" );
  338. GXV_LIMIT_CHECK( 2 * valid->face->num_glyphs );
  339. for ( i = 0; i < valid->face->num_glyphs; i++ )
  340. {
  341. GXV_LIMIT_CHECK( 2 );
  342. if ( p + 2 >= limit ) /* some fonts have too-short fmt0 array */
  343. {
  344. GXV_TRACE(( "too short, glyphs %d - %d are missing\n",
  345. i, valid->face->num_glyphs ));
  346. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  347. break;
  348. }
  349. value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
  350. valid->lookupval_func( i, &value, valid );
  351. }
  352. valid->subtable_length = p - table;
  353. GXV_EXIT;
  354. }
  355. /* ================= Segment Single Format 2 Loolup Table ============== */
  356. /*
  357. * Apple spec says:
  358. *
  359. * To guarantee that a binary search terminates, you must include one or
  360. * more special `end of search table' values at the end of the data to
  361. * be searched. The number of termination values that need to be
  362. * included is table-specific. The value that indicates binary search
  363. * termination is 0xFFFF.
  364. *
  365. * The problem is that nUnits does not include this end-marker. It's
  366. * quite difficult to discriminate whether the following 0xFFFF comes from
  367. * the end-marker or some next data.
  368. *
  369. * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
  370. */
  371. static void
  372. gxv_LookupTable_fmt2_skip_endmarkers( FT_Bytes table,
  373. FT_UShort unitSize,
  374. GXV_Validator valid )
  375. {
  376. FT_Bytes p = table;
  377. while ( ( p + 4 ) < valid->root->limit )
  378. {
  379. if ( p[0] != 0xFF || p[1] != 0xFF || /* lastGlyph */
  380. p[2] != 0xFF || p[3] != 0xFF ) /* firstGlyph */
  381. break;
  382. p += unitSize;
  383. }
  384. valid->subtable_length = p - table;
  385. }
  386. static void
  387. gxv_LookupTable_fmt2_validate( FT_Bytes table,
  388. FT_Bytes limit,
  389. GXV_Validator valid )
  390. {
  391. FT_Bytes p = table;
  392. FT_UShort gid;
  393. FT_UShort unitSize;
  394. FT_UShort nUnits;
  395. FT_UShort unit;
  396. FT_UShort lastGlyph;
  397. FT_UShort firstGlyph;
  398. GXV_LookupValueDesc value;
  399. GXV_NAME_ENTER( "LookupTable format 2" );
  400. unitSize = nUnits = 0;
  401. gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
  402. p += valid->subtable_length;
  403. GXV_UNITSIZE_VALIDATE( "format2", unitSize, nUnits, 6 );
  404. for ( unit = 0, gid = 0; unit < nUnits; unit++ )
  405. {
  406. GXV_LIMIT_CHECK( 2 + 2 + 2 );
  407. lastGlyph = FT_NEXT_USHORT( p );
  408. firstGlyph = FT_NEXT_USHORT( p );
  409. value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
  410. gxv_glyphid_validate( firstGlyph, valid );
  411. gxv_glyphid_validate( lastGlyph, valid );
  412. if ( lastGlyph < gid )
  413. {
  414. GXV_TRACE(( "reverse ordered segment specification:"
  415. " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
  416. unit, lastGlyph, unit - 1 , gid ));
  417. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  418. }
  419. if ( lastGlyph < firstGlyph )
  420. {
  421. GXV_TRACE(( "reverse ordered range specification at unit %d:",
  422. " lastGlyph %d < firstGlyph %d ",
  423. unit, lastGlyph, firstGlyph ));
  424. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  425. if ( valid->root->level == FT_VALIDATE_TIGHT )
  426. continue; /* ftxvalidator silently skips such an entry */
  427. FT_TRACE4(( "continuing with exchanged values\n" ));
  428. gid = firstGlyph;
  429. firstGlyph = lastGlyph;
  430. lastGlyph = gid;
  431. }
  432. for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
  433. valid->lookupval_func( gid, &value, valid );
  434. }
  435. gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, valid );
  436. p += valid->subtable_length;
  437. valid->subtable_length = p - table;
  438. GXV_EXIT;
  439. }
  440. /* ================= Segment Array Format 4 Lookup Table =============== */
  441. static void
  442. gxv_LookupTable_fmt4_validate( FT_Bytes table,
  443. FT_Bytes limit,
  444. GXV_Validator valid )
  445. {
  446. FT_Bytes p = table;
  447. FT_UShort unit;
  448. FT_UShort gid;
  449. FT_UShort unitSize;
  450. FT_UShort nUnits;
  451. FT_UShort lastGlyph;
  452. FT_UShort firstGlyph;
  453. GXV_LookupValueDesc base_value;
  454. GXV_LookupValueDesc value;
  455. GXV_NAME_ENTER( "LookupTable format 4" );
  456. unitSize = nUnits = 0;
  457. gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
  458. p += valid->subtable_length;
  459. GXV_UNITSIZE_VALIDATE( "format4", unitSize, nUnits, 6 );
  460. for ( unit = 0, gid = 0; unit < nUnits; unit++ )
  461. {
  462. GXV_LIMIT_CHECK( 2 + 2 );
  463. lastGlyph = FT_NEXT_USHORT( p );
  464. firstGlyph = FT_NEXT_USHORT( p );
  465. gxv_glyphid_validate( firstGlyph, valid );
  466. gxv_glyphid_validate( lastGlyph, valid );
  467. if ( lastGlyph < gid )
  468. {
  469. GXV_TRACE(( "reverse ordered segment specification:"
  470. " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
  471. unit, lastGlyph, unit - 1 , gid ));
  472. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  473. }
  474. if ( lastGlyph < firstGlyph )
  475. {
  476. GXV_TRACE(( "reverse ordered range specification at unit %d:",
  477. " lastGlyph %d < firstGlyph %d ",
  478. unit, lastGlyph, firstGlyph ));
  479. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  480. if ( valid->root->level == FT_VALIDATE_TIGHT )
  481. continue; /* ftxvalidator silently skips such an entry */
  482. FT_TRACE4(( "continuing with exchanged values\n" ));
  483. gid = firstGlyph;
  484. firstGlyph = lastGlyph;
  485. lastGlyph = gid;
  486. }
  487. GXV_LIMIT_CHECK( 2 );
  488. base_value = GXV_LOOKUP_VALUE_LOAD( p, GXV_LOOKUPVALUE_UNSIGNED );
  489. for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
  490. {
  491. value = valid->lookupfmt4_trans( (FT_UShort)( gid - firstGlyph ),
  492. &base_value,
  493. limit,
  494. valid );
  495. valid->lookupval_func( gid, &value, valid );
  496. }
  497. }
  498. gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, valid );
  499. p += valid->subtable_length;
  500. valid->subtable_length = p - table;
  501. GXV_EXIT;
  502. }
  503. /* ================= Segment Table Format 6 Lookup Table =============== */
  504. static void
  505. gxv_LookupTable_fmt6_skip_endmarkers( FT_Bytes table,
  506. FT_UShort unitSize,
  507. GXV_Validator valid )
  508. {
  509. FT_Bytes p = table;
  510. while ( p < valid->root->limit )
  511. {
  512. if ( p[0] != 0xFF || p[1] != 0xFF )
  513. break;
  514. p += unitSize;
  515. }
  516. valid->subtable_length = p - table;
  517. }
  518. static void
  519. gxv_LookupTable_fmt6_validate( FT_Bytes table,
  520. FT_Bytes limit,
  521. GXV_Validator valid )
  522. {
  523. FT_Bytes p = table;
  524. FT_UShort unit;
  525. FT_UShort prev_glyph;
  526. FT_UShort unitSize;
  527. FT_UShort nUnits;
  528. FT_UShort glyph;
  529. GXV_LookupValueDesc value;
  530. GXV_NAME_ENTER( "LookupTable format 6" );
  531. unitSize = nUnits = 0;
  532. gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
  533. p += valid->subtable_length;
  534. GXV_UNITSIZE_VALIDATE( "format6", unitSize, nUnits, 4 );
  535. for ( unit = 0, prev_glyph = 0; unit < nUnits; unit++ )
  536. {
  537. GXV_LIMIT_CHECK( 2 + 2 );
  538. glyph = FT_NEXT_USHORT( p );
  539. value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
  540. if ( gxv_glyphid_validate( glyph, valid ) )
  541. GXV_TRACE(( " endmarker found within defined range"
  542. " (entry %d < nUnits=%d)\n",
  543. unit, nUnits ));
  544. if ( prev_glyph > glyph )
  545. {
  546. GXV_TRACE(( "current gid 0x%04x < previous gid 0x%04x\n",
  547. glyph, prev_glyph ));
  548. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  549. }
  550. prev_glyph = glyph;
  551. valid->lookupval_func( glyph, &value, valid );
  552. }
  553. gxv_LookupTable_fmt6_skip_endmarkers( p, unitSize, valid );
  554. p += valid->subtable_length;
  555. valid->subtable_length = p - table;
  556. GXV_EXIT;
  557. }
  558. /* ================= Trimmed Array Format 8 Lookup Table =============== */
  559. static void
  560. gxv_LookupTable_fmt8_validate( FT_Bytes table,
  561. FT_Bytes limit,
  562. GXV_Validator valid )
  563. {
  564. FT_Bytes p = table;
  565. FT_UShort i;
  566. GXV_LookupValueDesc value;
  567. FT_UShort firstGlyph;
  568. FT_UShort glyphCount;
  569. GXV_NAME_ENTER( "LookupTable format 8" );
  570. /* firstGlyph + glyphCount */
  571. GXV_LIMIT_CHECK( 2 + 2 );
  572. firstGlyph = FT_NEXT_USHORT( p );
  573. glyphCount = FT_NEXT_USHORT( p );
  574. gxv_glyphid_validate( firstGlyph, valid );
  575. gxv_glyphid_validate( (FT_UShort)( firstGlyph + glyphCount ), valid );
  576. /* valueArray */
  577. for ( i = 0; i < glyphCount; i++ )
  578. {
  579. GXV_LIMIT_CHECK( 2 );
  580. value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
  581. valid->lookupval_func( (FT_UShort)( firstGlyph + i ), &value, valid );
  582. }
  583. valid->subtable_length = p - table;
  584. GXV_EXIT;
  585. }
  586. FT_LOCAL_DEF( void )
  587. gxv_LookupTable_validate( FT_Bytes table,
  588. FT_Bytes limit,
  589. GXV_Validator valid )
  590. {
  591. FT_Bytes p = table;
  592. FT_UShort format;
  593. GXV_Validate_Func fmt_funcs_table[] =
  594. {
  595. gxv_LookupTable_fmt0_validate, /* 0 */
  596. NULL, /* 1 */
  597. gxv_LookupTable_fmt2_validate, /* 2 */
  598. NULL, /* 3 */
  599. gxv_LookupTable_fmt4_validate, /* 4 */
  600. NULL, /* 5 */
  601. gxv_LookupTable_fmt6_validate, /* 6 */
  602. NULL, /* 7 */
  603. gxv_LookupTable_fmt8_validate, /* 8 */
  604. };
  605. GXV_Validate_Func func;
  606. GXV_NAME_ENTER( "LookupTable" );
  607. /* lookuptbl_head may be used in fmt4 transit function. */
  608. valid->lookuptbl_head = table;
  609. /* format */
  610. GXV_LIMIT_CHECK( 2 );
  611. format = FT_NEXT_USHORT( p );
  612. GXV_TRACE(( " (format %d)\n", format ));
  613. if ( format > 8 )
  614. FT_INVALID_FORMAT;
  615. func = fmt_funcs_table[format];
  616. if ( func == NULL )
  617. FT_INVALID_FORMAT;
  618. func( p, limit, valid );
  619. p += valid->subtable_length;
  620. valid->subtable_length = p - table;
  621. GXV_EXIT;
  622. }
  623. /*************************************************************************/
  624. /*************************************************************************/
  625. /***** *****/
  626. /***** Glyph ID *****/
  627. /***** *****/
  628. /*************************************************************************/
  629. /*************************************************************************/
  630. FT_LOCAL_DEF( FT_Int )
  631. gxv_glyphid_validate( FT_UShort gid,
  632. GXV_Validator valid )
  633. {
  634. FT_Face face;
  635. if ( gid == 0xFFFFU )
  636. {
  637. GXV_EXIT;
  638. return 1;
  639. }
  640. face = valid->face;
  641. if ( face->num_glyphs < gid )
  642. {
  643. GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %d < %d\n",
  644. face->num_glyphs, gid ));
  645. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  646. }
  647. return 0;
  648. }
  649. /*************************************************************************/
  650. /*************************************************************************/
  651. /***** *****/
  652. /***** CONTROL POINT *****/
  653. /***** *****/
  654. /*************************************************************************/
  655. /*************************************************************************/
  656. FT_LOCAL_DEF( void )
  657. gxv_ctlPoint_validate( FT_UShort gid,
  658. FT_Short ctl_point,
  659. GXV_Validator valid )
  660. {
  661. FT_Face face;
  662. FT_Error error;
  663. FT_GlyphSlot glyph;
  664. FT_Outline outline;
  665. short n_points;
  666. face = valid->face;
  667. error = FT_Load_Glyph( face,
  668. gid,
  669. FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM );
  670. if ( error )
  671. FT_INVALID_GLYPH_ID;
  672. glyph = face->glyph;
  673. outline = glyph->outline;
  674. n_points = outline.n_points;
  675. if ( !( ctl_point < n_points ) )
  676. FT_INVALID_DATA;
  677. }
  678. /*************************************************************************/
  679. /*************************************************************************/
  680. /***** *****/
  681. /***** SFNT NAME *****/
  682. /***** *****/
  683. /*************************************************************************/
  684. /*************************************************************************/
  685. FT_LOCAL_DEF( void )
  686. gxv_sfntName_validate( FT_UShort name_index,
  687. FT_UShort min_index,
  688. FT_UShort max_index,
  689. GXV_Validator valid )
  690. {
  691. FT_SfntName name;
  692. FT_UInt i;
  693. FT_UInt nnames;
  694. GXV_NAME_ENTER( "sfntName" );
  695. if ( name_index < min_index || max_index < name_index )
  696. FT_INVALID_FORMAT;
  697. nnames = FT_Get_Sfnt_Name_Count( valid->face );
  698. for ( i = 0; i < nnames; i++ )
  699. {
  700. if ( FT_Get_Sfnt_Name( valid->face, i, &name ) != GXV_Err_Ok )
  701. continue ;
  702. if ( name.name_id == name_index )
  703. goto Out;
  704. }
  705. GXV_TRACE(( " nameIndex = %d (UNTITLED)\n", name_index ));
  706. FT_INVALID_DATA;
  707. goto Exit; /* make compiler happy */
  708. Out:
  709. FT_TRACE1(( " nameIndex = %d (", name_index ));
  710. GXV_TRACE_HEXDUMP_SFNTNAME( name );
  711. FT_TRACE1(( ")\n" ));
  712. Exit:
  713. GXV_EXIT;
  714. }
  715. /*************************************************************************/
  716. /*************************************************************************/
  717. /***** *****/
  718. /***** STATE TABLE *****/
  719. /***** *****/
  720. /*************************************************************************/
  721. /*************************************************************************/
  722. /* -------------------------- Class Table --------------------------- */
  723. /*
  724. * highestClass specifies how many classes are defined in this
  725. * Class Subtable. Apple spec does not mention whether undefined
  726. * holes in the class (e.g.: 0-3 are predefined, 4 is unused, 5 is used)
  727. * are permitted. At present, holes in a defined class are not checked.
  728. * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
  729. */
  730. static void
  731. gxv_ClassTable_validate( FT_Bytes table,
  732. FT_UShort* length_p,
  733. FT_UShort stateSize,
  734. FT_Byte* maxClassID_p,
  735. GXV_Validator valid )
  736. {
  737. FT_Bytes p = table;
  738. FT_Bytes limit = table + *length_p;
  739. FT_UShort firstGlyph;
  740. FT_UShort nGlyphs;
  741. GXV_NAME_ENTER( "ClassTable" );
  742. *maxClassID_p = 3; /* Classes 0, 2, and 3 are predefined */
  743. GXV_LIMIT_CHECK( 2 + 2 );
  744. firstGlyph = FT_NEXT_USHORT( p );
  745. nGlyphs = FT_NEXT_USHORT( p );
  746. GXV_TRACE(( " (firstGlyph = %d, nGlyphs = %d)\n", firstGlyph, nGlyphs ));
  747. if ( !nGlyphs )
  748. goto Out;
  749. gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs ), valid );
  750. {
  751. FT_Byte nGlyphInClass[256];
  752. FT_Byte classID;
  753. FT_UShort i;
  754. ft_memset( nGlyphInClass, 0, 256 );
  755. for ( i = 0; i < nGlyphs; i++ )
  756. {
  757. GXV_LIMIT_CHECK( 1 );
  758. classID = FT_NEXT_BYTE( p );
  759. switch ( classID )
  760. {
  761. /* following classes should not appear in class array */
  762. case 0: /* end of text */
  763. case 2: /* out of bounds */
  764. case 3: /* end of line */
  765. FT_INVALID_DATA;
  766. break;
  767. case 1: /* out of bounds */
  768. default: /* user-defined: 4 - ( stateSize - 1 ) */
  769. if ( classID >= stateSize )
  770. FT_INVALID_DATA; /* assign glyph to undefined state */
  771. nGlyphInClass[classID]++;
  772. break;
  773. }
  774. }
  775. *length_p = (FT_UShort)( p - table );
  776. /* scan max ClassID in use */
  777. for ( i = 0; i < stateSize; i++ )
  778. if ( ( 3 < i ) && ( nGlyphInClass[i] > 0 ) )
  779. *maxClassID_p = (FT_Byte)i; /* XXX: Check Range? */
  780. }
  781. Out:
  782. GXV_TRACE(( "Declared stateSize=0x%02x, Used maxClassID=0x%02x\n",
  783. stateSize, *maxClassID_p ));
  784. GXV_EXIT;
  785. }
  786. /* --------------------------- State Array ----------------------------- */
  787. static void
  788. gxv_StateArray_validate( FT_Bytes table,
  789. FT_UShort* length_p,
  790. FT_Byte maxClassID,
  791. FT_UShort stateSize,
  792. FT_Byte* maxState_p,
  793. FT_Byte* maxEntry_p,
  794. GXV_Validator valid )
  795. {
  796. FT_Bytes p = table;
  797. FT_Bytes limit = table + *length_p;
  798. FT_Byte clazz;
  799. FT_Byte entry;
  800. FT_UNUSED( stateSize ); /* for the non-debugging case */
  801. GXV_NAME_ENTER( "StateArray" );
  802. GXV_TRACE(( "parse %d bytes by stateSize=%d maxClassID=%d\n",
  803. (int)(*length_p), stateSize, (int)(maxClassID) ));
  804. /*
  805. * 2 states are predefined and must be described in StateArray:
  806. * state 0 (start of text), 1 (start of line)
  807. */
  808. GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 );
  809. *maxState_p = 0;
  810. *maxEntry_p = 0;
  811. /* read if enough to read another state */
  812. while ( p + ( 1 + maxClassID ) <= limit )
  813. {
  814. (*maxState_p)++;
  815. for ( clazz = 0; clazz <= maxClassID; clazz++ )
  816. {
  817. entry = FT_NEXT_BYTE( p );
  818. *maxEntry_p = (FT_Byte)FT_MAX( *maxEntry_p, entry );
  819. }
  820. }
  821. GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n",
  822. *maxState_p, *maxEntry_p ));
  823. *length_p = (FT_UShort)( p - table );
  824. GXV_EXIT;
  825. }
  826. /* --------------------------- Entry Table ----------------------------- */
  827. static void
  828. gxv_EntryTable_validate( FT_Bytes table,
  829. FT_UShort* length_p,
  830. FT_Byte maxEntry,
  831. FT_UShort stateArray,
  832. FT_UShort stateArray_length,
  833. FT_Byte maxClassID,
  834. FT_Bytes statetable_table,
  835. FT_Bytes statetable_limit,
  836. GXV_Validator valid )
  837. {
  838. FT_Bytes p = table;
  839. FT_Bytes limit = table + *length_p;
  840. FT_Byte entry;
  841. FT_Byte state;
  842. FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( statetable );
  843. GXV_XStateTable_GlyphOffsetDesc glyphOffset;
  844. GXV_NAME_ENTER( "EntryTable" );
  845. GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
  846. if ( ( maxEntry + 1 ) * entrySize > *length_p )
  847. {
  848. GXV_SET_ERR_IF_PARANOID( FT_INVALID_TOO_SHORT );
  849. /* ftxvalidator and FontValidator both warn and continue */
  850. maxEntry = (FT_Byte)( *length_p / entrySize - 1 );
  851. GXV_TRACE(( "too large maxEntry, shrinking to %d fit EntryTable length\n",
  852. maxEntry ));
  853. }
  854. for ( entry = 0; entry <= maxEntry; entry++ )
  855. {
  856. FT_UShort newState;
  857. FT_UShort flags;
  858. GXV_LIMIT_CHECK( 2 + 2 );
  859. newState = FT_NEXT_USHORT( p );
  860. flags = FT_NEXT_USHORT( p );
  861. if ( newState < stateArray ||
  862. stateArray + stateArray_length < newState )
  863. {
  864. GXV_TRACE(( " newState offset 0x%04x is out of stateArray\n",
  865. newState ));
  866. GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  867. continue;
  868. }
  869. if ( 0 != ( ( newState - stateArray ) % ( 1 + maxClassID ) ) )
  870. {
  871. GXV_TRACE(( " newState offset 0x%04x is not aligned to %d-classes\n",
  872. newState, 1 + maxClassID ));
  873. GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  874. continue;
  875. }
  876. state = (FT_Byte)( ( newState - stateArray ) / ( 1 + maxClassID ) );
  877. switch ( GXV_GLYPHOFFSET_FMT( statetable ) )
  878. {
  879. case GXV_GLYPHOFFSET_NONE:
  880. glyphOffset.uc = 0; /* make compiler happy */
  881. break;
  882. case GXV_GLYPHOFFSET_UCHAR:
  883. glyphOffset.uc = FT_NEXT_BYTE( p );
  884. break;
  885. case GXV_GLYPHOFFSET_CHAR:
  886. glyphOffset.c = FT_NEXT_CHAR( p );
  887. break;
  888. case GXV_GLYPHOFFSET_USHORT:
  889. glyphOffset.u = FT_NEXT_USHORT( p );
  890. break;
  891. case GXV_GLYPHOFFSET_SHORT:
  892. glyphOffset.s = FT_NEXT_SHORT( p );
  893. break;
  894. case GXV_GLYPHOFFSET_ULONG:
  895. glyphOffset.ul = FT_NEXT_ULONG( p );
  896. break;
  897. case GXV_GLYPHOFFSET_LONG:
  898. glyphOffset.l = FT_NEXT_LONG( p );
  899. break;
  900. default:
  901. GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
  902. goto Exit;
  903. }
  904. if ( NULL != valid->statetable.entry_validate_func )
  905. valid->statetable.entry_validate_func( state,
  906. flags,
  907. &glyphOffset,
  908. statetable_table,
  909. statetable_limit,
  910. valid );
  911. }
  912. Exit:
  913. *length_p = (FT_UShort)( p - table );
  914. GXV_EXIT;
  915. }
  916. /* =========================== State Table ============================= */
  917. FT_LOCAL_DEF( void )
  918. gxv_StateTable_subtable_setup( FT_UShort table_size,
  919. FT_UShort classTable,
  920. FT_UShort stateArray,
  921. FT_UShort entryTable,
  922. FT_UShort* classTable_length_p,
  923. FT_UShort* stateArray_length_p,
  924. FT_UShort* entryTable_length_p,
  925. GXV_Validator valid )
  926. {
  927. FT_UShort o[3];
  928. FT_UShort* l[3];
  929. FT_UShort buff[4];
  930. o[0] = classTable;
  931. o[1] = stateArray;
  932. o[2] = entryTable;
  933. l[0] = classTable_length_p;
  934. l[1] = stateArray_length_p;
  935. l[2] = entryTable_length_p;
  936. gxv_set_length_by_ushort_offset( o, l, buff, 3, table_size, valid );
  937. }
  938. FT_LOCAL_DEF( void )
  939. gxv_StateTable_validate( FT_Bytes table,
  940. FT_Bytes limit,
  941. GXV_Validator valid )
  942. {
  943. FT_UShort stateSize;
  944. FT_UShort classTable; /* offset to Class(Sub)Table */
  945. FT_UShort stateArray; /* offset to StateArray */
  946. FT_UShort entryTable; /* offset to EntryTable */
  947. FT_UShort classTable_length;
  948. FT_UShort stateArray_length;
  949. FT_UShort entryTable_length;
  950. FT_Byte maxClassID;
  951. FT_Byte maxState;
  952. FT_Byte maxEntry;
  953. GXV_StateTable_Subtable_Setup_Func setup_func;
  954. FT_Bytes p = table;
  955. GXV_NAME_ENTER( "StateTable" );
  956. GXV_TRACE(( "StateTable header\n" ));
  957. GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
  958. stateSize = FT_NEXT_USHORT( p );
  959. classTable = FT_NEXT_USHORT( p );
  960. stateArray = FT_NEXT_USHORT( p );
  961. entryTable = FT_NEXT_USHORT( p );
  962. GXV_TRACE(( "stateSize=0x%04x\n", stateSize ));
  963. GXV_TRACE(( "offset to classTable=0x%04x\n", classTable ));
  964. GXV_TRACE(( "offset to stateArray=0x%04x\n", stateArray ));
  965. GXV_TRACE(( "offset to entryTable=0x%04x\n", entryTable ));
  966. if ( stateSize > 0xFF )
  967. FT_INVALID_DATA;
  968. if ( valid->statetable.optdata_load_func != NULL )
  969. valid->statetable.optdata_load_func( p, limit, valid );
  970. if ( valid->statetable.subtable_setup_func != NULL)
  971. setup_func = valid->statetable.subtable_setup_func;
  972. else
  973. setup_func = gxv_StateTable_subtable_setup;
  974. setup_func( (FT_UShort)( limit - table ),
  975. classTable,
  976. stateArray,
  977. entryTable,
  978. &classTable_length,
  979. &stateArray_length,
  980. &entryTable_length,
  981. valid );
  982. GXV_TRACE(( "StateTable Subtables\n" ));
  983. if ( classTable != 0 )
  984. gxv_ClassTable_validate( table + classTable,
  985. &classTable_length,
  986. stateSize,
  987. &maxClassID,
  988. valid );
  989. else
  990. maxClassID = (FT_Byte)( stateSize - 1 );
  991. if ( stateArray != 0 )
  992. gxv_StateArray_validate( table + stateArray,
  993. &stateArray_length,
  994. maxClassID,
  995. stateSize,
  996. &maxState,
  997. &maxEntry,
  998. valid );
  999. else
  1000. {
  1001. maxState = 1; /* 0:start of text, 1:start of line are predefined */
  1002. maxEntry = 0;
  1003. }
  1004. if ( maxEntry > 0 && entryTable == 0 )
  1005. FT_INVALID_OFFSET;
  1006. if ( entryTable != 0 )
  1007. gxv_EntryTable_validate( table + entryTable,
  1008. &entryTable_length,
  1009. maxEntry,
  1010. stateArray,
  1011. stateArray_length,
  1012. maxClassID,
  1013. table,
  1014. limit,
  1015. valid );
  1016. GXV_EXIT;
  1017. }
  1018. /* ================= eXtended State Table (for morx) =================== */
  1019. FT_LOCAL_DEF( void )
  1020. gxv_XStateTable_subtable_setup( FT_ULong table_size,
  1021. FT_ULong classTable,
  1022. FT_ULong stateArray,
  1023. FT_ULong entryTable,
  1024. FT_ULong* classTable_length_p,
  1025. FT_ULong* stateArray_length_p,
  1026. FT_ULong* entryTable_length_p,
  1027. GXV_Validator valid )
  1028. {
  1029. FT_ULong o[3];
  1030. FT_ULong* l[3];
  1031. FT_ULong buff[4];
  1032. o[0] = classTable;
  1033. o[1] = stateArray;
  1034. o[2] = entryTable;
  1035. l[0] = classTable_length_p;
  1036. l[1] = stateArray_length_p;
  1037. l[2] = entryTable_length_p;
  1038. gxv_set_length_by_ulong_offset( o, l, buff, 3, table_size, valid );
  1039. }
  1040. static void
  1041. gxv_XClassTable_lookupval_validate( FT_UShort glyph,
  1042. GXV_LookupValueCPtr value_p,
  1043. GXV_Validator valid )
  1044. {
  1045. FT_UNUSED( glyph );
  1046. if ( value_p->u >= valid->xstatetable.nClasses )
  1047. FT_INVALID_DATA;
  1048. if ( value_p->u > valid->xstatetable.maxClassID )
  1049. valid->xstatetable.maxClassID = value_p->u;
  1050. }
  1051. /*
  1052. +===============+ --------+
  1053. | lookup header | |
  1054. +===============+ |
  1055. | BinSrchHeader | |
  1056. +===============+ |
  1057. | lastGlyph[0] | |
  1058. +---------------+ |
  1059. | firstGlyph[0] | | head of lookup table
  1060. +---------------+ | +
  1061. | offset[0] | -> | offset [byte]
  1062. +===============+ | +
  1063. | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
  1064. +---------------+ |
  1065. | firstGlyph[1] | |
  1066. +---------------+ |
  1067. | offset[1] | |
  1068. +===============+ |
  1069. |
  1070. .... |
  1071. |
  1072. 16bit value array |
  1073. +===============+ |
  1074. | value | <-------+
  1075. ....
  1076. */
  1077. static GXV_LookupValueDesc
  1078. gxv_XClassTable_lookupfmt4_transit( FT_UShort relative_gindex,
  1079. GXV_LookupValueCPtr base_value_p,
  1080. FT_Bytes lookuptbl_limit,
  1081. GXV_Validator valid )
  1082. {
  1083. FT_Bytes p;
  1084. FT_Bytes limit;
  1085. FT_UShort offset;
  1086. GXV_LookupValueDesc value;
  1087. /* XXX: check range? */
  1088. offset = (FT_UShort)( base_value_p->u +
  1089. relative_gindex * sizeof ( FT_UShort ) );
  1090. p = valid->lookuptbl_head + offset;
  1091. limit = lookuptbl_limit;
  1092. GXV_LIMIT_CHECK ( 2 );
  1093. value.u = FT_NEXT_USHORT( p );
  1094. return value;
  1095. }
  1096. static void
  1097. gxv_XStateArray_validate( FT_Bytes table,
  1098. FT_ULong* length_p,
  1099. FT_UShort maxClassID,
  1100. FT_ULong stateSize,
  1101. FT_UShort* maxState_p,
  1102. FT_UShort* maxEntry_p,
  1103. GXV_Validator valid )
  1104. {
  1105. FT_Bytes p = table;
  1106. FT_Bytes limit = table + *length_p;
  1107. FT_UShort clazz;
  1108. FT_UShort entry;
  1109. FT_UNUSED( stateSize ); /* for the non-debugging case */
  1110. GXV_NAME_ENTER( "XStateArray" );
  1111. GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n",
  1112. (int)(*length_p), stateSize, (int)(maxClassID) ));
  1113. /*
  1114. * 2 states are predefined and must be described:
  1115. * state 0 (start of text), 1 (start of line)
  1116. */
  1117. GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 * 2 );
  1118. *maxState_p = 0;
  1119. *maxEntry_p = 0;
  1120. /* read if enough to read another state */
  1121. while ( p + ( ( 1 + maxClassID ) * 2 ) <= limit )
  1122. {
  1123. (*maxState_p)++;
  1124. for ( clazz = 0; clazz <= maxClassID; clazz++ )
  1125. {
  1126. entry = FT_NEXT_USHORT( p );
  1127. *maxEntry_p = (FT_UShort)FT_MAX( *maxEntry_p, entry );
  1128. }
  1129. }
  1130. GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n",
  1131. *maxState_p, *maxEntry_p ));
  1132. *length_p = p - table;
  1133. GXV_EXIT;
  1134. }
  1135. static void
  1136. gxv_XEntryTable_validate( FT_Bytes table,
  1137. FT_ULong* length_p,
  1138. FT_UShort maxEntry,
  1139. FT_ULong stateArray_length,
  1140. FT_UShort maxClassID,
  1141. FT_Bytes xstatetable_table,
  1142. FT_Bytes xstatetable_limit,
  1143. GXV_Validator valid )
  1144. {
  1145. FT_Bytes p = table;
  1146. FT_Bytes limit = table + *length_p;
  1147. FT_UShort entry;
  1148. FT_UShort state;
  1149. FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( xstatetable );
  1150. GXV_NAME_ENTER( "XEntryTable" );
  1151. GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
  1152. if ( ( p + ( maxEntry + 1 ) * entrySize ) > limit )
  1153. FT_INVALID_TOO_SHORT;
  1154. for (entry = 0; entry <= maxEntry ; entry++ )
  1155. {
  1156. FT_UShort newState_idx;
  1157. FT_UShort flags;
  1158. GXV_XStateTable_GlyphOffsetDesc glyphOffset;
  1159. GXV_LIMIT_CHECK( 2 + 2 );
  1160. newState_idx = FT_NEXT_USHORT( p );
  1161. flags = FT_NEXT_USHORT( p );
  1162. if ( stateArray_length < (FT_ULong)( newState_idx * 2 ) )
  1163. {
  1164. GXV_TRACE(( " newState index 0x%04x points out of stateArray\n",
  1165. newState_idx ));
  1166. GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  1167. }
  1168. state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) );
  1169. if ( 0 != ( newState_idx % ( 1 + maxClassID ) ) )
  1170. {
  1171. FT_TRACE4(( "-> new state = %d (supposed)\n"
  1172. "but newState index 0x%04x is not aligned to %d-classes\n",
  1173. state, newState_idx, 1 + maxClassID ));
  1174. GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  1175. }
  1176. switch ( GXV_GLYPHOFFSET_FMT( xstatetable ) )
  1177. {
  1178. case GXV_GLYPHOFFSET_NONE:
  1179. glyphOffset.uc = 0; /* make compiler happy */
  1180. break;
  1181. case GXV_GLYPHOFFSET_UCHAR:
  1182. glyphOffset.uc = FT_NEXT_BYTE( p );
  1183. break;
  1184. case GXV_GLYPHOFFSET_CHAR:
  1185. glyphOffset.c = FT_NEXT_CHAR( p );
  1186. break;
  1187. case GXV_GLYPHOFFSET_USHORT:
  1188. glyphOffset.u = FT_NEXT_USHORT( p );
  1189. break;
  1190. case GXV_GLYPHOFFSET_SHORT:
  1191. glyphOffset.s = FT_NEXT_SHORT( p );
  1192. break;
  1193. case GXV_GLYPHOFFSET_ULONG:
  1194. glyphOffset.ul = FT_NEXT_ULONG( p );
  1195. break;
  1196. case GXV_GLYPHOFFSET_LONG:
  1197. glyphOffset.l = FT_NEXT_LONG( p );
  1198. break;
  1199. default:
  1200. GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
  1201. goto Exit;
  1202. }
  1203. if ( NULL != valid->xstatetable.entry_validate_func )
  1204. valid->xstatetable.entry_validate_func( state,
  1205. flags,
  1206. &glyphOffset,
  1207. xstatetable_table,
  1208. xstatetable_limit,
  1209. valid );
  1210. }
  1211. Exit:
  1212. *length_p = p - table;
  1213. GXV_EXIT;
  1214. }
  1215. FT_LOCAL_DEF( void )
  1216. gxv_XStateTable_validate( FT_Bytes table,
  1217. FT_Bytes limit,
  1218. GXV_Validator valid )
  1219. {
  1220. /* StateHeader members */
  1221. FT_ULong classTable; /* offset to Class(Sub)Table */
  1222. FT_ULong stateArray; /* offset to StateArray */
  1223. FT_ULong entryTable; /* offset to EntryTable */
  1224. FT_ULong classTable_length;
  1225. FT_ULong stateArray_length;
  1226. FT_ULong entryTable_length;
  1227. FT_UShort maxState;
  1228. FT_UShort maxEntry;
  1229. GXV_XStateTable_Subtable_Setup_Func setup_func;
  1230. FT_Bytes p = table;
  1231. GXV_NAME_ENTER( "XStateTable" );
  1232. GXV_TRACE(( "XStateTable header\n" ));
  1233. GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
  1234. valid->xstatetable.nClasses = FT_NEXT_ULONG( p );
  1235. classTable = FT_NEXT_ULONG( p );
  1236. stateArray = FT_NEXT_ULONG( p );
  1237. entryTable = FT_NEXT_ULONG( p );
  1238. GXV_TRACE(( "nClasses =0x%08x\n", valid->xstatetable.nClasses ));
  1239. GXV_TRACE(( "offset to classTable=0x%08x\n", classTable ));
  1240. GXV_TRACE(( "offset to stateArray=0x%08x\n", stateArray ));
  1241. GXV_TRACE(( "offset to entryTable=0x%08x\n", entryTable ));
  1242. if ( valid->xstatetable.nClasses > 0xFFFFU )
  1243. FT_INVALID_DATA;
  1244. GXV_TRACE(( "StateTable Subtables\n" ));
  1245. if ( valid->xstatetable.optdata_load_func != NULL )
  1246. valid->xstatetable.optdata_load_func( p, limit, valid );
  1247. if ( valid->xstatetable.subtable_setup_func != NULL )
  1248. setup_func = valid->xstatetable.subtable_setup_func;
  1249. else
  1250. setup_func = gxv_XStateTable_subtable_setup;
  1251. setup_func( limit - table,
  1252. classTable,
  1253. stateArray,
  1254. entryTable,
  1255. &classTable_length,
  1256. &stateArray_length,
  1257. &entryTable_length,
  1258. valid );
  1259. if ( classTable != 0 )
  1260. {
  1261. valid->xstatetable.maxClassID = 0;
  1262. valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
  1263. valid->lookupval_func = gxv_XClassTable_lookupval_validate;
  1264. valid->lookupfmt4_trans = gxv_XClassTable_lookupfmt4_transit;
  1265. gxv_LookupTable_validate( table + classTable,
  1266. table + classTable + classTable_length,
  1267. valid );
  1268. if ( valid->subtable_length < classTable_length )
  1269. classTable_length = valid->subtable_length;
  1270. }
  1271. else
  1272. {
  1273. /* XXX: check range? */
  1274. valid->xstatetable.maxClassID =
  1275. (FT_UShort)( valid->xstatetable.nClasses - 1 );
  1276. }
  1277. if ( stateArray != 0 )
  1278. gxv_XStateArray_validate( table + stateArray,
  1279. &stateArray_length,
  1280. valid->xstatetable.maxClassID,
  1281. valid->xstatetable.nClasses,
  1282. &maxState,
  1283. &maxEntry,
  1284. valid );
  1285. else
  1286. {
  1287. maxState = 1; /* 0:start of text, 1:start of line are predefined */
  1288. maxEntry = 0;
  1289. }
  1290. if ( maxEntry > 0 && entryTable == 0 )
  1291. FT_INVALID_OFFSET;
  1292. if ( entryTable != 0 )
  1293. gxv_XEntryTable_validate( table + entryTable,
  1294. &entryTable_length,
  1295. maxEntry,
  1296. stateArray_length,
  1297. valid->xstatetable.maxClassID,
  1298. table,
  1299. limit,
  1300. valid );
  1301. GXV_EXIT;
  1302. }
  1303. /*************************************************************************/
  1304. /*************************************************************************/
  1305. /***** *****/
  1306. /***** Table overlapping *****/
  1307. /***** *****/
  1308. /*************************************************************************/
  1309. /*************************************************************************/
  1310. static int
  1311. gxv_compare_ranges( FT_Bytes table1_start,
  1312. FT_ULong table1_length,
  1313. FT_Bytes table2_start,
  1314. FT_ULong table2_length )
  1315. {
  1316. if ( table1_start == table2_start )
  1317. {
  1318. if ( ( table1_length == 0 || table2_length == 0 ) )
  1319. goto Out;
  1320. }
  1321. else if ( table1_start < table2_start )
  1322. {
  1323. if ( ( table1_start + table1_length ) <= table2_start )
  1324. goto Out;
  1325. }
  1326. else if ( table1_start > table2_start )
  1327. {
  1328. if ( ( table1_start >= table2_start + table2_length ) )
  1329. goto Out;
  1330. }
  1331. return 1;
  1332. Out:
  1333. return 0;
  1334. }
  1335. FT_LOCAL_DEF( void )
  1336. gxv_odtect_add_range( FT_Bytes start,
  1337. FT_ULong length,
  1338. const FT_String* name,
  1339. GXV_odtect_Range odtect )
  1340. {
  1341. odtect->range[odtect->nRanges].start = start;
  1342. odtect->range[odtect->nRanges].length = length;
  1343. odtect->range[odtect->nRanges].name = (FT_String*)name;
  1344. odtect->nRanges++;
  1345. }
  1346. FT_LOCAL_DEF( void )
  1347. gxv_odtect_validate( GXV_odtect_Range odtect,
  1348. GXV_Validator valid )
  1349. {
  1350. FT_UInt i, j;
  1351. GXV_NAME_ENTER( "check overlap among multi ranges" );
  1352. for ( i = 0; i < odtect->nRanges; i++ )
  1353. for ( j = 0; j < i; j++ )
  1354. if ( 0 != gxv_compare_ranges( odtect->range[i].start,
  1355. odtect->range[i].length,
  1356. odtect->range[j].start,
  1357. odtect->range[j].length ) )
  1358. {
  1359. if ( odtect->range[i].name || odtect->range[j].name )
  1360. GXV_TRACE(( "found overlap between range %d and range %d\n",
  1361. i, j ));
  1362. else
  1363. GXV_TRACE(( "found overlap between `%s' and `%s\'\n",
  1364. odtect->range[i].name,
  1365. odtect->range[j].name ));
  1366. FT_INVALID_OFFSET;
  1367. }
  1368. GXV_EXIT;
  1369. }
  1370. /* END */