hb-open-type-private.hh revision 2226fc93d1427b8830bfb892fe1b25b488ea36dc
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
115600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
116577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/*
117577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize
118577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */
119577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
12095e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE
121807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod#define HB_DEBUG_SANITIZE HB_DEBUG+0
12295e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif
12395e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod
124bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#define TRACE_SANITIZE() \
125bc200457430c083914a64bf4b056153506749610Behdad Esfahbod	HB_STMT_START { \
126bc200457430c083914a64bf4b056153506749610Behdad Esfahbod	  if (HB_DEBUG_SANITIZE) \
1277d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod		  _hb_trace ("SANITIZE", HB_FUNC, this, sanitize_depth, HB_DEBUG_SANITIZE); \
128bc200457430c083914a64bf4b056153506749610Behdad Esfahbod	} HB_STMT_END
129807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod
130b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod
13141895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod#define SANITIZE_ARG_DEF \
132bc200457430c083914a64bf4b056153506749610Behdad Esfahbod	hb_sanitize_context_t *context, \
13333d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod	unsigned int sanitize_depth HB_UNUSED
13441895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod#define SANITIZE_ARG \
135bc200457430c083914a64bf4b056153506749610Behdad Esfahbod	context, \
136bc200457430c083914a64bf4b056153506749610Behdad Esfahbod	(HB_DEBUG_SANITIZE ? sanitize_depth + 1 : 0)
137173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod
1381376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_sanitize_context_t
139577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
140577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  const char *start, *end;
141254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod  hb_bool_t writable;
142254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod  unsigned int edit_count;
143577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod};
144577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
1451376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod
146fa3b3d58443a7c22eca3f86243993ba2d4bd9f4aBehdad Esfahbodstatic inline void
1474e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod_hb_sanitize_init (hb_sanitize_context_t *context,
1484e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod		   hb_blob_t *blob)
149577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
150577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->start = hb_blob_lock (blob);
151577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->end = context->start + hb_blob_get_length (blob);
152254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod  context->writable = hb_blob_is_writable (blob);
153577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->edit_count = 0;
1544f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
155fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod  if (HB_DEBUG_SANITIZE)
156fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod    fprintf (stderr, "sanitize %p init [%p..%p] (%u bytes)\n",
157fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	     blob, context->start, context->end, context->end - context->start);
158577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
159577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
160fa3b3d58443a7c22eca3f86243993ba2d4bd9f4aBehdad Esfahbodstatic inline void
16133d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod_hb_sanitize_fini (hb_sanitize_context_t *context HB_UNUSED,
1628dfdca599c0a3ba5255131002910bca3b381acacBehdad Esfahbod		   hb_blob_t *blob)
163577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
164fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod  if (HB_DEBUG_SANITIZE)
165fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod    fprintf (stderr, "sanitize %p fini [%p..%p] %u edit requests\n",
166fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	     blob, context->start, context->end, context->edit_count);
1674f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
1688dfdca599c0a3ba5255131002910bca3b381acacBehdad Esfahbod  hb_blob_unlock (blob);
169577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
170577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
171eaf29edb8fa49390e5f48b78105dfd173aff445bJeff Muizelaarstatic inline bool
17241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod_hb_sanitize_check (SANITIZE_ARG_DEF,
17341895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod		    const char *base,
17441895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod		    unsigned int len)
17541895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod{
176ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod  bool ret = context->start <= base &&
177ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     base <= context->end &&
178ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     (unsigned int) (context->end - base) >= len;
179ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod
180fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod  if (HB_DEBUG_SANITIZE && (int) sanitize_depth < (int) HB_DEBUG_SANITIZE) \
181ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod    fprintf (stderr, "SANITIZE(%p) %-*d-> check [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \
182ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     base,
183ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     sanitize_depth, sanitize_depth,
184ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     base, base+len, len,
185ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     context->start, context->end,
186ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     ret ? "pass" : "FAIL");
187fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod
188ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod  return ret;
18941895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod}
19041895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod
191eaf29edb8fa49390e5f48b78105dfd173aff445bJeff Muizelaarstatic inline bool
192815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod_hb_sanitize_array (SANITIZE_ARG_DEF,
193815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod		    const char *base,
194815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod		    unsigned int record_size,
195815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod		    unsigned int len)
196815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod{
197815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod  bool overflows = len >= ((unsigned int) -1) / record_size;
198815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod
199fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod
200fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod  if (HB_DEBUG_SANITIZE && (int) sanitize_depth < (int) HB_DEBUG_SANITIZE)
201815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod    fprintf (stderr, "SANITIZE(%p) %-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s\n", \
202815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     base,
203815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     sanitize_depth, sanitize_depth,
204815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     base, base + (record_size * len), record_size, len, (unsigned long) record_size * len,
205815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     context->start, context->end,
206815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     !overflows ? "does not overflow" : "OVERFLOWS FAIL");
207254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod
20864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  return likely (!overflows) && _hb_sanitize_check (SANITIZE_ARG, base, record_size * len);
209815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod}
210815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod
211eaf29edb8fa49390e5f48b78105dfd173aff445bJeff Muizelaarstatic inline bool
21241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod_hb_sanitize_edit (SANITIZE_ARG_DEF,
21333d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		   const char *base HB_UNUSED,
21433d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		   unsigned int len HB_UNUSED)
215577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
216f4b58d3fc2956a9d1b6178588d809c781f7a5c0cBehdad Esfahbod  context->edit_count++;
2174f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
218fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod  if (HB_DEBUG_SANITIZE && (int) sanitize_depth < (int) HB_DEBUG_SANITIZE)
219fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod    fprintf (stderr, "SANITIZE(%p) %-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \
220fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	     base,
221fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	     sanitize_depth, sanitize_depth,
222fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	     context->edit_count,
223fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	     base, base+len, len,
224fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	     context->start, context->end,
225fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	     context->writable ? "granted" : "REJECTED");
226254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod
227254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod  return context->writable;
228577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
229577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
23064d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod#define SANITIZE(X) likely ((X).sanitize (SANITIZE_ARG))
231577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
23264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod#define SANITIZE_THIS(X) likely ((X).sanitize (SANITIZE_ARG, CharP(this)))
2332226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod#define SANITIZE_WITH_BASE(B,X) likely ((X).sanitize (SANITIZE_ARG, (B)))
234577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
23589da1346ec3a8dec8a368df46d61ca75356e22faBehdad Esfahbod#define SANITIZE_SELF() SANITIZE_MEM(this, sizeof (*this))
236577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
23764d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod#define SANITIZE_MEM(B,L) likely (_hb_sanitize_check (SANITIZE_ARG, CharP(B), (L)))
238577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
23964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod#define SANITIZE_ARRAY(A,S,L) likely (_hb_sanitize_array (SANITIZE_ARG, CharP(A), S, L))
240815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod
241577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2424e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */
2434e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type>
2444e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer
2454e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{
2464e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  static hb_blob_t *sanitize (hb_blob_t *blob) {
247173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod    hb_sanitize_context_t context[1];
248173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod    unsigned int sanitize_depth = 0;
2494e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    bool sane;
2504e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
251d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod    /* TODO is_sane() stuff */
2524e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
2534e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  retry:
254fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod    if (HB_DEBUG_SANITIZE)
2557d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod      fprintf (stderr, "Sanitizer %p start %s\n", blob, HB_FUNC);
2564f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
257173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod    _hb_sanitize_init (context, blob);
2584e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
259602e4f8d5512cdf48c696ad64ad62ff97f6dbdccBehdad Esfahbod    Type *t = CastP<Type> (const_cast<char *> (context->start));
2604e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
261173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod    sane = t->sanitize (SANITIZE_ARG);
2624e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane) {
263173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod      if (context->edit_count) {
264fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	if (HB_DEBUG_SANITIZE)
265fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	  fprintf (stderr, "Sanitizer %p passed first round with %d edits; doing a second round %s\n",
2667d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod		   blob, context->edit_count, HB_FUNC);
267fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod
2688b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod        /* sanitize again to ensure no toe-stepping */
269173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod        context->edit_count = 0;
270173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod	sane = t->sanitize (SANITIZE_ARG);
271173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod	if (context->edit_count) {
272fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	  if (HB_DEBUG_SANITIZE)
273fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	    fprintf (stderr, "Sanitizer %p requested %d edits in second round; FAILLING %s\n",
2747d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod		     blob, context->edit_count, HB_FUNC);
2754e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	  sane = false;
2764e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	}
2774e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
278173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod      _hb_sanitize_fini (context, blob);
2794e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    } else {
280173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod      unsigned int edit_count = context->edit_count;
281173fde7087c0db3e99409f1119530477c14072f5Behdad Esfahbod      _hb_sanitize_fini (context, blob);
282977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod      if (edit_count && !hb_blob_is_writable (blob) && hb_blob_try_writable (blob)) {
283977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod        /* ok, we made it writable by relocating.  try again */
284fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	if (HB_DEBUG_SANITIZE)
2857d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod	  fprintf (stderr, "Sanitizer %p retry %s\n", blob, HB_FUNC);
2864e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod        goto retry;
2874e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
2884e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
2894e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
290fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod    if (HB_DEBUG_SANITIZE)
2917d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod      fprintf (stderr, "Sanitizer %p %s %s\n", blob, sane ? "passed" : "FAILED", HB_FUNC);
2924e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane)
2934e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return blob;
2944e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    else {
2954e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      hb_blob_destroy (blob);
2964e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return hb_blob_create_empty ();
2974e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
2984e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  }
2994e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod};
3004e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3012d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
302f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod
303f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod
304b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/*
305b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *
306bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types
307b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */
308b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
309b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
310b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file.
311b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
312b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
3135f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
3145f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types
3155f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
3165f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
3176b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
318e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type, int Bytes> class BEInt;
319e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
320f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod/* LONGTERMTODO: On machines allowing unaligned access, we can make the
321f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod * following tighter by using byteswap instructions on ints directly. */
322e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
323e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 2>
324e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
325e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  public:
32601c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline class BEInt<Type,2>& operator = (Type i) { hb_be_uint16_put (v,i); return *this; }
32701c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type () const { return hb_be_uint16_get (v); }
32801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_cmp (v, o.v); }
32901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
330e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: uint8_t v[2];
331e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
332e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
333e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 4>
334e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
335e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  public:
33601c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline class BEInt<Type,4>& operator = (Type i) { hb_be_uint32_put (v,i); return *this; }
33701c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type () const { return hb_be_uint32_get (v); }
33801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_cmp (v, o.v); }
33901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
340e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: uint8_t v[4];
341e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
342e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
3432467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */
344e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
345e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType
346e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
347e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  static inline unsigned int get_size () { return sizeof (Type); }
34801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline void set (Type i) { v = i; }
34901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type(void) const { return v; }
35001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const IntType<Type> &o) const { return v == o.v; }
35101c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const IntType<Type> &o) const { return v != o.v; }
352e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
353e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod    TRACE_SANITIZE ();
354e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod    return SANITIZE_SELF ();
355e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  }
356e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: BEInt<Type, sizeof (Type)> v;
357e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
358e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
359e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint16_t> USHORT;	/* 16-bit unsigned integer. */
360e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int16_t>  SHORT;	/* 16-bit signed integer. */
361e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint32_t> ULONG;	/* 32-bit unsigned integer. */
362e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int32_t>  LONG;		/* 32-bit signed integer. */
363e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
364e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (USHORT, 2);
365e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (SHORT, 2);
366e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (ULONG, 4);
367e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (LONG, 4);
368bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
3696b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language
3706b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */
37120cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG
37260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
373befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
3740dfcc13a4668cdd2c2ebdd5f4a7540a51222cf2fBehdad Esfahbod  inline operator const char* (void) const { return CharP(this); }
375198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod  inline operator char* (void) { return CharP(this); }
3766b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
377303fe62824d4e99df554b6bfaacba05d068522fbBehdad EsfahbodASSERT_SIZE (Tag, 4);
3789d3677899f90abdc7fb3e3d854db654a8707a84bBehdad EsfahbodDEFINE_NULL_DATA (Tag, 4, "    ");
3796b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
3806b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */
3816ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID;
3826b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
3831f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
3846ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset;
3856ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod
3866ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
3876ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset;
3886ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod
3896b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
3906b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */
39160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG
39260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
39360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length)
39460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
3956b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    uint32_t Sum = 0L;
3964b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod    ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::get_size ();
3976b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
3986b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    while (Table < EndPtr)
3996b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod      Sum += *Table++;
4006b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    return Sum;
4016b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod  }
4026b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
4038b8358033184198ff638ee1379093717596e162dBehdad EsfahbodASSERT_SIZE (CheckSum, 4);
4046b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4056b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4066b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/*
4076b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers
4086b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */
4096b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
41087fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion
41160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
41209c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod  inline operator uint32_t (void) const { return (major << 16) + minor; }
41396908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod
414cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
4153e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
416cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return SANITIZE_SELF ();
417cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
418cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
4196ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod  USHORT major;
42087fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod  USHORT minor;
4216b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
42287fcdcbe3644da10154688765db2d62eb9ac079aBehdad EsfahbodASSERT_SIZE (FixedVersion, 4);
4236b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
42492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
42592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
4265f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
42792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing.
428f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset)
4295f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
4305f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
43192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type>
43292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType
43392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{
43400e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline const Type& operator () (const void *base) const
43592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  {
43692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
43764d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!offset)) return Null(Type);
438a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod    return StructAtOffset<Type> (*CharP(base), offset);
43992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
44092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
44162c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
4423e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
44395528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod    if (!SANITIZE_SELF ()) return false;
44492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
44564d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!offset)) return true;
4462226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod    Type &obj = StructAtOffset<Type> (*CharP(base), offset);
4472226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod    return likely (obj.sanitize (SANITIZE_ARG)) || neuter (SANITIZE_ARG);
44892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
44962c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base, void *base2) {
4503e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
45195528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod    if (!SANITIZE_SELF ()) return false;
452b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    unsigned int offset = *this;
45364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!offset)) return true;
4542226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod    Type &obj = StructAtOffset<Type> (*CharP(base), offset);
4552226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod    return likely (obj.sanitize (SANITIZE_ARG, base2)) || neuter (SANITIZE_ARG);
456b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod  }
45762c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base, unsigned int user_data) {
4583e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
45995528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod    if (!SANITIZE_SELF ()) return false;
46042b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int offset = *this;
46164d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!offset)) return true;
4622226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod    Type &obj = StructAtOffset<Type> (*CharP(base), offset);
4632226fc93d1427b8830bfb892fe1b25b488ea36dcBehdad Esfahbod    return likely (obj.sanitize (SANITIZE_ARG, user_data)) || neuter (SANITIZE_ARG);
464c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  }
465c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod
466c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  private:
467c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  /* Set the offset to Null */
468c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  inline bool neuter (SANITIZE_ARG_DEF) {
469c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod    if (_hb_sanitize_edit (SANITIZE_ARG, CharP(this), this->get_size ())) {
470c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod      this->set (0); /* 0 is Null offset */
471c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod      return true;
472c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod    }
473c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod    return false;
47442b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
47592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod};
47692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type>
47792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodinline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); }
47892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
4795f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type>
48092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {};
48192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
48292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
48392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
484bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
485bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
48692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/*
48792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types
48892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */
48992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
49092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type>
49192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf
49260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
4932cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod  const Type *array(void) const { return &StructAfter<Type> (len); }
4942e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod  Type *array(void) { return &StructAfter<Type> (len); }
495d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod
4964f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
49748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod  {
49848de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    unsigned int count = len;
49964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (start_offset > count))
50048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      count = 0;
50148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    else
50248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      count -= start_offset;
50348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    count = MIN (count, *pcount);
50448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    *pcount = count;
5052cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return array() + start_offset;
50648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod  }
50748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod
50860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
50960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
51064d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= len)) return Null(Type);
5112cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return array()[i];
5125f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  }
51360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_size () const
5144b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod  { return len.get_size () + len * Type::get_size (); }
515e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
51620b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
5173e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
51864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (!likely (sanitize_shallow (SANITIZE_ARG))) return false;
51940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* Note: for structs that do not reference other structs,
52040d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * we do not need to call their sanitize() as we already did
52140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * a bound check on the aggregate array size, hence the return.
52240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     */
5233564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod    return true;
52440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* We do keep this code though to make sure the structs pointed
52540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * to do have a simple sanitize(), ie. they do not reference
52640d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * other structs. */
52770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    unsigned int count = len;
52870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
529d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!SANITIZE (array()[i]))
53070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod        return false;
5319bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
53270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
53362c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
5343e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
53564d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (!likely (sanitize_shallow (SANITIZE_ARG))) return false;
536e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    unsigned int count = len;
537e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
538d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!array()[i].sanitize (SANITIZE_ARG, base))
539e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod        return false;
5409bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
541e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod  }
54262c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base, void *base2) {
5433e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
54464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (!likely (sanitize_shallow (SANITIZE_ARG))) return false;
545b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    unsigned int count = len;
546b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
547d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!array()[i].sanitize (SANITIZE_ARG, base, base2))
548b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod        return false;
5499bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
550b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod  }
55162c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base, unsigned int user_data) {
5523e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
55364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (!likely (sanitize_shallow (SANITIZE_ARG))) return false;
55442b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int count = len;
55542b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
556d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!array()[i].sanitize (SANITIZE_ARG, base, user_data))
55742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod        return false;
5589bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
55942b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
56070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
56130fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  private:
56230fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  inline bool sanitize_shallow (SANITIZE_ARG_DEF) {
56330fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod    TRACE_SANITIZE ();
56430fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod    return SANITIZE_SELF() && SANITIZE_ARRAY (this, Type::get_size (), len);
56530fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  }
56630fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod
56730fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  public:
56892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  LenType len;
569d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod/*Type array[VAR];*/
570e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod};
571e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
57292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */
57392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
57492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {};
57592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
57692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */
57792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
57892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {};
57992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
58092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */
58192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
58292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
58392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
58492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */
58592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
58692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
58792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
58892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */
58992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
59092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
59192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
59280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */
59380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type>
59480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type>
59580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{
59680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
59780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  {
59864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= this->len)) return Null(Type);
5992cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return this+this->array()[i];
60080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
60180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
60280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
6033e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
60462c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod    return OffsetArrayOf<Type>::sanitize (SANITIZE_ARG, CharP(this));
60580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
60680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, unsigned int user_data) {
6073e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
60862c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod    return OffsetArrayOf<Type>::sanitize (SANITIZE_ARG, CharP(this), user_data);
60980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
61080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod};
61180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
61280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
613e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements,
614e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */
615e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type>
61660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf
61760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
6182cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod  const Type *array(void) const { return &StructAfter<Type> (len); }
6192e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod  Type *array(void) { return &StructAfter<Type> (len); }
620d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod
62160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
62260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
62364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= len || !i)) return Null(Type);
6242cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return array()[i-1];
625e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod  }
62660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_size () const
6274b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod  { return len.get_size () + (len ? len - 1 : 0) * Type::get_size (); }
6285f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
629e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod  inline bool sanitize_shallow (SANITIZE_ARG_DEF) {
630e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    TRACE_SANITIZE ();
631e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    return SANITIZE_SELF() && SANITIZE_ARRAY (this, Type::get_size (), len);
632e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod  }
633e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod
63420b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
6353e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
63664d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (!likely (sanitize_shallow (SANITIZE_ARG))) return false;
63740d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* Note: for structs that do not reference other structs,
63840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * we do not need to call their sanitize() as we already did
63940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * a bound check on the aggregate array size, hence the return.
64040d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     */
6413564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod    return true;
64240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* We do keep this code though to make sure the structs pointed
64340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * to do have a simple sanitize(), ie. they do not reference
64440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * other structs. */
64515164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod    unsigned int count = len ? len - 1 : 0;
646d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod    Type *a = array();
64770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
648d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!SANITIZE (a[i]))
64970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod        return false;
6509bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
65170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
65270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
6535f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  USHORT len;
654d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod/*Type array[VAR];*/
6555f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod};
6565f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
6576b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
6581e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */
659