hb-open-type-private.hh revision 27e302dc8e794ff6bf878bc76e17d336d510849e
164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/* 2f9b37727985191c9b4aedb0e9835736027e59260Behdad Esfahbod * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc. 364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 4c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Permission is hereby granted, without written agreement and without 764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * software and its documentation for any purpose, provided that the 964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 1064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * all copies of this software. 1164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DAMAGE. 1764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 1964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 2064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 2164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 2264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 2364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 2464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 2564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod */ 2664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod 275f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#ifndef HB_OPEN_TYPES_PRIVATE_HH 285f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#define HB_OPEN_TYPES_PRIVATE_HH 2912c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod 302098a021a826e76ee27d5db74e32738d7d1c3d30Behdad Esfahbod#include "hb-private.h" 3112c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod 3270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod#include "hb-blob.h" 3370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 34a16ecbf0564a6e2576da22c12827f3c0719da549Behdad Esfahbod 35c85c3620675f38ffdca59134aeec2641485f40caBehdad Esfahbod/* Table/script/language-system/feature/... not found */ 36706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod#define NO_INDEX ((unsigned int) 0xFFFF) 375a0b791184cf6ef39eae0570e14aca21abc32845Behdad Esfahbod 38706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod 39a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 40196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod/* 41196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts 42196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */ 43196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 440dfcc13a4668cdd2c2ebdd5f4a7540a51222cf2fBehdad Esfahbod/* Cast to "const char *" and "char *" */ 45a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate <typename Type> 46a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline const char * CharP (const Type* X) 47a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const char *>(X); } 48a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate <typename Type> 49a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline char * CharP (Type* X) 50a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<char *>(X); } 512b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod 52187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, reference to reference */ 53a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 54187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type& CastR(const TObject &X) 55a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const Type&> (X); } 56a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 57187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type& CastR(TObject &X) 58a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<Type&> (X); } 59196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 60187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, pointer to pointer */ 61187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 62187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type* CastP(const TObject *X) 63187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<const Type*> (X); } 64187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 65187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type* CastP(TObject *X) 66187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<Type*> (X); } 67187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod 68a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod/* StructAtOffset<T>(X,Ofs) returns the struct T& that is placed at memory 69a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod * location of X plus Ofs bytes. */ 70a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 71a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline const Type& StructAtOffset(const TObject &X, unsigned int offset) 72d632ec4000b3079150e6424e88a3ab7509f7445cBehdad Esfahbod{ return * reinterpret_cast<const Type*> (CharP(&X) + offset); } 73a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 74a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline Type& StructAtOffset(TObject &X, unsigned int offset) 75d632ec4000b3079150e6424e88a3ab7509f7445cBehdad Esfahbod{ return * reinterpret_cast<Type*> (CharP(&X) + offset); } 7670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 772e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod/* StructAfter<T>(X) returns the struct T& that is placed after X. 7829c3f5e1b6212c775a7b911becd44ba093b7b0ebBehdad Esfahbod * Works with X of variable size also. X must implement get_size() */ 79e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 80e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline const Type& StructAfter(const TObject &X) 81a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return StructAtOffset<Type>(X, X.get_size()); } 82e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 83e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline Type& StructAfter(TObject &X) 84a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return StructAtOffset<Type>(X, X.get_size()); } 85a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 86e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod 87d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 8870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/* 89f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Null objects 90600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */ 91600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 928b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool. Enlarge as necessary. */ 939d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic const void *_NullPool[32 / sizeof (void *)]; 948b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 958b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Generic template for nul-content sizeof-sized Null objects. */ 968b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type> 979d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic inline const Type& Null () { 989d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); 99187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_NullPool); 1009d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod} 1018b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1028b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ 1038b8358033184198ff638ee1379093717596e162dBehdad Esfahbod#define DEFINE_NULL_DATA(Type, size, data) \ 104565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbodstatic const char _Null##Type[size + 1] = data; /* +1 is for nul-termination in data */ \ 1058b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \ 1069d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodinline const Type& Null<Type> () { \ 107187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_Null##Type); \ 108565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbod} /* The following line really exists such that we end in a place needing semicolon */ \ 109565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad EsfahbodASSERT_STATIC (sizeof (Type) + 1 <= sizeof (_Null##Type)) 1108b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1118b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */ 1129d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>() 1138b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1148b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 11520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod/* 116dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod * Trace 11720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod */ 11820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 119dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod 120dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodtemplate <int max_depth> 121dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodstruct hb_trace_t { 122dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod explicit hb_trace_t (unsigned int *pdepth) : pdepth(pdepth) { if (max_depth) ++*pdepth; } 123dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod ~hb_trace_t (void) { if (max_depth) --*pdepth; } 124dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod 125dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod inline void log (const char *what, const char *function, const void *obj) 126dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod { 127dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod if (*pdepth < max_depth) 128dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, *pdepth, *pdepth, function); 129dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod } 13020e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 13120e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod private: 132dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod unsigned int *pdepth; 13320e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod}; 134dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodtemplate <> /* Optimize when tracing is disabled */ 135dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodstruct hb_trace_t<0> { 136dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod explicit hb_trace_t (unsigned int *p) {} 137dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod inline void log (const char *what, const char *function, const void *obj) {}; 13820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod}; 13920e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 14020e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 141600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 142577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/* 143577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize 144577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */ 145577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 14695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE 147807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod#define HB_DEBUG_SANITIZE HB_DEBUG+0 14895e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 14995e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 15020e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 151bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#define TRACE_SANITIZE() \ 152dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod hb_trace_t<HB_DEBUG_SANITIZE> trace (&context->debug_depth); \ 153dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod trace.log ("SANITIZE", HB_FUNC, this); 154807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod 155b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod 1561376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_sanitize_context_t 157577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 15898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod inline void init (hb_blob_t *blob) 15998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 16098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob = hb_blob_reference (blob); 16198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start = hb_blob_lock (blob); 16298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->end = this->start + hb_blob_get_length (blob); 16398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->writable = hb_blob_is_writable (blob); 16498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count = 0; 16520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth = 0; 166577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 16798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod if (HB_DEBUG_SANITIZE) 16898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "sanitize %p init [%p..%p] (%u bytes)\n", 16998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob, this->start, this->end, this->end - this->start); 17098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 1711376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod 17298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod inline void finish (void) 17398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 17498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod if (HB_DEBUG_SANITIZE) 17598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "sanitize %p fini [%p..%p] %u edit requests\n", 17698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob, this->start, this->end, this->edit_count); 177577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 17898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_unlock (this->blob); 17998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_destroy (this->blob); 18098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob = NULL; 18198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start = this->end = NULL; 18298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 1834f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 18420e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod inline bool check (const char *base, unsigned int len) const 18598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 18698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool ret = this->start <= base && 18798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod base <= this->end && 18898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod (unsigned int) (this->end - base) >= len; 18998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 19020e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE) \ 19198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> check [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \ 19298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod base, 19320e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth, this->debug_depth, 19498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod base, base+len, len, 19598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start, this->end, 19698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod ret ? "pass" : "FAIL"); 19798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 19827e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod return likely (ret); 19998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 200577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 20120e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod inline bool check_array (const char *base, unsigned int record_size, unsigned int len) const 20298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 20398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool overflows = len >= ((unsigned int) -1) / record_size; 20441895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod 205815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 20620e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE) 20798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s\n", \ 20898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod base, 20920e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth, this->debug_depth, 21098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod base, base + (record_size * len), record_size, len, (unsigned long) record_size * len, 21198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start, this->end, 21298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod !overflows ? "does not overflow" : "OVERFLOWS FAIL"); 213fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 21427e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod return likely (!overflows && this->check (base, record_size * len)); 21598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 216254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod 21720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod inline bool can_edit (const char *base HB_UNUSED, unsigned int len HB_UNUSED) 21898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 21998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count++; 22098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 22120e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE) 22298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \ 22398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod base, 22420e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth, this->debug_depth, 22598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count, 22698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod base, base+len, len, 22798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start, this->end, 22898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->writable ? "granted" : "REJECTED"); 22998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 23098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod return this->writable; 23198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 23298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 23398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod const char *start, *end; 23498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool writable; 23598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod unsigned int edit_count; 23698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_t *blob; 23727e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod unsigned int debug_depth; 23898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod}; 239815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 240577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 24139840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod#define SANITIZE(X) likely ((X).sanitize (context)) 242577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 24339840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod#define SANITIZE_WITH_BASE(B,X) likely ((X).sanitize (context, CharP(B))) 244577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 24589da1346ec3a8dec8a368df46d61ca75356e22faBehdad Esfahbod#define SANITIZE_SELF() SANITIZE_MEM(this, sizeof (*this)) 246577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 24720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod#define SANITIZE_MEM(B,L) likely (context->check (CharP(B), (L))) 248577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 24920e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod#define SANITIZE_ARRAY(A,S,L) likely (context->check_array (CharP(A), S, L)) 250815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 251577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2524e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */ 2534e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type> 2544e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer 2554e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{ 2564e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod static hb_blob_t *sanitize (hb_blob_t *blob) { 257173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod hb_sanitize_context_t context[1]; 2584e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod bool sane; 2594e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 260d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod /* TODO is_sane() stuff */ 2614e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 2624e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod retry: 263fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 2647d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod fprintf (stderr, "Sanitizer %p start %s\n", blob, HB_FUNC); 2654f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 26698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod context->init (blob); 2674e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 26827e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod Type *t = CastP<Type> (const_cast<char *> (context->start)); 2694e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 27039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod sane = t->sanitize (context); 2714e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) { 27227e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod if (context->edit_count) { 273fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 274fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod fprintf (stderr, "Sanitizer %p passed first round with %d edits; doing a second round %s\n", 27527e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod blob, context->edit_count, HB_FUNC); 276fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 2778b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod /* sanitize again to ensure no toe-stepping */ 27827e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod context->edit_count = 0; 27939840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod sane = t->sanitize (context); 28027e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod if (context->edit_count) { 281fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 282fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod fprintf (stderr, "Sanitizer %p requested %d edits in second round; FAILLING %s\n", 28327e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod blob, context->edit_count, HB_FUNC); 2844e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod sane = false; 2854e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 2864e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 28798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod context->finish (); 2884e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } else { 28927e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod unsigned int edit_count = context->edit_count; 29098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod context->finish (); 291977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod if (edit_count && !hb_blob_is_writable (blob) && hb_blob_try_writable (blob)) { 292977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod /* ok, we made it writable by relocating. try again */ 293fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 2947d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod fprintf (stderr, "Sanitizer %p retry %s\n", blob, HB_FUNC); 2954e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod goto retry; 2964e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 2974e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 2984e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 299fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 3007d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod fprintf (stderr, "Sanitizer %p %s %s\n", blob, sane ? "passed" : "FAILED", HB_FUNC); 3014e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) 3024e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return blob; 3034e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod else { 3044e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_blob_destroy (blob); 3054e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return hb_blob_create_empty (); 3064e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3074e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3084e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod}; 3094e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 3102d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod 311f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 312f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 313b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* 314b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * 315bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types 316b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */ 317b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 318b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 319b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file. 320b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 321b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 3225f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 3235f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types 3245f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 3255f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 3266b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 327e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type, int Bytes> class BEInt; 328e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 329f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod/* LONGTERMTODO: On machines allowing unaligned access, we can make the 330f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod * following tighter by using byteswap instructions on ints directly. */ 331e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 332e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 2> 333e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 334e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 33501c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline class BEInt<Type,2>& operator = (Type i) { hb_be_uint16_put (v,i); return *this; } 33601c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type () const { return hb_be_uint16_get (v); } 33701c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_cmp (v, o.v); } 33801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); } 339e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[2]; 340e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 341e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 342e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 4> 343e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 344e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 34501c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline class BEInt<Type,4>& operator = (Type i) { hb_be_uint32_put (v,i); return *this; } 34601c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type () const { return hb_be_uint32_get (v); } 34701c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_cmp (v, o.v); } 34801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); } 349e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[4]; 350e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 351e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 3522467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */ 353e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 354e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType 355e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 356e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod static inline unsigned int get_size () { return sizeof (Type); } 35701c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline void set (Type i) { v = i; } 35801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type(void) const { return v; } 35901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator == (const IntType<Type> &o) const { return v == o.v; } 36001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const IntType<Type> &o) const { return v != o.v; } 36139840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context) { 362e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod TRACE_SANITIZE (); 363e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod return SANITIZE_SELF (); 364e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod } 365e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: BEInt<Type, sizeof (Type)> v; 366e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 367e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 368e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint16_t> USHORT; /* 16-bit unsigned integer. */ 369e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int16_t> SHORT; /* 16-bit signed integer. */ 370e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint32_t> ULONG; /* 32-bit unsigned integer. */ 371e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int32_t> LONG; /* 32-bit signed integer. */ 372e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 373e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (USHORT, 2); 374e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (SHORT, 2); 375e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (ULONG, 4); 376e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (LONG, 4); 377bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 3786b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language 3796b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */ 38020cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG 38160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 382befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 3830dfcc13a4668cdd2c2ebdd5f4a7540a51222cf2fBehdad Esfahbod inline operator const char* (void) const { return CharP(this); } 384198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod inline operator char* (void) { return CharP(this); } 3856b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 386303fe62824d4e99df554b6bfaacba05d068522fbBehdad EsfahbodASSERT_SIZE (Tag, 4); 3879d3677899f90abdc7fb3e3d854db654a8707a84bBehdad EsfahbodDEFINE_NULL_DATA (Tag, 4, " "); 3886b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 3896b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */ 3906ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID; 3916b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 3921f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ 3936ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset; 3946ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 3956ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ 3966ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset; 3976ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 3986b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 3996b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */ 40060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG 40160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 40260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) 40360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 4046b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod uint32_t Sum = 0L; 4054b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::get_size (); 4066b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4076b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod while (Table < EndPtr) 4086b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod Sum += *Table++; 4096b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod return Sum; 4106b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod } 4116b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 4128b8358033184198ff638ee1379093717596e162dBehdad EsfahbodASSERT_SIZE (CheckSum, 4); 4136b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4146b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4156b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* 4166b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers 4176b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */ 4186b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 41987fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion 42060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 42109c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod inline operator uint32_t (void) const { return (major << 16) + minor; } 42296908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod 42339840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context) { 4243e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 425cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod return SANITIZE_SELF (); 426cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod } 427cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod 4286ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod USHORT major; 42987fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod USHORT minor; 4306b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 43187fcdcbe3644da10154688765db2d62eb9ac079aBehdad EsfahbodASSERT_SIZE (FixedVersion, 4); 4326b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 43392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 43492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 4355f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 43692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing. 437f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset) 4385f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 4395f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 44092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type> 44192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType 44292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{ 44300e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod inline const Type& operator () (const void *base) const 44492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod { 44592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 44664d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return Null(Type); 447a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod return StructAtOffset<Type> (*CharP(base), offset); 44892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 44992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 45039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context, void *base) { 4513e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 45295528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod if (!SANITIZE_SELF ()) return false; 45392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 45464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return true; 4552226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod Type &obj = StructAtOffset<Type> (*CharP(base), offset); 45639840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod return likely (obj.sanitize (context)) || neuter (context); 45792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 4584a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 45939840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context, void *base, T user_data) { 4603e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 46195528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod if (!SANITIZE_SELF ()) return false; 46242b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int offset = *this; 46364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return true; 4642226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod Type &obj = StructAtOffset<Type> (*CharP(base), offset); 46539840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod return likely (obj.sanitize (context, user_data)) || neuter (context); 466c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 467c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod 468c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod private: 469c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod /* Set the offset to Null */ 47039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool neuter (hb_sanitize_context_t *context) { 47120e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod if (context->can_edit (CharP(this), this->get_size ())) { 472c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod this->set (0); /* 0 is Null offset */ 473c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return true; 474c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 475c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return false; 47642b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 47792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod}; 47892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 47992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodinline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); } 48092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 4815f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type> 48292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {}; 48392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 48492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 48592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {}; 486bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 487bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 48892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* 48992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types 49092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */ 49192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 49292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type> 49392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf 49460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 4952cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod const Type *array(void) const { return &StructAfter<Type> (len); } 4962e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod Type *array(void) { return &StructAfter<Type> (len); } 497d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 4984f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 49948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod { 50048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod unsigned int count = len; 50164d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (start_offset > count)) 50248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = 0; 50348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod else 50448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count -= start_offset; 50548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = MIN (count, *pcount); 50648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod *pcount = count; 5072cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod return array() + start_offset; 50848de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod } 50948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod 51060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 51160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 51264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len)) return Null(Type); 5132cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod return array()[i]; 5145f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod } 51560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline unsigned int get_size () const 5164b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod { return len.get_size () + len * Type::get_size (); } 517e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 51839840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context) { 5193e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 52039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod if (!likely (sanitize_shallow (context))) return false; 52140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 52240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 52340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * a bound check on the aggregate array size, hence the return. 52440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 5253564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod return true; 52640d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* We do keep this code though to make sure the structs pointed 52740d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * to do have a simple sanitize(), ie. they do not reference 52840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * other structs. */ 52970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod unsigned int count = len; 53070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 531d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod if (!SANITIZE (array()[i])) 53270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod return false; 5339bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 53470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 53539840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context, void *base) { 5363e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 53739840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod if (!likely (sanitize_shallow (context))) return false; 538e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod unsigned int count = len; 539e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 54039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod if (!array()[i].sanitize (context, base)) 541e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod return false; 5429bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 543e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod } 5444a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 54539840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context, void *base, T user_data) { 5463e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 54739840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod if (!likely (sanitize_shallow (context))) return false; 54842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int count = len; 54942b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 55039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod if (!array()[i].sanitize (context, base, user_data)) 55142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod return false; 5529bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 55342b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 55470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 55530fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod private: 55639840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *context) { 55730fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod TRACE_SANITIZE (); 55830fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod return SANITIZE_SELF() && SANITIZE_ARRAY (this, Type::get_size (), len); 55930fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod } 56030fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod 56130fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod public: 56292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod LenType len; 563d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod/*Type array[VAR];*/ 564e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod}; 565e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 56692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */ 56792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 56892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {}; 56992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 57092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */ 57192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 57292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {}; 57392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 57492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */ 57592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 57692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 57792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 57892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */ 57992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 58092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {}; 58192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 58292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */ 58392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 58492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {}; 58592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 58680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */ 58780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type> 58880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type> 58980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{ 59080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 59180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod { 59264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= this->len)) return Null(Type); 5932cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod return this+this->array()[i]; 59480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 59580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 59639840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context) { 5973e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 59839840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod return OffsetArrayOf<Type>::sanitize (context, CharP(this)); 59980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 6004a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 60139840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context, T user_data) { 6023e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 60339840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod return OffsetArrayOf<Type>::sanitize (context, CharP(this), user_data); 60480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 60580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod}; 60680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 60780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 608e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements, 609e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */ 610e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type> 61160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf 61260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 6132cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod const Type *array(void) const { return &StructAfter<Type> (len); } 6142e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod Type *array(void) { return &StructAfter<Type> (len); } 615d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 61660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 61760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 61864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len || !i)) return Null(Type); 6192cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod return array()[i-1]; 620e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod } 62160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline unsigned int get_size () const 6224b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod { return len.get_size () + (len ? len - 1 : 0) * Type::get_size (); } 6235f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 62439840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *context) { 625e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod return SANITIZE_SELF() && SANITIZE_ARRAY (this, Type::get_size (), len); 626e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod } 627e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod 62839840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *context) { 6293e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 63039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod if (!likely (sanitize_shallow (context))) return false; 63140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 63240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 63340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * a bound check on the aggregate array size, hence the return. 63440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 6353564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod return true; 63640d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* We do keep this code though to make sure the structs pointed 63740d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * to do have a simple sanitize(), ie. they do not reference 63840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * other structs. */ 63915164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod unsigned int count = len ? len - 1 : 0; 640d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod Type *a = array(); 64170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 642d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod if (!SANITIZE (a[i])) 64370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod return false; 6449bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 64570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 64670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 6475f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod USHORT len; 648d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod/*Type array[VAR];*/ 6495f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod}; 6505f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 6516b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6521e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */ 653