hb-open-type-private.hh revision 2cb08458f674301cde9d962c13911035a251f7c5
164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/* 2f9b37727985191c9b4aedb0e9835736027e59260Behdad Esfahbod * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc. 364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * This is part of HarfBuzz, an OpenType Layout engine 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 35706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod#define NO_INDEX ((unsigned int) 0xFFFF) 365a0b791184cf6ef39eae0570e14aca21abc32845Behdad Esfahbod 37706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod 38196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod/* 39196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts 40196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */ 41196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 42e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate <typename Type> inline const char * ConstCharP (const Type X) { return reinterpret_cast<const char *>(X); } 43e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate <typename Type> inline char * CharP (Type X) { return reinterpret_cast<char *>(X); } 44e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate <typename Type> inline char * DeConstCharP (const Type X) { return (char *) reinterpret_cast<const char *>(X); } 452b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod 46198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod#define CONST_CAST(T,X,Ofs) (*(reinterpret_cast<const T *>(ConstCharP(&(X)) + Ofs))) 47198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod#define DECONST_CAST(T,X,Ofs) (*(reinterpret_cast<T *>((char *)ConstCharP(&(X)) + Ofs))) 48198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod#define CAST(T,X,Ofs) (*(reinterpret_cast<T *>(CharP(&(X)) + Ofs))) 49196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 5070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 512e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod/* StructAfter<T>(X) returns the struct T& that is placed after X. 522e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod * Works with X of variable size also. */ 53e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 54e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline const Type& StructAfter(const TObject &X) 55e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod{ 56e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod return * reinterpret_cast<const Type*> (ConstCharP (&X) + X.get_size()); 57e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod} 58e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 59e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline Type& StructAfter(TObject &X) 60e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod{ 61e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod return * reinterpret_cast<Type*> (CharP (&X) + X.get_size()); 62e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod} 63e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod 64d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 6570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/* 66600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod * Class features 67600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */ 68600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 698b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 708b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Null objects */ 718b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 728b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool. Enlarge as necessary. */ 739d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic const void *_NullPool[32 / sizeof (void *)]; 748b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 758b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Generic template for nul-content sizeof-sized Null objects. */ 768b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type> 779d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic inline const Type& Null () { 789d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); 799d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod return CONST_CAST (Type, *_NullPool, 0); 809d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod} 818b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 828b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ 838b8358033184198ff638ee1379093717596e162dBehdad Esfahbod#define DEFINE_NULL_DATA(Type, size, data) \ 849d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic const char _Null##Type[size + 1] = data; \ 858b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \ 869d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodinline const Type& Null<Type> () { \ 879d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod return CONST_CAST (Type, *_Null##Type, 0); \ 888b8358033184198ff638ee1379093717596e162dBehdad Esfahbod} 898b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 908b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */ 919d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>() 928b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 938b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 94600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod/* get_for_data() is a static class method returning a reference to an 95600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod * instance of Type located at the input data location. It's just a 9654e5aac5e2947d4e2864c6f2987e4d275da73100Behdad Esfahbod * fancy, NULL-safe, cast! */ 97fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#define STATIC_DEFINE_GET_FOR_DATA(Type) \ 9860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod static inline const Type& get_for_data (const char *data) \ 9960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { \ 1008b8358033184198ff638ee1379093717596e162dBehdad Esfahbod if (HB_UNLIKELY (data == NULL)) return Null(Type); \ 1018b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod return CONST_CAST (Type, *data, 0); \ 102212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod } 103212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod/* Like get_for_data(), but checks major version first. */ 104cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod#define STATIC_DEFINE_GET_FOR_DATA_CHECK_MAJOR_VERSION(Type, MajorMin, MajorMax) \ 105212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod static inline const Type& get_for_data (const char *data) \ 106212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod { \ 107212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod if (HB_UNLIKELY (data == NULL)) return Null(Type); \ 1088b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod const Type& t = CONST_CAST (Type, *data, 0); \ 109cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod if (HB_UNLIKELY (t.version.major < MajorMin || t.version.major > MajorMax)) return Null(Type); \ 110212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod return t; \ 111212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod } 112600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 113600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 114577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/* 115577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize 116577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */ 117577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 11895e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE 11995e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#define HB_DEBUG_SANITIZE HB_DEBUG 12095e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 12195e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 12295e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 123d0351314cd29fbdf0efb5c7f89a569648f7a7fc7Behdad Esfahbod#include <stdio.h> 1240e206de98621ed8a55824b42e9e6bf320f4c6cc8Behdad Esfahbod#define TRACE_SANITIZE_ARG_DEF , unsigned int sanitize_depth HB_GNUC_UNUSED 1253e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG , sanitize_depth + 1 1263e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG_INIT , 1 1273e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE() \ 128b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod HB_STMT_START { \ 12995e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod if (sanitize_depth < HB_DEBUG_SANITIZE) \ 1307acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> %s\n", \ 131198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod (ConstCharP (this) == ConstCharP (&NullPool)) ? 0 : this, \ 1329b76a290a94f2603f3cb9498ae976125347cf54bBehdad Esfahbod sanitize_depth, sanitize_depth, \ 1337acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod __PRETTY_FUNCTION__); \ 134b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod } HB_STMT_END 135b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#else 1363e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG_DEF 1373e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG 1383e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG_INIT 1393e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE() HB_STMT_START {} HB_STMT_END 140b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#endif 141b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod 14241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod#define SANITIZE_ARG_DEF \ 1433e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod hb_sanitize_context_t *context TRACE_SANITIZE_ARG_DEF 14441895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod#define SANITIZE_ARG \ 1453e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod context TRACE_SANITIZE_ARG 14641895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod#define SANITIZE_ARG_INIT \ 1473e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod &context TRACE_SANITIZE_ARG_INIT 14841895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod 149577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodtypedef struct _hb_sanitize_context_t hb_sanitize_context_t; 150577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstruct _hb_sanitize_context_t 151577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 152577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod const char *start, *end; 153577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod int edit_count; 154577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod hb_blob_t *blob; 155577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}; 156577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 157577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstatic HB_GNUC_UNUSED void 1584e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod_hb_sanitize_init (hb_sanitize_context_t *context, 1594e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_blob_t *blob) 160577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 161577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod context->blob = blob; 162577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod context->start = hb_blob_lock (blob); 163577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod context->end = context->start + hb_blob_get_length (blob); 164577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod context->edit_count = 0; 1654f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 16695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 1677acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod fprintf (stderr, "sanitize %p init [%p..%p] (%u bytes)\n", 1687f96b39a9d5a81ba77e0c3dea8fe2cdb9957c4c7Behdad Esfahbod context->blob, context->start, context->end, context->end - context->start); 1694f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif 170577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod} 171577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 172577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstatic HB_GNUC_UNUSED void 1734e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod_hb_sanitize_fini (hb_sanitize_context_t *context, 1744e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod bool unlock) 175577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 17695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 1777acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod fprintf (stderr, "sanitize %p fini [%p..%p] %u edit requests\n", 1787acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod context->blob, context->start, context->end, context->edit_count); 1794f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif 1804f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 181577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod if (unlock) 182577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod hb_blob_unlock (context->blob); 183577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod} 184577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 1854f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbodstatic HB_GNUC_UNUSED inline bool 18641895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod_hb_sanitize_check (SANITIZE_ARG_DEF, 18741895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod const char *base, 18841895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod unsigned int len) 18941895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod{ 190ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod bool ret = context->start <= base && 191ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod base <= context->end && 192ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod (unsigned int) (context->end - base) >= len; 193ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod 19495e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 19595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod if (sanitize_depth < HB_DEBUG_SANITIZE) \ 196ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> check [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \ 197ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod base, 198ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod sanitize_depth, sanitize_depth, 199ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod base, base+len, len, 200ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod context->start, context->end, 201ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod ret ? "pass" : "FAIL"); 202ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod#endif 203ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod return ret; 20441895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod} 20541895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod 20641895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbodstatic HB_GNUC_UNUSED inline bool 207815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod_hb_sanitize_array (SANITIZE_ARG_DEF, 208815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod const char *base, 209815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod unsigned int record_size, 210815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod unsigned int len) 211815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod{ 212815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod bool overflows = len >= ((unsigned int) -1) / record_size; 213815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 21495e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 21595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod if (sanitize_depth < HB_DEBUG_SANITIZE) \ 216815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s\n", \ 217815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod base, 218815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod sanitize_depth, sanitize_depth, 219815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod base, base + (record_size * len), record_size, len, (unsigned long) record_size * len, 220815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod context->start, context->end, 221815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod !overflows ? "does not overflow" : "OVERFLOWS FAIL"); 222815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod#endif 223815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod return HB_LIKELY (!overflows) && _hb_sanitize_check (SANITIZE_ARG, base, record_size * len); 224815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod} 225815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 226815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbodstatic HB_GNUC_UNUSED inline bool 22741895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod_hb_sanitize_edit (SANITIZE_ARG_DEF, 2284f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod const char *base HB_GNUC_UNUSED, 2294f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod unsigned int len HB_GNUC_UNUSED) 230577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 231977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod bool perm = hb_blob_try_writable_inplace (context->blob); 232f4b58d3fc2956a9d1b6178588d809c781f7a5c0cBehdad Esfahbod context->edit_count++; 2334f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 23495e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 235ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \ 236ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod base, 237ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod sanitize_depth, sanitize_depth, 238ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod context->edit_count, 239ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod base, base+len, len, 240ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod context->start, context->end, 241ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod perm ? "granted" : "REJECTED"); 2424f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif 2434f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod return perm; 244577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod} 245577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 246577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG)) 247577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE2(X,Y) (SANITIZE (X) && SANITIZE (Y)) 248577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 249198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod#define SANITIZE_THIS(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG, ConstCharP(this))) 250577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_THIS2(X,Y) (SANITIZE_THIS (X) && SANITIZE_THIS (Y)) 251577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_THIS3(X,Y,Z) (SANITIZE_THIS (X) && SANITIZE_THIS (Y) && SANITIZE_THIS(Z)) 252577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 253577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_BASE(X,B) HB_LIKELY ((X).sanitize (SANITIZE_ARG, B)) 254577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_BASE2(X,Y,B) (SANITIZE_BASE (X,B) && SANITIZE_BASE (Y,B)) 255577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 256577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_SELF() SANITIZE_OBJ (*this) 257577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_OBJ(X) SANITIZE_MEM(&(X), sizeof (X)) 258577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_GET_SIZE() SANITIZE_SELF() && SANITIZE_MEM (this, this->get_size ()) 259577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 260198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod#define SANITIZE_MEM(B,L) HB_LIKELY (_hb_sanitize_check (SANITIZE_ARG, ConstCharP(B), (L))) 261577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 262198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod#define SANITIZE_ARRAY(A,S,L) HB_LIKELY (_hb_sanitize_array (SANITIZE_ARG, ConstCharP(A), S, L)) 263815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 264d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod#define NEUTER(Var, Val) \ 265d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod (SANITIZE_OBJ (Var) && \ 266198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod _hb_sanitize_edit (SANITIZE_ARG, ConstCharP(&(Var)), sizeof (Var)) && \ 267807b8aa486753474e05e09f4fcca8ac94021b97cBehdad Esfahbod ((Var).set (Val), true)) 268577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 269577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2704e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */ 2714e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type> 2724e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer 2734e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{ 2744e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod static hb_blob_t *sanitize (hb_blob_t *blob) { 2754e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_sanitize_context_t context; 2764e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod bool sane; 2774e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 278d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod /* TODO is_sane() stuff */ 2794e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 2804e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod retry: 28195e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 2827acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod fprintf (stderr, "Sanitizer %p start %s\n", blob, __PRETTY_FUNCTION__); 2834f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif 2844f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 2854e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod _hb_sanitize_init (&context, blob); 2864e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 287198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod Type *t = &CAST (Type, *DeConstCharP(context.start), 0); 2884e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 289b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod sane = t->sanitize (SANITIZE_ARG_INIT); 2904e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) { 2914e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (context.edit_count) { 29295e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 2930d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod fprintf (stderr, "Sanitizer %p passed first round with %d edits; going a second round %s\n", 2940d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod blob, context.edit_count, __PRETTY_FUNCTION__); 2950d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod#endif 2968b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod /* sanitize again to ensure no toe-stepping */ 2974e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod context.edit_count = 0; 298b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod sane = t->sanitize (SANITIZE_ARG_INIT); 2994e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (context.edit_count) { 30095e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 301ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod fprintf (stderr, "Sanitizer %p requested %d edits in second round; FAILLING %s\n", 3020d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod blob, context.edit_count, __PRETTY_FUNCTION__); 3030d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod#endif 3044e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod sane = false; 3054e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3064e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3074e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod _hb_sanitize_fini (&context, true); 3084e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } else { 3094f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod unsigned int edit_count = context.edit_count; 3104e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod _hb_sanitize_fini (&context, true); 311977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod if (edit_count && !hb_blob_is_writable (blob) && hb_blob_try_writable (blob)) { 312977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod /* ok, we made it writable by relocating. try again */ 31395e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 3147acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod fprintf (stderr, "Sanitizer %p retry %s\n", blob, __PRETTY_FUNCTION__); 3154f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif 3164e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod goto retry; 3174e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3184e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3194e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 32095e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE 321ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod fprintf (stderr, "Sanitizer %p %s %s\n", blob, sane ? "passed" : "FAILED", __PRETTY_FUNCTION__); 3224f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif 3234e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) 3244e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return blob; 3254e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod else { 3264e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_blob_destroy (blob); 3274e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return hb_blob_create_empty (); 3284e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3294e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3304e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 331d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod static const Type& lock_instance (hb_blob_t *blob) { 3324e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return Type::get_for_data (hb_blob_lock (blob)); 3334e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3344e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod}; 3354e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 3362d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod 337b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* 338b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * 339bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types 340b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */ 341b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 342b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 343b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file. 344b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 345b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 3465f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 3475f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types 3485f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 3495f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 3506b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 351e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type, int Bytes> class BEInt; 352e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 353e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 354e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 2> 355e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 356e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 357e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline void put (Type i) { hb_be_uint16_put (v,i); } 358e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline Type get () const { return hb_be_uint16_get (v); } 359e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline bool cmp (const BEInt<Type, 2> o) const { return hb_be_uint16_cmp (v, o.v); } 360e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[2]; 361e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 362e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 363e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 4> 364e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 365e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 366e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline void put (Type i) { hb_be_uint32_put (v,i); } 367e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline Type get () const { return hb_be_uint32_get (v); } 368e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline bool cmp (const BEInt<Type, 4> o) const { return hb_be_uint32_cmp (v, o.v); } 369e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[4]; 370e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 371e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 372e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 373e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType 374e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 375e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod static inline unsigned int get_size () { return sizeof (Type); } 376e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline void set (Type i) { v.put (i); } 377e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline operator Type(void) const { return v.get (); } 378e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline bool operator == (const IntType<Type> &o) const { return v.cmp (o.v); } 379e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF) { 380e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod TRACE_SANITIZE (); 381e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod return SANITIZE_SELF (); 382e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod } 383e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: BEInt<Type, sizeof (Type)> v; 384e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 385e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 386e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint16_t> USHORT; /* 16-bit unsigned integer. */ 387e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int16_t> SHORT; /* 16-bit signed integer. */ 388e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint32_t> ULONG; /* 32-bit unsigned integer. */ 389e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int32_t> LONG; /* 32-bit signed integer. */ 390e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 391e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (USHORT, 2); 392e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (SHORT, 2); 393e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (ULONG, 4); 394e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (LONG, 4); 395bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 3966b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language 3976b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */ 39820cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG 39960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 400befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 401198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod inline operator const char* (void) const { return ConstCharP(this); } 402198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod inline operator char* (void) { return CharP(this); } 403738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod 404738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF) { 4053e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 406738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod /* Note: Only accept ASCII-visible tags (mind DEL) 4079b39755d104603d1163738f77637cc1923d4055bBehdad Esfahbod * This is one of the few places (only place?) that we check 4089b39755d104603d1163738f77637cc1923d4055bBehdad Esfahbod * for data integrity, as opposed to just boundary checks. 409738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod */ 410738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod return SANITIZE_SELF () && (((uint32_t) *this) & 0x80808080) == 0; 411738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod } 4126b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 413303fe62824d4e99df554b6bfaacba05d068522fbBehdad EsfahbodASSERT_SIZE (Tag, 4); 4149d3677899f90abdc7fb3e3d854db654a8707a84bBehdad EsfahbodDEFINE_NULL_DATA (Tag, 4, " "); 4156b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4166b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */ 4176ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID; 4186b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4191f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ 4206ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset; 4216ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 4226ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ 4236ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset; 4246ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 4256b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4266b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */ 42760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG 42860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 42960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) 43060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 4316b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod uint32_t Sum = 0L; 4324b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::get_size (); 4336b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4346b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod while (Table < EndPtr) 4356b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod Sum += *Table++; 4366b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod return Sum; 4376b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod } 4386b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 4398b8358033184198ff638ee1379093717596e162dBehdad EsfahbodASSERT_SIZE (CheckSum, 4); 4406b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4416b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4426b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* 4436b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers 4446b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */ 4456b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 44687fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion 44760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 44809c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod inline operator uint32_t (void) const { return (major << 16) + minor; } 44996908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod 450cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF) { 4513e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 452cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod return SANITIZE_SELF (); 453cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod } 454cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod 4556ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod USHORT major; 45687fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod USHORT minor; 4576b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 45887fcdcbe3644da10154688765db2d62eb9ac079aBehdad EsfahbodASSERT_SIZE (FixedVersion, 4); 4596b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 46092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 46192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 4625f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 46392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing. 46492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Use: (this+memberName) 4655f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 4665f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 46792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type> 46892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType 46992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{ 47000e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod inline const Type& operator () (const void *base) const 47192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod { 47292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 47392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod if (HB_UNLIKELY (!offset)) return Null(Type); 474198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod return CONST_CAST(Type, *ConstCharP(base), offset); 47592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 47692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 47720b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF, const void *base) { 4783e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 47995528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod if (!SANITIZE_SELF ()) return false; 48092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 48192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod if (HB_UNLIKELY (!offset)) return true; 482198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod return SANITIZE (CAST(Type, *DeConstCharP(base), offset)) || NEUTER (DECONST_CAST(OffsetType,*this,0), 0); 48392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 48420b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF, const void *base, const void *base2) { 4853e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 48695528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod if (!SANITIZE_SELF ()) return false; 487b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod unsigned int offset = *this; 488b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod if (HB_UNLIKELY (!offset)) return true; 489198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod return SANITIZE_BASE (CAST(Type, *DeConstCharP(base), offset), base2) || NEUTER (DECONST_CAST(OffsetType,*this,0), 0); 490b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod } 49120b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF, const void *base, unsigned int user_data) { 4923e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 49395528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod if (!SANITIZE_SELF ()) return false; 49442b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int offset = *this; 49542b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod if (HB_UNLIKELY (!offset)) return true; 496198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod return SANITIZE_BASE (CAST(Type, *DeConstCharP(base), offset), user_data) || NEUTER (DECONST_CAST(OffsetType,*this,0), 0); 49742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 49892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod}; 49992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 50092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodinline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); } 50192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 5025f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type> 50392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {}; 50492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 50592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 50692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {}; 507bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 508bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 50992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* 51092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types 51192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */ 51292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 51392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type> 51492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf 51560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 5162cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod const Type *array(void) const { return &StructAfter<Type> (len); } 5172e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod Type *array(void) { return &StructAfter<Type> (len); } 518d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 51948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod const Type *const_sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 52048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod { 52148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod unsigned int count = len; 52248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod if (HB_UNLIKELY (start_offset > count)) 52348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = 0; 52448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod else 52548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count -= start_offset; 52648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = MIN (count, *pcount); 52748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod *pcount = count; 5282cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod return array() + start_offset; 52948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod } 53048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod 53160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 53260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 5335f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod if (HB_UNLIKELY (i >= len)) return Null(Type); 5342cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod return array()[i]; 5355f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod } 53660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline unsigned int get_size () const 5374b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod { return len.get_size () + len * Type::get_size (); } 538e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 53920b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF) { 5403e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 541dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod if (!SANITIZE_GET_SIZE()) return false; 54240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 54340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 54440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * a bound check on the aggregate array size, hence the return. 54540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 5463564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod return true; 54740d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* We do keep this code though to make sure the structs pointed 54840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * to do have a simple sanitize(), ie. they do not reference 54940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * other structs. */ 55070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod unsigned int count = len; 55170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 552d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod if (!SANITIZE (array()[i])) 55370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod return false; 5549bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 55570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 55620b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF, const void *base) { 5573e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 558dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod if (!SANITIZE_GET_SIZE()) return false; 559e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod unsigned int count = len; 560e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 561d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod if (!array()[i].sanitize (SANITIZE_ARG, base)) 562e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod return false; 5639bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 564e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod } 56520b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF, const void *base, const void *base2) { 5663e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 567b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod if (!SANITIZE_GET_SIZE()) return false; 568b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod unsigned int count = len; 569b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 570d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod if (!array()[i].sanitize (SANITIZE_ARG, base, base2)) 571b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod return false; 5729bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 573b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod } 57420b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF, const void *base, unsigned int user_data) { 5753e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 57642b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod if (!SANITIZE_GET_SIZE()) return false; 57742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int count = len; 57842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 579d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod if (!array()[i].sanitize (SANITIZE_ARG, base, user_data)) 58042b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod return false; 5819bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 58242b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 58370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 58492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod LenType len; 585d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod/*Type array[VAR];*/ 586e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod}; 587e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 58892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */ 58992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 59092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {}; 59192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 59292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */ 59392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 59492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {}; 59592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 59692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */ 59792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 59892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 59992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 60092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */ 60192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 60292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {}; 60392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 60492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */ 60592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 60692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {}; 60792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 60880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */ 60980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type> 61080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type> 61180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{ 61280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 61380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod { 61480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod if (HB_UNLIKELY (i >= this->len)) return Null(Type); 6152cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod return this+this->array()[i]; 61680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 61780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 61880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF) { 6193e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 620198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod return OffsetArrayOf<Type>::sanitize (SANITIZE_ARG, ConstCharP(this)); 62180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 62280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF, unsigned int user_data) { 6233e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 624198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod return OffsetArrayOf<Type>::sanitize (SANITIZE_ARG, ConstCharP(this), user_data); 62580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 62680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod}; 62780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 62880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 629e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements, 630e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */ 631e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type> 63260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf 63360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 6342cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod const Type *array(void) const { return &StructAfter<Type> (len); } 6352e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod Type *array(void) { return &StructAfter<Type> (len); } 636d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 63760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 63860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 639e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod if (HB_UNLIKELY (i >= len || !i)) return Null(Type); 6402cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod return array()[i-1]; 641e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod } 64260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline unsigned int get_size () const 6434b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod { return len.get_size () + (len ? len - 1 : 0) * Type::get_size (); } 6445f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 64520b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod inline bool sanitize (SANITIZE_ARG_DEF) { 6463e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 647dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod if (!SANITIZE_GET_SIZE()) return false; 64840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 64940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 65040d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * a bound check on the aggregate array size, hence the return. 65140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 6523564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod return true; 65340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* We do keep this code though to make sure the structs pointed 65440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * to do have a simple sanitize(), ie. they do not reference 65540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * other structs. */ 65615164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod unsigned int count = len ? len - 1 : 0; 657d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod Type *a = array(); 65870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 659d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod if (!SANITIZE (a[i])) 66070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod return false; 6619bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 66270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 66370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 6645f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod USHORT len; 665d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod/*Type array[VAR];*/ 6665f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod}; 6675f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 6686b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6691e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */ 670