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.
17 #include "opentype-sanitiser.h"
19 // arraysize borrowed from base/basictypes.h
20 template <typename T
, size_t N
>
21 char (&ArraySizeHelper(T (&array
)[N
]))[N
];
22 #define arraysize(array) (sizeof(ArraySizeHelper(array)))
26 #if !defined(OTS_DEBUG)
27 #define OTS_FAILURE() false
29 #define OTS_FAILURE() \
31 std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \
32 __FILE__, __LINE__, __FUNCTION__) \
37 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original
38 // message-less OTS_FAILURE(), so that the current parser will return 'false' as
39 // its result (indicating a failure).
41 #if !defined(OTS_DEBUG)
42 #define OTS_MESSAGE_(level,otf_,...) \
43 (otf_)->context->Message(level,__VA_ARGS__)
45 #define OTS_MESSAGE_(level,otf_,...) \
47 (otf_)->context->Message(level,__VA_ARGS__)
50 // Generate a simple message
51 #define OTS_FAILURE_MSG_(otf_,...) \
52 (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false)
54 #define OTS_WARNING_MSG_(otf_,...) \
55 OTS_MESSAGE_(1,otf_,__VA_ARGS__)
57 // Generate a message with an associated table tag
58 #define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
59 (OTS_MESSAGE_(0,otf_,"%c%c%c%c: %s", OTS_UNTAG(tag_), msg_), false)
61 // Convenience macros for use in files that only handle a single table tag,
62 // defined as TABLE_NAME at the top of the file; the 'file' variable is
63 // expected to be the current OpenTypeFile pointer.
64 #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__)
66 #define OTS_WARNING(...) OTS_WARNING_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__)
68 // -----------------------------------------------------------------------------
69 // Buffer helper class
71 // This class perform some trival buffer operations while checking for
72 // out-of-bounds errors. As a family they return false if anything is amiss,
73 // updating the current offset otherwise.
74 // -----------------------------------------------------------------------------
77 Buffer(const uint8_t *buf
, size_t len
)
82 bool Skip(size_t n_bytes
) {
83 return Read(NULL
, n_bytes
);
86 bool Read(uint8_t *buf
, size_t n_bytes
) {
87 if (n_bytes
> 1024 * 1024 * 1024) {
90 if ((offset_
+ n_bytes
> length_
) ||
91 (offset_
> length_
- n_bytes
)) {
95 std::memcpy(buf
, buffer_
+ offset_
, n_bytes
);
101 inline bool ReadU8(uint8_t *value
) {
102 if (offset_
+ 1 > length_
) {
103 return OTS_FAILURE();
105 *value
= buffer_
[offset_
];
110 bool ReadU16(uint16_t *value
) {
111 if (offset_
+ 2 > length_
) {
112 return OTS_FAILURE();
114 std::memcpy(value
, buffer_
+ offset_
, sizeof(uint16_t));
115 *value
= ntohs(*value
);
120 bool ReadS16(int16_t *value
) {
121 return ReadU16(reinterpret_cast<uint16_t*>(value
));
124 bool ReadU24(uint32_t *value
) {
125 if (offset_
+ 3 > length_
) {
126 return OTS_FAILURE();
128 *value
= static_cast<uint32_t>(buffer_
[offset_
]) << 16 |
129 static_cast<uint32_t>(buffer_
[offset_
+ 1]) << 8 |
130 static_cast<uint32_t>(buffer_
[offset_
+ 2]);
135 bool ReadU32(uint32_t *value
) {
136 if (offset_
+ 4 > length_
) {
137 return OTS_FAILURE();
139 std::memcpy(value
, buffer_
+ offset_
, sizeof(uint32_t));
140 *value
= ntohl(*value
);
145 bool ReadS32(int32_t *value
) {
146 return ReadU32(reinterpret_cast<uint32_t*>(value
));
149 bool ReadR64(uint64_t *value
) {
150 if (offset_
+ 8 > length_
) {
151 return OTS_FAILURE();
153 std::memcpy(value
, buffer_
+ offset_
, sizeof(uint64_t));
158 const uint8_t *buffer() const { return buffer_
; }
159 size_t offset() const { return offset_
; }
160 size_t length() const { return length_
; }
162 void set_offset(size_t newoffset
) { offset_
= newoffset
; }
165 const uint8_t * const buffer_
;
166 const size_t length_
;
170 // Round a value up to the nearest multiple of 4. Don't round the value in the
171 // case that rounding up overflows.
172 template<typename T
> T
Round4(T value
) {
173 if (std::numeric_limits
<T
>::max() - value
< 3) {
176 return (value
+ 3) & ~3;
179 template<typename T
> T
Round2(T value
) {
180 if (value
== std::numeric_limits
<T
>::max()) {
183 return (value
+ 1) & ~1;
186 bool IsValidVersionTag(uint32_t tag
);
188 #define FOR_EACH_TABLE_TYPE \
216 #define F(name, capname) struct OpenType##capname;
223 #define F(name, capname) \
224 bool ots_##name##_parse(Font *f, const uint8_t *d, size_t l); \
225 bool ots_##name##_should_serialise(Font *f); \
226 bool ots_##name##_serialise(OTSStream *s, Font *f); \
227 void ots_##name##_reuse(Font *f, Font *o);\
228 void ots_##name##_free(Font *f);
233 Font(const OpenTypeFile
*f
) {
235 #define F(name, capname) \
237 name##_reused = false;
243 #define F(name, capname) \
244 if (!name##_reused) {\
245 ots_##name##_free(this); \
251 const OpenTypeFile
*file
;
255 uint16_t search_range
;
256 uint16_t entry_selector
;
257 uint16_t range_shift
;
259 #define F(name, capname) \
260 OpenType##capname *name; \
272 bool operator<(const OutputTable
& other
) const {
273 return tag
< other
.tag
;
277 typedef std::map
<uint32_t, std::pair
<Font
*, OutputTable
> > TableMap
;
279 struct OpenTypeFile
{
286 #undef FOR_EACH_TABLE_TYPE