• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 The Chromium 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 OTS_H_
6 #define OTS_H_
7 
8 #include <stddef.h>
9 #include <cstdarg>
10 #include <cstddef>
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
14 #include <limits>
15 
16 #include "opentype-sanitiser.h"
17 
18 // arraysize borrowed from base/basictypes.h
19 template <typename T, size_t N>
20 char (&ArraySizeHelper(T (&array)[N]))[N];
21 #define arraysize(array) (sizeof(ArraySizeHelper(array)))
22 
23 namespace ots {
24 
25 #if defined(_MSC_VER) || !defined(OTS_DEBUG)
26 #define OTS_FAILURE() false
27 #else
28 #define OTS_FAILURE() ots::Failure(__FILE__, __LINE__, __PRETTY_FUNCTION__)
29 bool Failure(const char *f, int l, const char *fn);
30 #endif
31 
32 #if defined(_MSC_VER)
33 // MSVC supports C99 style variadic macros.
34 #define OTS_WARNING(format, ...)
35 #else
36 // GCC
37 #if defined(OTS_DEBUG)
38 #define OTS_WARNING(format, args...) \
39     ots::Warning(__FILE__, __LINE__, format, ##args)
40 void Warning(const char *f, int l, const char *format, ...)
41      __attribute__((format(printf, 3, 4)));
42 #else
43 #define OTS_WARNING(format, args...)
44 #endif
45 #endif
46 
47 // Define OTS_NO_TRANSCODE_HINTS (i.e., g++ -DOTS_NO_TRANSCODE_HINTS) if you
48 // want to omit TrueType hinting instructions and variables in glyf, fpgm, prep,
49 // and cvt tables.
50 #if defined(OTS_NO_TRANSCODE_HINTS)
51 const bool g_transcode_hints = false;
52 #else
53 const bool g_transcode_hints = true;
54 #endif
55 
56 // -----------------------------------------------------------------------------
57 // Buffer helper class
58 //
59 // This class perform some trival buffer operations while checking for
60 // out-of-bounds errors. As a family they return false if anything is amiss,
61 // updating the current offset otherwise.
62 // -----------------------------------------------------------------------------
63 class Buffer {
64  public:
Buffer(const uint8_t * buffer,size_t len)65   Buffer(const uint8_t *buffer, size_t len)
66       : buffer_(buffer),
67         length_(len),
68         offset_(0) { }
69 
Skip(size_t n_bytes)70   bool Skip(size_t n_bytes) {
71     return Read(NULL, n_bytes);
72   }
73 
Read(uint8_t * buffer,size_t n_bytes)74   bool Read(uint8_t *buffer, size_t n_bytes) {
75     if (n_bytes > 1024 * 1024 * 1024) {
76       return OTS_FAILURE();
77     }
78     if ((offset_ + n_bytes > length_) ||
79         (offset_ > length_ - n_bytes)) {
80       return OTS_FAILURE();
81     }
82     if (buffer) {
83       std::memcpy(buffer, buffer_ + offset_, n_bytes);
84     }
85     offset_ += n_bytes;
86     return true;
87   }
88 
ReadU8(uint8_t * value)89   inline bool ReadU8(uint8_t *value) {
90     if (offset_ + 1 > length_) {
91       return OTS_FAILURE();
92     }
93     *value = buffer_[offset_];
94     ++offset_;
95     return true;
96   }
97 
ReadU16(uint16_t * value)98   bool ReadU16(uint16_t *value) {
99     if (offset_ + 2 > length_) {
100       return OTS_FAILURE();
101     }
102     std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
103     *value = ntohs(*value);
104     offset_ += 2;
105     return true;
106   }
107 
ReadS16(int16_t * value)108   bool ReadS16(int16_t *value) {
109     return ReadU16(reinterpret_cast<uint16_t*>(value));
110   }
111 
ReadU24(uint32_t * value)112   bool ReadU24(uint32_t *value) {
113     if (offset_ + 3 > length_) {
114       return OTS_FAILURE();
115     }
116     *value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
117         static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 |
118         static_cast<uint32_t>(buffer_[offset_ + 2]);
119     offset_ += 3;
120     return true;
121   }
122 
ReadU32(uint32_t * value)123   bool ReadU32(uint32_t *value) {
124     if (offset_ + 4 > length_) {
125       return OTS_FAILURE();
126     }
127     std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
128     *value = ntohl(*value);
129     offset_ += 4;
130     return true;
131   }
132 
ReadS32(int32_t * value)133   bool ReadS32(int32_t *value) {
134     return ReadU32(reinterpret_cast<uint32_t*>(value));
135   }
136 
ReadTag(uint32_t * value)137   bool ReadTag(uint32_t *value) {
138     if (offset_ + 4 > length_) {
139       return OTS_FAILURE();
140     }
141     std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
142     offset_ += 4;
143     return true;
144   }
145 
ReadR64(uint64_t * value)146   bool ReadR64(uint64_t *value) {
147     if (offset_ + 8 > length_) {
148       return OTS_FAILURE();
149     }
150     std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
151     offset_ += 8;
152     return true;
153   }
154 
buffer()155   const uint8_t *buffer() const { return buffer_; }
offset()156   size_t offset() const { return offset_; }
length()157   size_t length() const { return length_; }
158 
set_offset(size_t newoffset)159   void set_offset(size_t newoffset) { offset_ = newoffset; }
160 
161  private:
162   const uint8_t * const buffer_;
163   const size_t length_;
164   size_t offset_;
165 };
166 
167 // Round a value up to the nearest multiple of 4. Don't round the value in the
168 // case that rounding up overflows.
Round4(T value)169 template<typename T> T Round4(T value) {
170   if (std::numeric_limits<T>::max() - value < 3) {
171     return value;
172   }
173   return (value + 3) & ~3;
174 }
175 
Round2(T value)176 template<typename T> T Round2(T value) {
177   if (value == std::numeric_limits<T>::max()) {
178     return value;
179   }
180   return (value + 1) & ~1;
181 }
182 
183 bool IsValidVersionTag(uint32_t tag);
184 
185 #define FOR_EACH_TABLE_TYPE \
186   F(cff, CFF) \
187   F(cmap, CMAP) \
188   F(cvt, CVT) \
189   F(fpgm, FPGM) \
190   F(gasp, GASP) \
191   F(gdef, GDEF) \
192   F(glyf, GLYF) \
193   F(gpos, GPOS) \
194   F(gsub, GSUB) \
195   F(hdmx, HDMX) \
196   F(head, HEAD) \
197   F(hhea, HHEA) \
198   F(hmtx, HMTX) \
199   F(kern, KERN) \
200   F(loca, LOCA) \
201   F(ltsh, LTSH) \
202   F(maxp, MAXP) \
203   F(name, NAME) \
204   F(os2, OS2) \
205   F(post, POST) \
206   F(prep, PREP) \
207   F(vdmx, VDMX) \
208   F(vorg, VORG) \
209   F(vhea, VHEA) \
210   F(vmtx, VMTX)
211 
212 #define F(name, capname) struct OpenType##capname;
213 FOR_EACH_TABLE_TYPE
214 #undef F
215 
216 struct OpenTypeFile {
OpenTypeFileOpenTypeFile217   OpenTypeFile() {
218 #define F(name, capname) name = NULL;
219     FOR_EACH_TABLE_TYPE
220 #undef F
221   }
222 
223   uint32_t version;
224   uint16_t num_tables;
225   uint16_t search_range;
226   uint16_t entry_selector;
227   uint16_t range_shift;
228 
229 #define F(name, capname) OpenType##capname *name;
230 FOR_EACH_TABLE_TYPE
231 #undef F
232 };
233 
234 #define F(name, capname) \
235 bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \
236 bool ots_##name##_should_serialise(OpenTypeFile *f); \
237 bool ots_##name##_serialise(OTSStream *s, OpenTypeFile *f); \
238 void ots_##name##_free(OpenTypeFile *f);
239 // TODO(yusukes): change these function names to follow Chromium coding rule.
240 FOR_EACH_TABLE_TYPE
241 #undef F
242 
243 }  // namespace ots
244 
245 #endif  // OTS_H_
246