OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. |
3 * Copyright © 2012 Google, Inc. | 3 * Copyright © 2012 Google, Inc. |
4 * | 4 * |
5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
6 * | 6 * |
7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 this->writable = false; | 190 this->writable = false; |
191 } | 191 } |
192 | 192 |
193 inline void start_processing (void) | 193 inline void start_processing (void) |
194 { | 194 { |
195 this->start = hb_blob_get_data (this->blob, NULL); | 195 this->start = hb_blob_get_data (this->blob, NULL); |
196 this->end = this->start + hb_blob_get_length (this->blob); | 196 this->end = this->start + hb_blob_get_length (this->blob); |
197 this->edit_count = 0; | 197 this->edit_count = 0; |
198 this->debug_depth = 0; | 198 this->debug_depth = 0; |
199 | 199 |
200 DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1, | 200 DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1, |
201 "start [%p..%p] (%lu bytes)", | 201 "start [%p..%p] (%lu bytes)", |
202 this->start, this->end, | 202 this->start, this->end, |
203 (unsigned long) (this->end - this->start)); | 203 (unsigned long) (this->end - this->start)); |
204 } | 204 } |
205 | 205 |
206 inline void end_processing (void) | 206 inline void end_processing (void) |
207 { | 207 { |
208 DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1, | 208 DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1, |
209 "end [%p..%p] %u edit requests", | 209 "end [%p..%p] %u edit requests", |
210 this->start, this->end, this->edit_count); | 210 this->start, this->end, this->edit_count); |
211 | 211 |
212 hb_blob_destroy (this->blob); | 212 hb_blob_destroy (this->blob); |
213 this->blob = NULL; | 213 this->blob = NULL; |
214 this->start = this->end = NULL; | 214 this->start = this->end = NULL; |
215 } | 215 } |
216 | 216 |
217 inline bool check_range (const void *base, unsigned int len) const | 217 inline bool check_range (const void *base, unsigned int len) const |
218 { | 218 { |
219 const char *p = (const char *) base; | 219 const char *p = (const char *) base; |
| 220 bool ok = this->start <= p && p <= this->end && (unsigned int) (this->end -
p) >= len; |
220 | 221 |
221 hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace | 222 DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, |
222 (&this->debug_depth, "SANITIZE", this->blob, NULL, | 223 "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s", |
223 "check_range [%p..%p] (%d bytes) in [%p..%p]", | |
224 p, p + len, len, | 224 p, p + len, len, |
225 this->start, this->end); | 225 this->start, this->end, |
| 226 ok ? "OK" : "OUT-OF-RANGE"); |
226 | 227 |
227 return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned
int) (this->end - p) >= len)); | 228 return likely (ok); |
228 } | 229 } |
229 | 230 |
230 inline bool check_array (const void *base, unsigned int record_size, unsigned
int len) const | 231 inline bool check_array (const void *base, unsigned int record_size, unsigned
int len) const |
231 { | 232 { |
232 const char *p = (const char *) base; | 233 const char *p = (const char *) base; |
233 bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); | 234 bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); |
| 235 unsigned int array_size = record_size * len; |
| 236 bool ok = !overflows && this->check_range (base, array_size); |
234 | 237 |
235 hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace | 238 DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, |
236 (&this->debug_depth, "SANITIZE", this->blob, NULL, | 239 "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s", |
237 "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", | 240 p, p + (record_size * len), record_size, len, (unsigned int) array_size, |
238 p, p + (record_size * len), record_size, len, (unsigned long) record_size
* len, | 241 this->start, this->end, |
239 this->start, this->end); | 242 overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE"); |
240 | 243 |
241 return TRACE_RETURN (likely (!overflows && this->check_range (base, record_s
ize * len))); | 244 return likely (ok); |
242 } | 245 } |
243 | 246 |
244 template <typename Type> | 247 template <typename Type> |
245 inline bool check_struct (const Type *obj) const | 248 inline bool check_struct (const Type *obj) const |
246 { | 249 { |
247 return likely (this->check_range (obj, obj->min_size)); | 250 return likely (this->check_range (obj, obj->min_size)); |
248 } | 251 } |
249 | 252 |
250 inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) | 253 inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) |
251 { | 254 { |
252 if (this->edit_count >= HB_SANITIZE_MAX_EDITS) | 255 if (this->edit_count >= HB_SANITIZE_MAX_EDITS) |
253 return false; | 256 return false; |
254 | 257 |
255 const char *p = (const char *) base; | 258 const char *p = (const char *) base; |
256 this->edit_count++; | 259 this->edit_count++; |
257 | 260 |
258 hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace | 261 DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, |
259 (&this->debug_depth, "SANITIZE", this->blob, NULL, | |
260 "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", | 262 "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", |
261 this->edit_count, | 263 this->edit_count, |
262 p, p + len, len, | 264 p, p + len, len, |
263 this->start, this->end, | 265 this->start, this->end, |
264 this->writable ? "GRANTED" : "DENIED"); | 266 this->writable ? "GRANTED" : "DENIED"); |
265 | 267 |
266 return TRACE_RETURN (this->writable); | 268 return this->writable; |
267 } | 269 } |
268 | 270 |
269 template <typename Type, typename ValueType> | 271 template <typename Type, typename ValueType> |
270 inline bool try_set (Type *obj, const ValueType &v) { | 272 inline bool try_set (Type *obj, const ValueType &v) { |
271 if (this->may_edit (obj, obj->static_size)) { | 273 if (this->may_edit (obj, obj->static_size)) { |
272 obj->set (v); | 274 obj->set (v); |
273 return true; | 275 return true; |
274 } | 276 } |
275 return false; | 277 return false; |
276 } | 278 } |
(...skipping 13 matching lines...) Expand all Loading... |
290 { | 292 { |
291 static hb_blob_t *sanitize (hb_blob_t *blob) { | 293 static hb_blob_t *sanitize (hb_blob_t *blob) { |
292 hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}}; | 294 hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}}; |
293 bool sane; | 295 bool sane; |
294 | 296 |
295 /* TODO is_sane() stuff */ | 297 /* TODO is_sane() stuff */ |
296 | 298 |
297 c->init (blob); | 299 c->init (blob); |
298 | 300 |
299 retry: | 301 retry: |
300 DEBUG_MSG_FUNC (SANITIZE, blob, "start"); | 302 DEBUG_MSG_FUNC (SANITIZE, c->start, "start"); |
301 | 303 |
302 c->start_processing (); | 304 c->start_processing (); |
303 | 305 |
304 if (unlikely (!c->start)) { | 306 if (unlikely (!c->start)) { |
305 c->end_processing (); | 307 c->end_processing (); |
306 return blob; | 308 return blob; |
307 } | 309 } |
308 | 310 |
309 Type *t = CastP<Type> (const_cast<char *> (c->start)); | 311 Type *t = CastP<Type> (const_cast<char *> (c->start)); |
310 | 312 |
311 sane = t->sanitize (c); | 313 sane = t->sanitize (c); |
312 if (sane) { | 314 if (sane) { |
313 if (c->edit_count) { | 315 if (c->edit_count) { |
314 » DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going
for second round", c->edit_count); | 316 » DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; g
oing for second round", c->edit_count); |
315 | 317 |
316 /* sanitize again to ensure no toe-stepping */ | 318 /* sanitize again to ensure no toe-stepping */ |
317 c->edit_count = 0; | 319 c->edit_count = 0; |
318 sane = t->sanitize (c); | 320 sane = t->sanitize (c); |
319 if (c->edit_count) { | 321 if (c->edit_count) { |
320 » DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; F
AILLING", c->edit_count); | 322 » DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second roun
d; FAILLING", c->edit_count); |
321 sane = false; | 323 sane = false; |
322 } | 324 } |
323 } | 325 } |
324 } else { | 326 } else { |
325 unsigned int edit_count = c->edit_count; | 327 unsigned int edit_count = c->edit_count; |
326 if (edit_count && !c->writable) { | 328 if (edit_count && !c->writable) { |
327 c->start = hb_blob_get_data_writable (blob, NULL); | 329 c->start = hb_blob_get_data_writable (blob, NULL); |
328 c->end = c->start + hb_blob_get_length (blob); | 330 c->end = c->start + hb_blob_get_length (blob); |
329 | 331 |
330 if (c->start) { | 332 if (c->start) { |
331 c->writable = true; | 333 c->writable = true; |
332 /* ok, we made it writable by relocating. try again */ | 334 /* ok, we made it writable by relocating. try again */ |
333 » DEBUG_MSG_FUNC (SANITIZE, blob, "retry"); | 335 » DEBUG_MSG_FUNC (SANITIZE, c->start, "retry"); |
334 goto retry; | 336 goto retry; |
335 } | 337 } |
336 } | 338 } |
337 } | 339 } |
338 | 340 |
339 c->end_processing (); | 341 c->end_processing (); |
340 | 342 |
341 DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED"); | 343 DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED"); |
342 if (sane) | 344 if (sane) |
343 return blob; | 345 return blob; |
344 else { | 346 else { |
345 hb_blob_destroy (blob); | 347 hb_blob_destroy (blob); |
346 return hb_blob_get_empty (); | 348 return hb_blob_get_empty (); |
347 } | 349 } |
348 } | 350 } |
349 | 351 |
350 static const Type* lock_instance (hb_blob_t *blob) { | 352 static const Type* lock_instance (hb_blob_t *blob) { |
351 hb_blob_make_immutable (blob); | 353 hb_blob_make_immutable (blob); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 * Int types | 528 * Int types |
527 */ | 529 */ |
528 | 530 |
529 | 531 |
530 template <typename Type, int Bytes> struct BEInt; | 532 template <typename Type, int Bytes> struct BEInt; |
531 | 533 |
532 template <typename Type> | 534 template <typename Type> |
533 struct BEInt<Type, 2> | 535 struct BEInt<Type, 2> |
534 { | 536 { |
535 public: | 537 public: |
536 inline void set (Type i) { hb_be_uint16_put (v,i); } | 538 inline void set (Type V) |
537 inline operator Type (void) const { return hb_be_uint16_get (v); } | 539 { |
538 inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_
eq (v, o.v); } | 540 v[0] = (V >> 8) & 0xFF; |
| 541 v[1] = (V ) & 0xFF; |
| 542 } |
| 543 inline operator Type (void) const |
| 544 { |
| 545 return (v[0] << 8) |
| 546 + (v[1] ); |
| 547 } |
| 548 inline bool operator == (const BEInt<Type, 2>& o) const |
| 549 { |
| 550 return v[0] == o.v[0] |
| 551 && v[1] == o.v[1]; |
| 552 } |
539 inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o)
; } | 553 inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o)
; } |
540 private: uint8_t v[2]; | 554 private: uint8_t v[2]; |
541 }; | 555 }; |
542 template <typename Type> | 556 template <typename Type> |
| 557 struct BEInt<Type, 3> |
| 558 { |
| 559 public: |
| 560 inline void set (Type V) |
| 561 { |
| 562 v[0] = (V >> 16) & 0xFF; |
| 563 v[1] = (V >> 8) & 0xFF; |
| 564 v[2] = (V ) & 0xFF; |
| 565 } |
| 566 inline operator Type (void) const |
| 567 { |
| 568 return (v[0] << 16) |
| 569 + (v[1] << 8) |
| 570 + (v[2] ); |
| 571 } |
| 572 inline bool operator == (const BEInt<Type, 3>& o) const |
| 573 { |
| 574 return v[0] == o.v[0] |
| 575 && v[1] == o.v[1] |
| 576 && v[2] == o.v[2]; |
| 577 } |
| 578 inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o)
; } |
| 579 private: uint8_t v[3]; |
| 580 }; |
| 581 template <typename Type> |
543 struct BEInt<Type, 4> | 582 struct BEInt<Type, 4> |
544 { | 583 { |
545 public: | 584 public: |
546 inline void set (Type i) { hb_be_uint32_put (v,i); } | 585 inline void set (Type V) |
547 inline operator Type (void) const { return hb_be_uint32_get (v); } | 586 { |
548 inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_
eq (v, o.v); } | 587 v[0] = (V >> 24) & 0xFF; |
| 588 v[1] = (V >> 16) & 0xFF; |
| 589 v[2] = (V >> 8) & 0xFF; |
| 590 v[3] = (V ) & 0xFF; |
| 591 } |
| 592 inline operator Type (void) const |
| 593 { |
| 594 return (v[0] << 24) |
| 595 + (v[1] << 16) |
| 596 + (v[2] << 8) |
| 597 + (v[3] ); |
| 598 } |
| 599 inline bool operator == (const BEInt<Type, 4>& o) const |
| 600 { |
| 601 return v[0] == o.v[0] |
| 602 && v[1] == o.v[1] |
| 603 && v[2] == o.v[2] |
| 604 && v[3] == o.v[3]; |
| 605 } |
549 inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o)
; } | 606 inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o)
; } |
550 private: uint8_t v[4]; | 607 private: uint8_t v[4]; |
551 }; | 608 }; |
552 template <typename Type> | |
553 struct BEInt<Type, 3> | |
554 { | |
555 public: | |
556 inline void set (Type i) { hb_be_uint24_put (v,i); } | |
557 inline operator Type (void) const { return hb_be_uint24_get (v); } | |
558 inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_
eq (v, o.v); } | |
559 inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o)
; } | |
560 private: uint8_t v[3]; | |
561 }; | |
562 | 609 |
563 /* Integer types in big-endian order and no alignment requirement */ | 610 /* Integer types in big-endian order and no alignment requirement */ |
564 template <typename Type, unsigned int Size> | 611 template <typename Type, unsigned int Size> |
565 struct IntType | 612 struct IntType |
566 { | 613 { |
567 inline void set (Type i) { v.set (i); } | 614 inline void set (Type i) { v.set (i); } |
568 inline operator Type(void) const { return v; } | 615 inline operator Type(void) const { return v; } |
569 inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v;
} | 616 inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v;
} |
570 inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v;
} | 617 inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v;
} |
571 static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *
b) { return b->cmp (*a); } | 618 static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *
b) { return b->cmp (*a); } |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 } | 998 } |
952 return -1; | 999 return -1; |
953 } | 1000 } |
954 }; | 1001 }; |
955 | 1002 |
956 | 1003 |
957 } /* namespace OT */ | 1004 } /* namespace OT */ |
958 | 1005 |
959 | 1006 |
960 #endif /* HB_OPEN_TYPE_PRIVATE_HH */ | 1007 #endif /* HB_OPEN_TYPE_PRIVATE_HH */ |
OLD | NEW |