From 3a9262cc3de4be58804cdd431dd4ae9fa9bfbe7a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 4 Nov 2023 12:52:46 -0600 Subject: [PATCH] [sanitize] More hb_barrier() annotations --- src/OT/Color/CPAL/CPAL.hh | 10 ++++++- src/OT/Color/sbix/sbix.hh | 1 + src/OT/Color/svg/svg.hh | 1 + src/OT/Layout/Common/Coverage.hh | 1 + src/OT/Layout/GDEF/GDEF.hh | 4 +++ src/OT/Layout/GPOS/Anchor.hh | 1 + src/OT/Layout/GPOS/AnchorMatrix.hh | 2 ++ src/OT/Layout/GPOS/MarkMarkPosFormat1.hh | 1 + src/OT/Layout/GPOS/PairPosFormat1.hh | 1 + src/OT/Layout/GPOS/PairSet.hh | 6 +++-- src/OT/Layout/GPOS/SinglePosFormat1.hh | 1 + src/OT/Layout/GPOS/ValueFormat.hh | 1 + .../GSUB/ReverseChainSingleSubstFormat1.hh | 2 ++ src/OT/name/name.hh | 5 +++- src/graph/classdef-graph.hh | 3 +++ src/graph/coverage-graph.hh | 3 +++ src/graph/gsubgpos-graph.hh | 4 +++ src/graph/markbasepos-graph.hh | 3 +++ src/graph/pairpos-graph.hh | 3 +++ src/hb-aat-layout-ankr-table.hh | 1 + src/hb-aat-layout-bsln-table.hh | 1 + src/hb-aat-layout-common.hh | 6 +++++ src/hb-aat-layout-feat-table.hh | 2 ++ src/hb-aat-layout-just-table.hh | 3 +++ src/hb-aat-layout-kerx-table.hh | 17 +++++++----- src/hb-aat-layout-morx-table.hh | 26 ++++++++++++++----- src/hb-aat-layout-opbd-table.hh | 1 + src/hb-aat-layout-trak-table.hh | 2 ++ src/hb-aat-ltag-table.hh | 5 +++- src/hb-open-file.hh | 6 +++++ src/hb-open-type.hh | 14 +++++++++- src/hb-ot-cff-common.hh | 19 +++++++++++--- src/hb-ot-cff1-table.hh | 23 +++++++++++++--- src/hb-ot-cff2-table.hh | 12 ++++++++- 34 files changed, 164 insertions(+), 27 deletions(-) diff --git a/src/OT/Color/CPAL/CPAL.hh b/src/OT/Color/CPAL/CPAL.hh index c07716c1c..e7d32724c 100644 --- a/src/OT/Color/CPAL/CPAL.hh +++ b/src/OT/Color/CPAL/CPAL.hh @@ -214,13 +214,17 @@ struct CPAL hb_set_t *nameids_to_retain /* OUT */) const { if (version == 1) + { + hb_barrier (); v1 ().collect_name_ids (this, numPalettes, numColors, color_index_map, nameids_to_retain); + } } private: const CPALV1Tail& v1 () const { if (version == 0) return Null (CPALV1Tail); + hb_barrier (); return StructAfter (*this); } @@ -312,7 +316,10 @@ struct CPAL return_trace (false); if (version == 1) + { + hb_barrier (); return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map)); + } return_trace (true); } @@ -323,7 +330,8 @@ struct CPAL return_trace (c->check_struct (this) && (this+colorRecordsZ).sanitize (c, numColorRecords) && colorRecordIndicesZ.sanitize (c, numPalettes) && - (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors))); + (version == 0 || + (hb_barrier () && v1 ().sanitize (c, this, numPalettes, numColors)))); } protected: diff --git a/src/OT/Color/sbix/sbix.hh b/src/OT/Color/sbix/sbix.hh index ce8693cfb..51ae1a9c6 100644 --- a/src/OT/Color/sbix/sbix.hh +++ b/src/OT/Color/sbix/sbix.hh @@ -368,6 +368,7 @@ struct sbix { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && version >= 1 && strikes.sanitize (c, this))); } diff --git a/src/OT/Color/svg/svg.hh b/src/OT/Color/svg/svg.hh index c7d91b88e..2e1f93510 100644 --- a/src/OT/Color/svg/svg.hh +++ b/src/OT/Color/svg/svg.hh @@ -56,6 +56,7 @@ struct SVGDocumentIndexEntry { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && svgDoc.sanitize (c, base, svgDocLength)); } diff --git a/src/OT/Layout/Common/Coverage.hh b/src/OT/Layout/Common/Coverage.hh index 25056c9bc..344e87afb 100644 --- a/src/OT/Layout/Common/Coverage.hh +++ b/src/OT/Layout/Common/Coverage.hh @@ -64,6 +64,7 @@ struct Coverage { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); + hb_barrier (); switch (u.format) { case 1: return_trace (u.format1.sanitize (c)); diff --git a/src/OT/Layout/GDEF/GDEF.hh b/src/OT/Layout/GDEF/GDEF.hh index d3611b98f..14a9b5e5c 100644 --- a/src/OT/Layout/GDEF/GDEF.hh +++ b/src/OT/Layout/GDEF/GDEF.hh @@ -291,6 +291,7 @@ struct CaretValue { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); + hb_barrier (); switch (u.format) { case 1: return_trace (u.format1.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); @@ -556,6 +557,7 @@ struct MarkGlyphSets { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); + hb_barrier (); switch (u.format) { case 1: return_trace (u.format1.sanitize (c)); default:return_trace (true); @@ -630,6 +632,7 @@ struct GDEFVersion1_2 attachList.sanitize (c, this) && ligCaretList.sanitize (c, this) && markAttachClassDef.sanitize (c, this) && + hb_barrier () && (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); } @@ -750,6 +753,7 @@ struct GDEF { TRACE_SANITIZE (this); if (unlikely (!u.version.sanitize (c))) return_trace (false); + hb_barrier (); switch (u.version.major) { case 1: return_trace (u.version1.sanitize (c)); #ifndef HB_NO_BEYOND_64K diff --git a/src/OT/Layout/GPOS/Anchor.hh b/src/OT/Layout/GPOS/Anchor.hh index 49e76e775..7802e397f 100644 --- a/src/OT/Layout/GPOS/Anchor.hh +++ b/src/OT/Layout/GPOS/Anchor.hh @@ -25,6 +25,7 @@ struct Anchor { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); + hb_barrier (); switch (u.format) { case 1: return_trace (u.format1.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); diff --git a/src/OT/Layout/GPOS/AnchorMatrix.hh b/src/OT/Layout/GPOS/AnchorMatrix.hh index 17aebab69..dff409c8e 100644 --- a/src/OT/Layout/GPOS/AnchorMatrix.hh +++ b/src/OT/Layout/GPOS/AnchorMatrix.hh @@ -18,6 +18,7 @@ struct AnchorMatrix { TRACE_SANITIZE (this); if (!c->check_struct (this)) return_trace (false); + hb_barrier (); if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false); unsigned int count = rows * cols; if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false); @@ -25,6 +26,7 @@ struct AnchorMatrix if (c->lazy_some_gpos) return_trace (true); + hb_barrier (); for (unsigned int i = 0; i < count; i++) if (!matrixZ[i].sanitize (c, this)) return_trace (false); return_trace (true); diff --git a/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh index 70cf07166..57eb782a9 100644 --- a/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh +++ b/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh @@ -42,6 +42,7 @@ struct MarkMarkPosFormat1_2 mark1Coverage.sanitize (c, this) && mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this) && + hb_barrier () && mark2Array.sanitize (c, this, (unsigned int) classCount)); } diff --git a/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/OT/Layout/GPOS/PairPosFormat1.hh index fa6460852..ac2774a76 100644 --- a/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -36,6 +36,7 @@ struct PairPosFormat1_3 TRACE_SANITIZE (this); if (!c->check_struct (this)) return_trace (false); + hb_barrier (); unsigned int len1 = valueFormat[0].get_len (); unsigned int len2 = valueFormat[1].get_len (); diff --git a/src/OT/Layout/GPOS/PairSet.hh b/src/OT/Layout/GPOS/PairSet.hh index 461360b63..5560fab17 100644 --- a/src/OT/Layout/GPOS/PairSet.hh +++ b/src/OT/Layout/GPOS/PairSet.hh @@ -45,10 +45,12 @@ struct PairSet : ValueBase bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const { TRACE_SANITIZE (this); - if (!(c->check_struct (this) - && c->check_range (&firstPairValueRecord, + if (!(c->check_struct (this) && + hb_barrier () && + c->check_range (&firstPairValueRecord, len, closure->stride))) return_trace (false); + hb_barrier (); unsigned int count = len; const PairValueRecord *record = &firstPairValueRecord; diff --git a/src/OT/Layout/GPOS/SinglePosFormat1.hh b/src/OT/Layout/GPOS/SinglePosFormat1.hh index 57cb826e6..b2d151d44 100644 --- a/src/OT/Layout/GPOS/SinglePosFormat1.hh +++ b/src/OT/Layout/GPOS/SinglePosFormat1.hh @@ -28,6 +28,7 @@ struct SinglePosFormat1 : ValueBase TRACE_SANITIZE (this); return_trace (c->check_struct (this) && coverage.sanitize (c, this) && + hb_barrier () && /* The coverage table may use a range to represent a set * of glyphs, which means a small number of bytes can * generate a large glyph set. Manually modify the diff --git a/src/OT/Layout/GPOS/ValueFormat.hh b/src/OT/Layout/GPOS/ValueFormat.hh index 2b11ffbda..17f57db1f 100644 --- a/src/OT/Layout/GPOS/ValueFormat.hh +++ b/src/OT/Layout/GPOS/ValueFormat.hh @@ -390,6 +390,7 @@ struct ValueFormat : HBUINT16 if (c->lazy_some_gpos) return_trace (true); + hb_barrier (); return_trace (sanitize_values_stride_unsafe (c, base, values, count, size)); } diff --git a/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh index 92bafb5bc..ec374f2f0 100644 --- a/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh +++ b/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh @@ -33,9 +33,11 @@ struct ReverseChainSingleSubstFormat1 TRACE_SANITIZE (this); if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) return_trace (false); + hb_barrier (); const auto &lookahead = StructAfter (backtrack); if (!lookahead.sanitize (c, this)) return_trace (false); + hb_barrier (); const auto &substitute = StructAfter (lookahead); return_trace (substitute.sanitize (c)); } diff --git a/src/OT/name/name.hh b/src/OT/name/name.hh index c8de10134..e2a25d4a0 100644 --- a/src/OT/name/name.hh +++ b/src/OT/name/name.hh @@ -242,7 +242,9 @@ struct NameRecord bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && offset.sanitize (c, base, length)); + return_trace (c->check_struct (this) && + hb_barrier () && + offset.sanitize (c, base, length)); } HBUINT16 platformID; /* Platform ID. */ @@ -465,6 +467,7 @@ struct name { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && likely (format == 0 || format == 1) && c->check_array (nameRecordZ.arrayZ, count) && c->check_range (this, stringOffset) && diff --git a/src/graph/classdef-graph.hh b/src/graph/classdef-graph.hh index c1432883f..9cf845a82 100644 --- a/src/graph/classdef-graph.hh +++ b/src/graph/classdef-graph.hh @@ -39,6 +39,7 @@ struct ClassDefFormat1 : public OT::ClassDefFormat1_3 int64_t vertex_len = vertex.obj.tail - vertex.obj.head; constexpr unsigned min_size = OT::ClassDefFormat1_3::min_size; if (vertex_len < min_size) return false; + hb_barrier (); return vertex_len >= min_size + classValue.get_size () - classValue.len.get_size (); } }; @@ -50,6 +51,7 @@ struct ClassDefFormat2 : public OT::ClassDefFormat2_4 int64_t vertex_len = vertex.obj.tail - vertex.obj.head; constexpr unsigned min_size = OT::ClassDefFormat2_4::min_size; if (vertex_len < min_size) return false; + hb_barrier (); return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size (); } }; @@ -114,6 +116,7 @@ struct ClassDef : public OT::ClassDef { int64_t vertex_len = vertex.obj.tail - vertex.obj.head; if (vertex_len < OT::ClassDef::min_size) return false; + hb_barrier (); switch (u.format) { case 1: return ((ClassDefFormat1*)this)->sanitize (vertex); diff --git a/src/graph/coverage-graph.hh b/src/graph/coverage-graph.hh index 4f44e076d..61ca063e3 100644 --- a/src/graph/coverage-graph.hh +++ b/src/graph/coverage-graph.hh @@ -39,6 +39,7 @@ struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3::min_size; if (vertex_len < min_size) return false; + hb_barrier (); return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size (); } }; @@ -50,6 +51,7 @@ struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4::min_size; if (vertex_len < min_size) return false; + hb_barrier (); return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size (); } }; @@ -138,6 +140,7 @@ struct Coverage : public OT::Layout::Common::Coverage { int64_t vertex_len = vertex.obj.tail - vertex.obj.head; if (vertex_len < OT::Layout::Common::Coverage::min_size) return false; + hb_barrier (); switch (u.format) { case 1: return ((CoverageFormat1*)this)->sanitize (vertex); diff --git a/src/graph/gsubgpos-graph.hh b/src/graph/gsubgpos-graph.hh index 12fcbdc49..0f6d5662e 100644 --- a/src/graph/gsubgpos-graph.hh +++ b/src/graph/gsubgpos-graph.hh @@ -76,6 +76,7 @@ struct Lookup : public OT::Lookup { int64_t vertex_len = vertex.obj.tail - vertex.obj.head; if (vertex_len < OT::Lookup::min_size) return false; + hb_barrier (); return vertex_len >= this->get_size (); } @@ -351,6 +352,7 @@ struct LookupList : public OT::LookupList { int64_t vertex_len = vertex.obj.tail - vertex.obj.head; if (vertex_len < OT::LookupList::min_size) return false; + hb_barrier (); return vertex_len >= OT::LookupList::item_size * this->len; } }; @@ -364,6 +366,7 @@ struct GSTAR : public OT::GSUBGPOS GSTAR* gstar = (GSTAR*) r.obj.head; if (!gstar || !gstar->sanitize (r)) return nullptr; + hb_barrier (); return gstar; } @@ -383,6 +386,7 @@ struct GSTAR : public OT::GSUBGPOS { int64_t len = vertex.obj.tail - vertex.obj.head; if (len < OT::GSUBGPOS::min_size) return false; + hb_barrier (); return len >= get_size (); } diff --git a/src/graph/markbasepos-graph.hh b/src/graph/markbasepos-graph.hh index ae5ebd0d1..fb4166128 100644 --- a/src/graph/markbasepos-graph.hh +++ b/src/graph/markbasepos-graph.hh @@ -40,6 +40,7 @@ struct AnchorMatrix : public OT::Layout::GPOS_impl::AnchorMatrix { int64_t vertex_len = vertex.obj.tail - vertex.obj.head; if (vertex_len < AnchorMatrix::min_size) return false; + hb_barrier (); return vertex_len >= AnchorMatrix::min_size + OT::Offset16::static_size * class_count * this->rows; @@ -128,6 +129,7 @@ struct MarkArray : public OT::Layout::GPOS_impl::MarkArray int64_t vertex_len = vertex.obj.tail - vertex.obj.head; unsigned min_size = MarkArray::min_size; if (vertex_len < min_size) return false; + hb_barrier (); return vertex_len >= get_size (); } @@ -495,6 +497,7 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos { int64_t vertex_len = vertex.obj.tail - vertex.obj.head; if (vertex_len < u.format.get_size ()) return false; + hb_barrier (); switch (u.format) { case 1: diff --git a/src/graph/pairpos-graph.hh b/src/graph/pairpos-graph.hh index ad158cc9e..f7f74b18c 100644 --- a/src/graph/pairpos-graph.hh +++ b/src/graph/pairpos-graph.hh @@ -42,6 +42,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3::min_size; if (vertex_len < min_size) return false; + hb_barrier (); return vertex_len >= min_size + pairSet.get_size () - pairSet.len.get_size(); @@ -198,6 +199,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4::min_size; if (vertex_len < min_size) return false; + hb_barrier (); const unsigned class1_count = class1Count; return vertex_len >= @@ -625,6 +627,7 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos { int64_t vertex_len = vertex.obj.tail - vertex.obj.head; if (vertex_len < u.format.get_size ()) return false; + hb_barrier (); switch (u.format) { case 1: diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh index 63fac8452..dbb38b1bc 100644 --- a/src/hb-aat-layout-ankr-table.hh +++ b/src/hb-aat-layout-ankr-table.hh @@ -75,6 +75,7 @@ struct ankr { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && version == 0 && c->check_range (this, anchorData) && lookupTable.sanitize (c, this, &(this+anchorData)))); diff --git a/src/hb-aat-layout-bsln-table.hh b/src/hb-aat-layout-bsln-table.hh index bf12d2e69..8e42fab2e 100644 --- a/src/hb-aat-layout-bsln-table.hh +++ b/src/hb-aat-layout-bsln-table.hh @@ -123,6 +123,7 @@ struct bsln TRACE_SANITIZE (this); if (unlikely (!(c->check_struct (this) && defaultBaseline < 32))) return_trace (false); + hb_barrier (); switch (format) { diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 672f80e0d..05dd58c6d 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -191,6 +191,7 @@ struct LookupSegmentArray { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && first <= last && valuesZ.sanitize (c, base, last - first + 1)); } @@ -199,6 +200,7 @@ struct LookupSegmentArray { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && first <= last && valuesZ.sanitize (c, base, last - first + 1, std::forward (ds)...)); } @@ -360,6 +362,7 @@ struct LookupFormat10 { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && valueSize <= 4 && valueArrayZ.sanitize (c, glyphCount * valueSize)); } @@ -415,6 +418,7 @@ struct Lookup { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); + hb_barrier (); switch (u.format) { case 0: return_trace (u.format0.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); @@ -429,6 +433,7 @@ struct Lookup { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); + hb_barrier (); switch (u.format) { case 0: return_trace (u.format0.sanitize (c, base)); case 2: return_trace (u.format2.sanitize (c, base)); @@ -558,6 +563,7 @@ struct StateTable { TRACE_SANITIZE (this); if (unlikely (!(c->check_struct (this) && + hb_barrier () && nClasses >= 4 /* Ensure pre-defined classes fit. */ && classTable.sanitize (c, this)))) return_trace (false); diff --git a/src/hb-aat-layout-feat-table.hh b/src/hb-aat-layout-feat-table.hh index 815a1fd2a..4fbec332e 100644 --- a/src/hb-aat-layout-feat-table.hh +++ b/src/hb-aat-layout-feat-table.hh @@ -138,6 +138,7 @@ struct FeatureName { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && (base+settingTableZ).sanitize (c, nSettings))); } @@ -200,6 +201,7 @@ struct feat { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && version.major == 1 && namesZ.sanitize (c, featureNameCount, this))); } diff --git a/src/hb-aat-layout-just-table.hh b/src/hb-aat-layout-just-table.hh index 8fd3990f8..ee08da172 100644 --- a/src/hb-aat-layout-just-table.hh +++ b/src/hb-aat-layout-just-table.hh @@ -185,6 +185,7 @@ struct ActionSubrecord TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); + hb_barrier (); switch (u.header.actionType) { @@ -220,6 +221,7 @@ struct PostcompensationActionChain TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); + hb_barrier (); unsigned int offset = min_size; for (unsigned int i = 0; i < count; i++) @@ -389,6 +391,7 @@ struct just TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && version.major == 1 && horizData.sanitize (c, this, this) && vertData.sanitize (c, this, this))); diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 638908da0..0de54e0a0 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -432,6 +432,7 @@ struct KerxSubTableFormat2 return_trace (likely (c->check_struct (this) && leftClassTable.sanitize (c, this) && rightClassTable.sanitize (c, this) && + hb_barrier () && c->check_range (this, array))); } @@ -682,6 +683,7 @@ struct KerxSubTableFormat6 { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && (is_long () ? ( u.l.rowIndexTable.sanitize (c, this) && @@ -795,9 +797,10 @@ struct KerxSubTable bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!u.header.sanitize (c) || - u.header.length <= u.header.static_size || - !c->check_range (this, u.header.length)) + if (!(u.header.sanitize (c) && + hb_barrier () && + u.header.length >= u.header.static_size && + c->check_range (this, u.header.length))) return_trace (false); return_trace (dispatch (c)); @@ -944,9 +947,10 @@ struct KerxTable bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (!thiz()->version.sanitize (c) || - (unsigned) thiz()->version < (unsigned) T::minVersion || - !thiz()->tableCount.sanitize (c))) + if (unlikely (!(thiz()->version.sanitize (c) && + hb_barrier () && + (unsigned) thiz()->version >= (unsigned) T::minVersion && + thiz()->tableCount.sanitize (c)))) return_trace (false); typedef typename T::SubTable SubTable; @@ -957,6 +961,7 @@ struct KerxTable { if (unlikely (!st->u.header.sanitize (c))) return_trace (false); + hb_barrier (); /* OpenType kern table has 2-byte subtable lengths. That's limiting. * MS implementation also only supports one subtable, of format 0, * anyway. Certain versions of some fonts, like Calibry, contain diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 0abc1659a..df2f35d0d 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -261,6 +261,7 @@ struct ContextualSubtable replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; if (!(replacement->sanitize (&c->sanitizer) && hb_barrier ()) || !*replacement) replacement = nullptr; + hb_barrier (); } if (replacement) { @@ -289,6 +290,7 @@ struct ContextualSubtable replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; if (!(replacement->sanitize (&c->sanitizer) && hb_barrier ()) || !*replacement) replacement = nullptr; + hb_barrier (); } if (replacement) { @@ -336,6 +338,7 @@ struct ContextualSubtable unsigned int num_entries = 0; if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false); + hb_barrier (); if (!Types::extended) return_trace (substitutionTables.sanitize (c, this, 0)); @@ -590,6 +593,7 @@ struct LigatureSubtable TRACE_SANITIZE (this); /* The rest of array sanitizations are done at run-time. */ return_trace (c->check_struct (this) && machine.sanitize (c) && + hb_barrier () && ligAction && component && ligature); } @@ -854,6 +858,7 @@ struct InsertionSubtable TRACE_SANITIZE (this); /* The rest of array sanitizations are done at run-time. */ return_trace (c->check_struct (this) && machine.sanitize (c) && + hb_barrier () && insertionAction); } @@ -949,9 +954,10 @@ struct ChainSubtable bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!length.sanitize (c) || - length <= min_size || - !c->check_range (this, length)) + if (!(length.sanitize (c) && + hb_barrier () && + length >= min_size && + c->check_range (this, length))) return_trace (false); hb_sanitize_with_object_t with (c, this); @@ -1094,9 +1100,10 @@ struct Chain bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const { TRACE_SANITIZE (this); - if (!length.sanitize (c) || - length < min_size || - !c->check_range (this, length)) + if (!(length.sanitize (c) && + hb_barrier () && + length >= min_size && + c->check_range (this, length))) return_trace (false); if (!c->check_array (featureZ.arrayZ, featureCount)) @@ -1108,6 +1115,7 @@ struct Chain { if (!subtable->sanitize (c)) return_trace (false); + hb_barrier (); subtable = &StructAfter> (*subtable); } @@ -1178,7 +1186,10 @@ struct mortmorx bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!version.sanitize (c) || !version || !chainCount.sanitize (c)) + if (!(version.sanitize (c) && + hb_barrier () && + version && + chainCount.sanitize (c))) return_trace (false); const Chain *chain = &firstChain; @@ -1187,6 +1198,7 @@ struct mortmorx { if (!chain->sanitize (c, version)) return_trace (false); + hb_barrier (); chain = &StructAfter> (*chain); } diff --git a/src/hb-aat-layout-opbd-table.hh b/src/hb-aat-layout-opbd-table.hh index 51b650fc3..9840d3a55 100644 --- a/src/hb-aat-layout-opbd-table.hh +++ b/src/hb-aat-layout-opbd-table.hh @@ -144,6 +144,7 @@ struct opbd TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this) || version.major != 1)) return_trace (false); + hb_barrier (); switch (format) { diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index c72c0865d..345a236e9 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -134,6 +134,7 @@ struct TrackData { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && sizeTable.sanitize (c, base, nSizes) && trackTable.sanitize (c, nTracks, base, nSizes))); } @@ -203,6 +204,7 @@ struct trak TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && version.major == 1 && horizData.sanitize (c, this, this) && vertData.sanitize (c, this, this))); diff --git a/src/hb-aat-ltag-table.hh b/src/hb-aat-ltag-table.hh index 6d771e151..c974025d4 100644 --- a/src/hb-aat-ltag-table.hh +++ b/src/hb-aat-ltag-table.hh @@ -46,7 +46,9 @@ struct FTStringRange bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && (base+tag).sanitize (c, length)); + return_trace (c->check_struct (this) && + hb_barrier () && + (base+tag).sanitize (c, length)); } protected: @@ -73,6 +75,7 @@ struct ltag { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && version >= 1 && tagRanges.sanitize (c, this))); } diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh index 04f144a72..1157ea46d 100644 --- a/src/hb-open-file.hh +++ b/src/hb-open-file.hh @@ -267,6 +267,7 @@ struct TTCHeader { TRACE_SANITIZE (this); if (unlikely (!u.header.version.sanitize (c))) return_trace (false); + hb_barrier (); switch (u.header.version.major) { case 2: /* version 2 is compatible with version 1 */ case 1: return_trace (u.version1.sanitize (c)); @@ -302,6 +303,7 @@ struct ResourceRecord TRACE_SANITIZE (this); return_trace (c->check_struct (this) && offset.sanitize (c, data_base) && + hb_barrier () && get_face (data_base).sanitize (c)); } @@ -337,6 +339,7 @@ struct ResourceTypeRecord { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && resourcesZ.sanitize (c, type_base, get_resource_count (), data_base)); @@ -385,6 +388,7 @@ struct ResourceMap { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && typeList.sanitize (c, this, &(this+typeList), data_base)); @@ -428,6 +432,7 @@ struct ResourceForkHeader { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && data.sanitize (c, this, dataLen) && map.sanitize (c, this, &(this+data))); } @@ -508,6 +513,7 @@ struct OpenTypeFontFile { TRACE_SANITIZE (this); if (unlikely (!u.tag.sanitize (c))) return_trace (false); + hb_barrier (); switch (u.tag) { case CFFTag: /* All the non-collection tags */ case TrueTag: diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 5581484f1..6967bca3d 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -418,6 +418,7 @@ struct OffsetTo : Offset { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); + hb_barrier (); //if (unlikely (this->is_null ())) return_trace (true); if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false); return_trace (true); @@ -431,6 +432,7 @@ struct OffsetTo : Offset { TRACE_SANITIZE (this); return_trace (sanitize_shallow (c, base) && + hb_barrier () && (this->is_null () || c->dispatch (StructAtOffset (base, *this), std::forward (ds)...) || neuter (c))); @@ -536,6 +538,7 @@ struct UnsizedArrayOf TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c, count))) return_trace (false); if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true); + hb_barrier (); for (unsigned int i = 0; i < count; i++) if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...))) return_trace (false); @@ -725,6 +728,7 @@ struct ArrayOf TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true); + hb_barrier (); unsigned int count = len; for (unsigned int i = 0; i < count; i++) if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...))) @@ -735,7 +739,9 @@ struct ArrayOf bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (len.sanitize (c) && c->check_array_sized (arrayZ, len, sizeof (LenType))); + return_trace (len.sanitize (c) && + hb_barrier () && + c->check_array_sized (arrayZ, len, sizeof (LenType))); } public: @@ -866,6 +872,7 @@ struct HeadlessArrayOf TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true); + hb_barrier (); unsigned int count = get_length (); for (unsigned int i = 0; i < count; i++) if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...))) @@ -878,6 +885,7 @@ struct HeadlessArrayOf { TRACE_SANITIZE (this); return_trace (lenP1.sanitize (c) && + hb_barrier () && (!lenP1 || c->check_array_sized (arrayZ, lenP1 - 1, sizeof (LenType)))); } @@ -919,6 +927,7 @@ struct ArrayOfM1 TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true); + hb_barrier (); unsigned int count = lenM1 + 1; for (unsigned int i = 0; i < count; i++) if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...))) @@ -931,6 +940,7 @@ struct ArrayOfM1 { TRACE_SANITIZE (this); return_trace (lenM1.sanitize (c) && + hb_barrier () && (c->check_array_sized (arrayZ, lenM1 + 1, sizeof (LenType)))); } @@ -1104,6 +1114,7 @@ struct VarSizedBinSearchArrayOf TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true); + hb_barrier (); unsigned int count = get_length (); for (unsigned int i = 0; i < count; i++) if (unlikely (!(*this)[i].sanitize (c, std::forward (ds)...))) @@ -1130,6 +1141,7 @@ struct VarSizedBinSearchArrayOf { TRACE_SANITIZE (this); return_trace (header.sanitize (c) && + hb_barrier () && Type::static_size <= header.unitSize && c->check_range (bytesZ.arrayZ, header.nUnits, diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh index 923a32b26..6375e8b56 100644 --- a/src/hb-ot-cff-common.hh +++ b/src/hb-ot-cff-common.hh @@ -274,8 +274,10 @@ struct CFFIndex { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && + hb_barrier () && (count == 0 || /* empty INDEX */ (count < count + 1u && + hb_barrier () && c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 && c->check_array (offsets, offSize, count + 1u) && c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count)))))); @@ -412,6 +414,7 @@ struct FDSelect0 { TRACE_SANITIZE (this); if (unlikely (!(c->check_struct (this)))) return_trace (false); + hb_barrier (); if (unlikely (!c->check_array (fds, c->get_num_glyphs ()))) return_trace (false); @@ -438,7 +441,9 @@ struct FDSelect3_4_Range bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const { TRACE_SANITIZE (this); - return_trace (first < c->get_num_glyphs () && (fd < fdcount)); + return_trace (c->check_struct (this) && + hb_barrier () && + first < c->get_num_glyphs () && (fd < fdcount)); } GID_TYPE first; @@ -456,15 +461,20 @@ struct FDSelect3_4 bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) || - (nRanges () == 0) || ranges[0].first != 0)) + if (unlikely (!(c->check_struct (this) && + ranges.sanitize (c, nullptr, fdcount) && + hb_barrier () && + (nRanges () != 0) && + ranges[0].first == 0))) return_trace (false); for (unsigned int i = 1; i < nRanges (); i++) if (unlikely (ranges[i - 1].first >= ranges[i].first)) return_trace (false); - if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ()))) + if (unlikely (!(sentinel().sanitize (c) && + hb_barrier () && + (sentinel() == c->get_num_glyphs ())))) return_trace (false); return_trace (true); @@ -559,6 +569,7 @@ struct FDSelect TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); + hb_barrier (); switch (format) { diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 1e81dcb5e..c869e9055 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -275,6 +275,7 @@ struct Encoding TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); + hb_barrier (); switch (table_format ()) { @@ -376,13 +377,13 @@ struct Charset1_2 { bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) - return_trace (false); num_glyphs--; unsigned i; for (i = 0; num_glyphs > 0; i++) { - if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1))) + if (unlikely (!(ranges[i].sanitize (c) && + hb_barrier () && + (num_glyphs >= ranges[i].nLeft + 1)))) return_trace (false); num_glyphs -= (ranges[i].nLeft + 1); } @@ -615,6 +616,7 @@ struct Charset TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); + hb_barrier (); switch (format) { @@ -1055,6 +1057,7 @@ struct cff1 { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && likely (version.major == 1)); } @@ -1085,14 +1088,17 @@ struct cff1 nameIndex = &cff->nameIndex (cff); if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc)) goto fail; + hb_barrier (); topDictIndex = &StructAtOffset (nameIndex, nameIndex->get_size ()); if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0)) goto fail; + hb_barrier (); { /* parse top dict */ const hb_ubytes_t topDictStr = (*topDictIndex)[0]; if (unlikely (!topDictStr.sanitize (&sc))) goto fail; + hb_barrier (); cff1_top_dict_interp_env_t env (topDictStr); cff1_top_dict_interpreter_t top_interp (env); if (unlikely (!top_interp.interpret (topDict))) goto fail; @@ -1104,6 +1110,7 @@ struct cff1 { charset = &StructAtOffsetOrNull (cff, topDict.CharsetOffset); if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries))) goto fail; + hb_barrier (); } fdCount = 1; @@ -1114,6 +1121,7 @@ struct cff1 if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) || (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count))) goto fail; + hb_barrier (); fdCount = fdArray->count; } @@ -1134,21 +1142,25 @@ struct cff1 { encoding = &StructAtOffsetOrNull (cff, topDict.EncodingOffset); if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) goto fail; + hb_barrier (); } } stringIndex = &StructAtOffset (topDictIndex, topDictIndex->get_size ()); if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc)) goto fail; + hb_barrier (); globalSubrs = &StructAtOffset (stringIndex, stringIndex->get_size ()); if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc)) goto fail; + hb_barrier (); charStrings = &StructAtOffsetOrNull (cff, topDict.charStringsOffset); if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc))) goto fail; + hb_barrier (); num_glyphs = charStrings->count; if (num_glyphs != sc.get_num_glyphs ()) @@ -1166,6 +1178,7 @@ struct cff1 { hb_ubytes_t fontDictStr = (*fdArray)[i]; if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; + hb_barrier (); cff1_font_dict_values_t *font; cff1_top_dict_interp_env_t env (fontDictStr); cff1_font_dict_interpreter_t font_interp (env); @@ -1177,6 +1190,7 @@ struct cff1 PRIVDICTVAL *priv = &privateDicts[i]; const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); if (unlikely (!privDictStr.sanitize (&sc))) goto fail; + hb_barrier (); num_interp_env_t env2 (privDictStr); dict_interpreter_t priv_interp (env2); priv->init (); @@ -1186,6 +1200,7 @@ struct cff1 if (priv->localSubrs != &Null (CFF1Subrs) && unlikely (!priv->localSubrs->sanitize (&sc))) goto fail; + hb_barrier (); } } else /* non-CID */ @@ -1195,6 +1210,7 @@ struct cff1 const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); if (unlikely (!privDictStr.sanitize (&sc))) goto fail; + hb_barrier (); num_interp_env_t env (privDictStr); dict_interpreter_t priv_interp (env); priv->init (); @@ -1204,6 +1220,7 @@ struct cff1 if (priv->localSubrs != &Null (CFF1Subrs) && unlikely (!priv->localSubrs->sanitize (&sc))) goto fail; + hb_barrier (); } return; diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh index af24bb998..652748b73 100644 --- a/src/hb-ot-cff2-table.hh +++ b/src/hb-ot-cff2-table.hh @@ -90,6 +90,7 @@ struct CFF2FDSelect TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); + hb_barrier (); switch (format) { @@ -115,7 +116,10 @@ struct CFF2VariationStore bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this)) && c->check_range (&varStore, size) && varStore.sanitize (c)); + return_trace (c->check_struct (this) && + hb_barrier () && + c->check_range (&varStore, size) && + varStore.sanitize (c)); } bool serialize (hb_serialize_context_t *c, const CFF2VariationStore *varStore) @@ -384,6 +388,7 @@ struct cff2 { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + hb_barrier () && likely (version.major == 2)); } @@ -414,6 +419,7 @@ struct cff2 { /* parse top dict */ hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize); if (unlikely (!topDictStr.sanitize (&sc))) goto fail; + hb_barrier (); num_interp_env_t env (topDictStr); cff2_top_dict_interpreter_t top_interp (env); topDict.init (); @@ -430,6 +436,7 @@ struct cff2 (charStrings == &Null (CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) || (globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) || (fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) || + !hb_barrier () || (((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count))))) goto fail; @@ -446,6 +453,7 @@ struct cff2 { const hb_ubytes_t fontDictStr = (*fdArray)[i]; if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; + hb_barrier (); cff2_font_dict_values_t *font; num_interp_env_t env (fontDictStr); cff2_font_dict_interpreter_t font_interp (env); @@ -456,6 +464,7 @@ struct cff2 const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff2, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); if (unlikely (!privDictStr.sanitize (&sc))) goto fail; + hb_barrier (); cff2_priv_dict_interp_env_t env2 (privDictStr); dict_interpreter_t priv_interp (env2); privateDicts[i].init (); @@ -465,6 +474,7 @@ struct cff2 if (privateDicts[i].localSubrs != &Null (CFF2Subrs) && unlikely (!privateDicts[i].localSubrs->sanitize (&sc))) goto fail; + hb_barrier (); } return;