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.
16 #include "opentype-sanitiser.h"
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)))
25 #if !defined(OTS_DEBUG)
26 #define OTS_FAILURE() false
28 #define OTS_FAILURE() \
30 std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \
31 __FILE__, __LINE__, __FUNCTION__) \
36 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original
37 // message-less OTS_FAILURE(), so that the current parser will return 'false' as
38 // its result (indicating a failure).
40 #if !defined(OTS_DEBUG)
41 #define OTS_MESSAGE_(level,otf_,...) \
42 (otf_)->context->Message(level,__VA_ARGS__)
44 #define OTS_MESSAGE_(level,otf_,...) \
46 (otf_)->context->Message(level,__VA_ARGS__)
49 // Generate a simple message
50 #define OTS_FAILURE_MSG_(otf_,...) \
51 (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false)
53 #define OTS_WARNING_MSG_(otf_,...) \
54 OTS_MESSAGE_(1,otf_,__VA_ARGS__)
56 // Generate a message with an associated table tag
57 #define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
58 (OTS_MESSAGE_(0,otf_,"%4.4s: %s", tag_, msg_), false)
60 // Convenience macros for use in files that only handle a single table tag,
61 // defined as TABLE_NAME at the top of the file; the 'file' variable is
62 // expected to be the current OpenTypeFile pointer.
63 #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__)
65 #define OTS_WARNING(...) OTS_WARNING_MSG_(file, TABLE_NAME ": " __VA_ARGS__)
67 // -----------------------------------------------------------------------------
68 // Buffer helper class
70 // This class perform some trival buffer operations while checking for
71 // out-of-bounds errors. As a family they return false if anything is amiss,
72 // updating the current offset otherwise.
73 // -----------------------------------------------------------------------------
76 Buffer(const uint8_t *buf
, size_t len
)
81 bool Skip(size_t n_bytes
) {
82 return Read(NULL
, n_bytes
);
85 bool Read(uint8_t *buf
, size_t n_bytes
) {
86 if (n_bytes
> 1024 * 1024 * 1024) {
89 if ((offset_
+ n_bytes
> length_
) ||
90 (offset_
> length_
- n_bytes
)) {
94 std::memcpy(buf
, buffer_
+ offset_
, n_bytes
);
100 inline bool ReadU8(uint8_t *value
) {
101 if (offset_
+ 1 > length_
) {
102 return OTS_FAILURE();
104 *value
= buffer_
[offset_
];
109 bool ReadU16(uint16_t *value
) {
110 if (offset_
+ 2 > length_
) {
111 return OTS_FAILURE();
113 std::memcpy(value
, buffer_
+ offset_
, sizeof(uint16_t));
114 *value
= ntohs(*value
);
119 bool ReadS16(int16_t *value
) {
120 return ReadU16(reinterpret_cast<uint16_t*>(value
));
123 bool ReadU24(uint32_t *value
) {
124 if (offset_
+ 3 > length_
) {
125 return OTS_FAILURE();
127 *value
= static_cast<uint32_t>(buffer_
[offset_
]) << 16 |
128 static_cast<uint32_t>(buffer_
[offset_
+ 1]) << 8 |
129 static_cast<uint32_t>(buffer_
[offset_
+ 2]);
134 bool ReadU32(uint32_t *value
) {
135 if (offset_
+ 4 > length_
) {
136 return OTS_FAILURE();
138 std::memcpy(value
, buffer_
+ offset_
, sizeof(uint32_t));
139 *value
= ntohl(*value
);
144 bool ReadS32(int32_t *value
) {
145 return ReadU32(reinterpret_cast<uint32_t*>(value
));
148 bool ReadTag(uint32_t *value
) {
149 if (offset_
+ 4 > length_
) {
150 return OTS_FAILURE();
152 std::memcpy(value
, buffer_
+ offset_
, sizeof(uint32_t));
157 bool ReadR64(uint64_t *value
) {
158 if (offset_
+ 8 > length_
) {
159 return OTS_FAILURE();
161 std::memcpy(value
, buffer_
+ offset_
, sizeof(uint64_t));
166 const uint8_t *buffer() const { return buffer_
; }
167 size_t offset() const { return offset_
; }
168 size_t length() const { return length_
; }
170 void set_offset(size_t newoffset
) { offset_
= newoffset
; }
173 const uint8_t * const buffer_
;
174 const size_t length_
;
178 // Round a value up to the nearest multiple of 4. Don't round the value in the
179 // case that rounding up overflows.
180 template<typename T
> T
Round4(T value
) {
181 if (std::numeric_limits
<T
>::max() - value
< 3) {
184 return (value
+ 3) & ~3;
187 template<typename T
> T
Round2(T value
) {
188 if (value
== std::numeric_limits
<T
>::max()) {
191 return (value
+ 1) & ~1;
194 bool IsValidVersionTag(uint32_t tag
);
196 #define FOR_EACH_TABLE_TYPE \
224 #define F(name, capname) struct OpenType##capname;
228 struct OpenTypeFile
{
230 #define F(name, capname) name = NULL;
237 uint16_t search_range
;
238 uint16_t entry_selector
;
239 uint16_t range_shift
;
243 #define F(name, capname) OpenType##capname *name;
248 #define F(name, capname) \
249 bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \
250 bool ots_##name##_should_serialise(OpenTypeFile *f); \
251 bool ots_##name##_serialise(OTSStream *s, OpenTypeFile *f); \
252 void ots_##name##_free(OpenTypeFile *f);
253 // TODO(yusukes): change these function names to follow Chromium coding rule.