1 // Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef OPENTYPE_SANITISER_H_
6 #define OPENTYPE_SANITISER_H_
7 
8 #if defined(_WIN32) || defined(__CYGWIN__)
9   #define OTS_DLL_IMPORT __declspec(dllimport)
10   #define OTS_DLL_EXPORT __declspec(dllexport)
11 #else
12   #if __GNUC__ >= 4
13     #define OTS_DLL_IMPORT __attribute__((visibility ("default")))
14     #define OTS_DLL_EXPORT __attribute__((visibility ("default")))
15   #endif
16 #endif
17 
18 #ifdef OTS_DLL
19   #ifdef OTS_DLL_EXPORTS
20     #define OTS_API OTS_DLL_EXPORT
21   #else
22     #define OTS_API OTS_DLL_IMPORT
23   #endif
24 #else
25   #define OTS_API
26 #endif
27 
28 #if defined(_WIN32)
29 #include <stdlib.h>
30 typedef signed char int8_t;
31 typedef unsigned char uint8_t;
32 typedef short int16_t;
33 typedef unsigned short uint16_t;
34 typedef int int32_t;
35 typedef unsigned int uint32_t;
36 typedef __int64 int64_t;
37 typedef unsigned __int64 uint64_t;
38 #define ots_ntohl(x) _byteswap_ulong (x)
39 #define ots_ntohs(x) _byteswap_ushort (x)
40 #define ots_htonl(x) _byteswap_ulong (x)
41 #define ots_htons(x) _byteswap_ushort (x)
42 #else
43 #include <arpa/inet.h>
44 #include <stdint.h>
45 #define ots_ntohl(x) ntohl (x)
46 #define ots_ntohs(x) ntohs (x)
47 #define ots_htonl(x) htonl (x)
48 #define ots_htons(x) htons (x)
49 #endif
50 
51 #include <sys/types.h>
52 
53 #include <algorithm>
54 #include <cassert>
55 #include <cstddef>
56 #include <cstring>
57 
58 #define OTS_TAG(c1,c2,c3,c4) ((uint32_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4))))
59 #define OTS_UNTAG(tag)       ((char)((tag)>>24)), ((char)((tag)>>16)), ((char)((tag)>>8)), ((char)(tag))
60 
61 #if defined(__GNUC__) && (__GNUC__ >= 4) || (__clang__)
62 #define OTS_UNUSED __attribute__((unused))
63 #elif defined(_MSC_VER)
64 #define OTS_UNUSED __pragma(warning(suppress: 4100 4101))
65 #else
66 #define OTS_UNUSED
67 #endif
68 
69 namespace ots {
70 
71 // -----------------------------------------------------------------------------
72 // This is an interface for an abstract stream class which is used for writing
73 // the serialised results out.
74 // -----------------------------------------------------------------------------
75 class OTSStream {
76  public:
OTSStream()77   OTSStream() : chksum_(0) {}
78 
~OTSStream()79   virtual ~OTSStream() {}
80 
81   // This should be implemented to perform the actual write.
82   virtual bool WriteRaw(const void *data, size_t length) = 0;
83 
Write(const void * data,size_t length)84   bool Write(const void *data, size_t length) {
85     if (!length) return false;
86 
87     const size_t orig_length = length;
88     size_t offset = 0;
89 
90     size_t chksum_offset = Tell() & 3;
91     if (chksum_offset) {
92       const size_t l = std::min(length, static_cast<size_t>(4) - chksum_offset);
93       uint32_t tmp = 0;
94       std::memcpy(reinterpret_cast<uint8_t *>(&tmp) + chksum_offset, data, l);
95       chksum_ += ots_ntohl(tmp);
96       length -= l;
97       offset += l;
98     }
99 
100     while (length >= 4) {
101       uint32_t tmp;
102       std::memcpy(&tmp, reinterpret_cast<const uint8_t *>(data) + offset,
103         sizeof(uint32_t));
104       chksum_ += ots_ntohl(tmp);
105       length -= 4;
106       offset += 4;
107     }
108 
109     if (length) {
110       if (length > 4) return false;  // not reached
111       uint32_t tmp = 0;
112       std::memcpy(&tmp,
113                   reinterpret_cast<const uint8_t*>(data) + offset, length);
114       chksum_ += ots_ntohl(tmp);
115     }
116 
117     return WriteRaw(data, orig_length);
118   }
119 
120   virtual bool Seek(off_t position) = 0;
121   virtual off_t Tell() const = 0;
122 
Pad(size_t bytes)123   virtual bool Pad(size_t bytes) {
124     static const uint32_t kZero = 0;
125     while (bytes >= 4) {
126       if (!Write(&kZero, 4)) return false;
127       bytes -= 4;
128     }
129     while (bytes) {
130       static const uint8_t kZerob = 0;
131       if (!Write(&kZerob, 1)) return false;
132       bytes--;
133     }
134     return true;
135   }
136 
WriteU8(uint8_t v)137   bool WriteU8(uint8_t v) {
138     return Write(&v, sizeof(v));
139   }
140 
WriteU16(uint16_t v)141   bool WriteU16(uint16_t v) {
142     v = ots_htons(v);
143     return Write(&v, sizeof(v));
144   }
145 
WriteS16(int16_t v)146   bool WriteS16(int16_t v) {
147     v = ots_htons(v);
148     return Write(&v, sizeof(v));
149   }
150 
WriteU24(uint32_t v)151   bool WriteU24(uint32_t v) {
152     v = ots_htonl(v);
153     return Write(reinterpret_cast<uint8_t*>(&v)+1, 3);
154   }
155 
WriteU32(uint32_t v)156   bool WriteU32(uint32_t v) {
157     v = ots_htonl(v);
158     return Write(&v, sizeof(v));
159   }
160 
WriteS32(int32_t v)161   bool WriteS32(int32_t v) {
162     v = ots_htonl(v);
163     return Write(&v, sizeof(v));
164   }
165 
WriteR64(uint64_t v)166   bool WriteR64(uint64_t v) {
167     return Write(&v, sizeof(v));
168   }
169 
ResetChecksum()170   void ResetChecksum() {
171     assert((Tell() & 3) == 0);
172     chksum_ = 0;
173   }
174 
chksum()175   uint32_t chksum() const {
176     return chksum_;
177   }
178 
179  protected:
180   uint32_t chksum_;
181 };
182 
183 #ifdef __GCC__
184 #define MSGFUNC_FMT_ATTR __attribute__((format(printf, 2, 3)))
185 #else
186 #define MSGFUNC_FMT_ATTR
187 #endif
188 
189 enum TableAction {
190   TABLE_ACTION_DEFAULT,  // Use OTS's default action for that table
191   TABLE_ACTION_SANITIZE, // Sanitize the table, potentially dropping it
192   TABLE_ACTION_PASSTHRU, // Serialize the table unchanged
193   TABLE_ACTION_DROP      // Drop the table
194 };
195 
196 class OTS_API OTSContext {
197   public:
OTSContext()198     OTSContext() {}
~OTSContext()199     virtual ~OTSContext() {}
200 
201     // Process a given OpenType file and write out a sanitized version
202     //   output: a pointer to an object implementing the OTSStream interface. The
203     //     sanitisied output will be written to this. In the even of a failure,
204     //     partial output may have been written.
205     //   input: the OpenType file
206     //   length: the size, in bytes, of |input|
207     //   index: if the input is a font collection and index is specified, then
208     //     the corresponding font will be returned, otherwise the whole
209     //     collection. Ignored for non-collection fonts.
210     bool Process(OTSStream *output, const uint8_t *input, size_t length, uint32_t index = -1);
211 
212     // This function will be called when OTS is reporting an error.
213     //   level: the severity of the generated message:
214     //     0: error messages in case OTS fails to sanitize the font.
215     //     1: warning messages about issue OTS fixed in the sanitized font.
Message(int level OTS_UNUSED,const char * format OTS_UNUSED,...)216     virtual void Message(int level OTS_UNUSED, const char *format OTS_UNUSED, ...) MSGFUNC_FMT_ATTR {}
217 
218     // This function will be called when OTS needs to decide what to do for a
219     // font table.
220     //   tag: table tag formed with OTS_TAG() macro
GetTableAction(uint32_t tag OTS_UNUSED)221     virtual TableAction GetTableAction(uint32_t tag OTS_UNUSED) { return ots::TABLE_ACTION_DEFAULT; }
222 };
223 
224 }  // namespace ots
225 
226 #endif  // OPENTYPE_SANITISER_H_
227