LETableReference.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * -*- c++ -*-
  3. *
  4. * (C) Copyright IBM Corp. and others 2015 - All Rights Reserved
  5. *
  6. * Range checking
  7. *
  8. */
  9. #ifndef __LETABLEREFERENCE_H
  10. #define __LETABLEREFERENCE_H
  11. #include "LETypes.h"
  12. #include "LEFontInstance.h"
  13. #define kQuestionmarkTableTag 0x3F3F3F3FUL
  14. #define kTildeTableTag 0x7e7e7e7eUL
  15. #ifdef __cplusplus
  16. // internal - interface for range checking
  17. U_NAMESPACE_BEGIN
  18. #if LE_ASSERT_BAD_FONT
  19. class LETableReference; // fwd
  20. /**
  21. * defined in OpenTypeUtilities.cpp
  22. * @internal
  23. */
  24. extern void _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len);
  25. #define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
  26. #define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z);
  27. #if 0
  28. #define LE_TRACE_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
  29. #else
  30. #define LE_TRACE_TR(x)
  31. #endif
  32. #else
  33. #define LE_DEBUG_TR(x)
  34. #define LE_DEBUG_TR3(x,y,z)
  35. #define LE_TRACE_TR(x)
  36. #endif
  37. /**
  38. * @internal
  39. */
  40. class LETableReference {
  41. public:
  42. /**
  43. * @internal
  44. * Construct from a specific tag
  45. */
  46. LETableReference(const LEFontInstance* font, LETag tableTag, LEErrorCode &success) :
  47. fFont(font), fTag(tableTag), fParent(NULL), fStart(NULL),fLength(LE_UINTPTR_MAX) {
  48. loadTable(success);
  49. LE_TRACE_TR("INFO: new table load")
  50. }
  51. LETableReference(const LETableReference &parent, LEErrorCode &success) : fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), fStart(parent.fStart), fLength(parent.fLength) {
  52. if(LE_FAILURE(success)) {
  53. clear();
  54. }
  55. LE_TRACE_TR("INFO: new clone")
  56. }
  57. LETableReference(const le_uint8* data, size_t length = LE_UINTPTR_MAX) :
  58. fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) {
  59. LE_TRACE_TR("INFO: new raw")
  60. }
  61. LETableReference() :
  62. fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(NULL), fLength(0) {
  63. LE_TRACE_TR("INFO: new empty")
  64. }
  65. ~LETableReference() {
  66. fTag=kTildeTableTag;
  67. LE_TRACE_TR("INFO: new dtor")
  68. }
  69. /**
  70. * @internal
  71. * @param length if LE_UINTPTR_MAX means "whole table"
  72. * subset
  73. */
  74. LETableReference(const LETableReference &parent, size_t offset, size_t length,
  75. LEErrorCode &err) :
  76. fFont(parent.fFont), fTag(parent.fTag), fParent(&parent),
  77. fStart((parent.fStart)+offset), fLength(length) {
  78. if(LE_SUCCESS(err)) {
  79. if(isEmpty()) {
  80. //err = LE_MISSING_FONT_TABLE_ERROR;
  81. clear(); // it's just empty. Not an error.
  82. } else if(offset >= fParent->fLength) {
  83. LE_DEBUG_TR3("offset out of range: (%p) +%d", NULL, offset);
  84. err = LE_INDEX_OUT_OF_BOUNDS_ERROR;
  85. clear();
  86. } else {
  87. if(fLength == LE_UINTPTR_MAX &&
  88. fParent->fLength != LE_UINTPTR_MAX) {
  89. fLength = (fParent->fLength) - offset; // decrement length as base address is incremented
  90. }
  91. if(fLength != LE_UINTPTR_MAX) { // if we have bounds:
  92. if(offset+fLength > fParent->fLength) {
  93. LE_DEBUG_TR3("offset+fLength out of range: (%p) +%d", NULL, offset+fLength);
  94. err = LE_INDEX_OUT_OF_BOUNDS_ERROR; // exceeded
  95. clear();
  96. }
  97. }
  98. }
  99. } else {
  100. clear();
  101. }
  102. LE_TRACE_TR("INFO: new subset")
  103. }
  104. const void* getAlias() const { return (const void*)fStart; }
  105. const void* getAliasRAW() const { LE_DEBUG_TR("getAliasRAW()"); return (const void*)fStart; }
  106. le_bool isEmpty() const { return fStart==NULL || fLength==0; }
  107. le_bool isValid() const { return !isEmpty(); }
  108. le_bool hasBounds() const { return fLength!=LE_UINTPTR_MAX; }
  109. void clear() { fLength=0; fStart=NULL; }
  110. size_t getLength() const { return fLength; }
  111. const LEFontInstance* getFont() const { return fFont; }
  112. LETag getTag() const { return fTag; }
  113. const LETableReference* getParent() const { return fParent; }
  114. void addOffset(size_t offset, LEErrorCode &success) {
  115. if(hasBounds()) {
  116. if(offset > fLength) {
  117. LE_DEBUG_TR("addOffset off end");
  118. success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
  119. return;
  120. } else {
  121. fLength -= offset;
  122. }
  123. }
  124. fStart += offset;
  125. }
  126. size_t ptrToOffset(const void *atPtr, LEErrorCode &success) const {
  127. if(atPtr==NULL) return 0;
  128. if(LE_FAILURE(success)) return LE_UINTPTR_MAX;
  129. if((atPtr < fStart) ||
  130. (hasBounds() && (atPtr > fStart+fLength))) {
  131. LE_DEBUG_TR3("ptrToOffset args out of range: %p", atPtr, 0);
  132. success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
  133. return LE_UINTPTR_MAX;
  134. }
  135. return ((const le_uint8*)atPtr)-fStart;
  136. }
  137. /**
  138. * Clamp down the length, for range checking.
  139. */
  140. size_t contractLength(size_t newLength) {
  141. if(fLength!=LE_UINTPTR_MAX&&newLength>0&&newLength<=fLength) {
  142. fLength = newLength;
  143. }
  144. return fLength;
  145. }
  146. /**
  147. * Throw an error if offset+length off end
  148. */
  149. public:
  150. size_t verifyLength(size_t offset, size_t length, LEErrorCode &success) {
  151. if(isValid()&&
  152. LE_SUCCESS(success) &&
  153. fLength!=LE_UINTPTR_MAX && length!=LE_UINTPTR_MAX && offset!=LE_UINTPTR_MAX &&
  154. (offset+length)>fLength) {
  155. LE_DEBUG_TR3("verifyLength failed (%p) %d",NULL, offset+length);
  156. success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
  157. #if LE_ASSERT_BAD_FONT
  158. fprintf(stderr, "offset=%lu, len=%lu, would be at %p, (%lu) off end. End at %p\n", offset,length, fStart+offset+length, (offset+length-fLength), (offset+length-fLength)+fStart);
  159. #endif
  160. }
  161. return fLength;
  162. }
  163. /**
  164. * Throw an error if size*count overflows
  165. */
  166. size_t verifyLength(size_t offset, size_t size, le_uint32 count, LEErrorCode &success) {
  167. if(count!=0 && size>LE_UINT32_MAX/count) {
  168. LE_DEBUG_TR3("verifyLength failed size=%u, count=%u", size, count);
  169. success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
  170. return 0;
  171. }
  172. return verifyLength(offset, size*count, success);
  173. }
  174. /**
  175. * Change parent link to another
  176. */
  177. LETableReference &reparent(const LETableReference &base) {
  178. fParent = &base;
  179. return *this;
  180. }
  181. /**
  182. * remove parent link. Factory functions should do this.
  183. */
  184. void orphan(void) {
  185. fParent=NULL;
  186. }
  187. protected:
  188. const LEFontInstance* fFont;
  189. LETag fTag;
  190. const LETableReference *fParent;
  191. const le_uint8 *fStart; // keep as 8 bit internally, for pointer math
  192. size_t fLength;
  193. void loadTable(LEErrorCode &success) {
  194. if(LE_SUCCESS(success)) {
  195. fStart = (const le_uint8*)(fFont->getFontTable(fTag, fLength)); // note - a null table is not an error.
  196. }
  197. }
  198. void setRaw(const void *data, size_t length = LE_UINTPTR_MAX) {
  199. fFont = NULL;
  200. fTag = kQuestionmarkTableTag;
  201. fParent = NULL;
  202. fStart = (const le_uint8*)data;
  203. fLength = length;
  204. }
  205. };
  206. template<class T>
  207. class LETableVarSizer {
  208. public:
  209. inline static size_t getSize();
  210. };
  211. // base definition- could override for adjustments
  212. template<class T> inline
  213. size_t LETableVarSizer<T>::getSize() {
  214. return sizeof(T);
  215. }
  216. /**
  217. * \def LE_VAR_ARRAY
  218. * @param x Type (T)
  219. * @param y some member that is of length ANY_NUMBER
  220. * Call this after defining a class, for example:
  221. * LE_VAR_ARRAY(FeatureListTable,featureRecordArray)
  222. * this is roughly equivalent to:
  223. * template<> inline size_t LETableVarSizer<FeatureListTable>::getSize() { return sizeof(FeatureListTable) - (sizeof(le_uint16)*ANY_NUMBER); }
  224. * it's a specialization that informs the LETableReference subclasses to NOT include the variable array in the size.
  225. * dereferencing NULL is valid here because we never actually dereference it, just inside sizeof.
  226. */
  227. #define LE_VAR_ARRAY(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return sizeof(x) - (sizeof(((const x*)0)->y)); }
  228. /**
  229. * \def LE_CORRECT_SIZE
  230. * @param x type (T)
  231. * @param y fixed size for T
  232. */
  233. #define LE_CORRECT_SIZE(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return y; }
  234. /**
  235. * Open a new entry based on an existing table
  236. */
  237. /**
  238. * \def LE_UNBOUNDED_ARRAY
  239. * define an array with no *known* bound. Will trim to available size.
  240. * @internal
  241. */
  242. #define LE_UNBOUNDED_ARRAY LE_UINT32_MAX
  243. template<class T>
  244. class LEReferenceToArrayOf : public LETableReference {
  245. public:
  246. LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, size_t offset, le_uint32 count)
  247. : LETableReference(parent, offset, LE_UINTPTR_MAX, success), fCount(count) {
  248. LE_TRACE_TR("INFO: new RTAO by offset")
  249. if(LE_SUCCESS(success)) {
  250. if(count == LE_UNBOUNDED_ARRAY) { // not a known length
  251. count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
  252. }
  253. LETableReference::verifyLength(0, LETableVarSizer<T>::getSize(), fCount, success);
  254. }
  255. if(LE_FAILURE(success)) {
  256. fCount=0;
  257. clear();
  258. }
  259. }
  260. LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, le_uint32 count)
  261. : LETableReference(parent, parent.ptrToOffset(array, success), LE_UINTPTR_MAX, success), fCount(count) {
  262. LE_TRACE_TR("INFO: new RTAO")
  263. if(LE_SUCCESS(success)) {
  264. if(count == LE_UNBOUNDED_ARRAY) { // not a known length
  265. count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
  266. }
  267. LETableReference::verifyLength(0, LETableVarSizer<T>::getSize(), fCount, success);
  268. }
  269. if(LE_FAILURE(success)) clear();
  270. }
  271. LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, size_t offset, le_uint32 count)
  272. : LETableReference(parent, parent.ptrToOffset(array, success)+offset, LE_UINTPTR_MAX, success), fCount(count) {
  273. LE_TRACE_TR("INFO: new RTAO")
  274. if(LE_SUCCESS(success)) {
  275. if(count == LE_UNBOUNDED_ARRAY) { // not a known length
  276. count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
  277. }
  278. LETableReference::verifyLength(0, LETableVarSizer<T>::getSize(), fCount, success);
  279. }
  280. if(LE_FAILURE(success)) clear();
  281. }
  282. LEReferenceToArrayOf() :LETableReference(), fCount(0) {}
  283. le_uint32 getCount() const { return fCount; }
  284. using LETableReference::getAlias;
  285. const T *getAlias(le_uint32 i, LEErrorCode &success) const {
  286. return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success)));
  287. }
  288. const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; }
  289. const T& getObject(le_uint32 i, LEErrorCode &success) const {
  290. const T *ret = getAlias(i, success);
  291. if (LE_FAILURE(success) || ret==NULL) {
  292. return *(new T(0));
  293. } else {
  294. return *ret;
  295. }
  296. }
  297. const T& operator()(le_uint32 i, LEErrorCode &success) const {
  298. return *getAlias(i,success);
  299. }
  300. size_t getOffsetFor(le_uint32 i, LEErrorCode &success) const {
  301. if(LE_SUCCESS(success)&&i<getCount()) {
  302. return LETableVarSizer<T>::getSize()*i;
  303. } else {
  304. success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
  305. }
  306. return 0;
  307. }
  308. LEReferenceToArrayOf<T> &reparent(const LETableReference &base) {
  309. fParent = &base;
  310. return *this;
  311. }
  312. LEReferenceToArrayOf(const LETableReference& parent, LEErrorCode & success) : LETableReference(parent,0, LE_UINTPTR_MAX, success), fCount(0) {
  313. LE_TRACE_TR("INFO: null RTAO")
  314. }
  315. private:
  316. le_uint32 fCount;
  317. };
  318. template<class T>
  319. class LEReferenceTo : public LETableReference {
  320. public:
  321. /**
  322. * open a sub reference.
  323. * @param parent parent reference
  324. * @param success error status
  325. * @param atPtr location of reference - if NULL, will be at offset zero (i.e. downcast of parent). Otherwise must be a pointer within parent's bounds.
  326. */
  327. inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr)
  328. : LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) {
  329. verifyLength(0, LETableVarSizer<T>::getSize(), success);
  330. if(LE_FAILURE(success)) clear();
  331. }
  332. /**
  333. * ptr plus offset
  334. */
  335. inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr, size_t offset)
  336. : LETableReference(parent, parent.ptrToOffset(atPtr, success)+offset, LE_UINTPTR_MAX, success) {
  337. verifyLength(0, LETableVarSizer<T>::getSize(), success);
  338. if(LE_FAILURE(success)) clear();
  339. }
  340. inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, size_t offset)
  341. : LETableReference(parent, offset, LE_UINTPTR_MAX, success) {
  342. verifyLength(0, LETableVarSizer<T>::getSize(), success);
  343. if(LE_FAILURE(success)) clear();
  344. }
  345. inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success)
  346. : LETableReference(parent, 0, LE_UINTPTR_MAX, success) {
  347. verifyLength(0, LETableVarSizer<T>::getSize(), success);
  348. if(LE_FAILURE(success)) clear();
  349. }
  350. inline LEReferenceTo(const LEFontInstance *font, LETag tableTag, LEErrorCode &success)
  351. : LETableReference(font, tableTag, success) {
  352. verifyLength(0, LETableVarSizer<T>::getSize(), success);
  353. if(LE_FAILURE(success)) clear();
  354. }
  355. inline LEReferenceTo(const le_uint8 *data, size_t length = LE_UINTPTR_MAX) : LETableReference(data, length) {}
  356. inline LEReferenceTo(const T *data, size_t length = LE_UINTPTR_MAX) : LETableReference((const le_uint8*)data, length) {}
  357. inline LEReferenceTo() : LETableReference(NULL) {}
  358. inline LEReferenceTo<T>& operator=(const T* other) {
  359. setRaw(other);
  360. return *this;
  361. }
  362. LEReferenceTo<T> &reparent(const LETableReference &base) {
  363. fParent = &base;
  364. return *this;
  365. }
  366. /**
  367. * roll forward by one <T> size.
  368. * same as addOffset(LETableVarSizer<T>::getSize(),success)
  369. */
  370. void addObject(LEErrorCode &success) {
  371. addOffset(LETableVarSizer<T>::getSize(), success);
  372. }
  373. void addObject(size_t count, LEErrorCode &success) {
  374. addOffset(LETableVarSizer<T>::getSize()*count, success);
  375. }
  376. const T *operator->() const { return getAlias(); }
  377. const T *getAlias() const { return (const T*)fStart; }
  378. const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; }
  379. };
  380. U_NAMESPACE_END
  381. #endif
  382. #endif