summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2018-11-16 16:41:59 -0800
committerBehdad Esfahbod <behdad@behdad.org>2018-11-16 16:41:59 -0800
commit52f61cdb87b67ef42a25288d8624170d0b6d3a25 (patch)
tree3737e4e9234c6880441d934cb7ccf25e5c6866d0
parent6910ff03e66f5f4c9eb5592262d414ef7d91df04 (diff)
Detect over/under-flow in UnsizedArray::operator[]
Was causing bad substitutions in mort table because of WordOffsetToIndex() producing negative numbers that were cast to unsigned int and returned as large numbers (which was desirable, so they would be rejected), but then they were cast to int when passed to this operator and acting as small negative integers, which was bad... Detect overflow. Ouch, however, now I see this still fails on 32-bit. Guess I'm going to revert an earlier change.
-rw-r--r--src/hb-open-type.hh21
1 files changed, 16 insertions, 5 deletions
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index a14d0f02..bae73da4 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -339,16 +339,27 @@ struct UnsizedArrayOf
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
- /* Unlikely other places, use "int i" instead of "unsigned int i" for our
- * indexing operator. For two reasons:
+ /* Unlikely other places, use "ssize_t i" instead of "unsigned int i" for our
+ * indexing operator. For three reasons:
* 1. For UnsizedArrayOf, it's not totally unimaginable to want to look
* at items before the start of current array.
- * 2. Fixes MSVC 2008 "overloads have similar conversions" issue with the
+ * 2. Use the largest type, to help detect overflows.
+ * 3. Fixes MSVC 2008 "overloads have similar conversions" issue with the
* built-in operator [] that takes int, in expressions like sizeof (array[0])).
* I suppose I could fix that by replacing 0 with 0u, but like this fix
* more now. */
- inline const Type& operator [] (int i) const { return arrayZ[i]; }
- inline Type& operator [] (int i) { return arrayZ[i]; }
+ inline const Type& operator [] (ssize_t i) const
+ {
+ const Type *p = &arrayZ[i];
+ if (unlikely ((0 <= i) != (arrayZ <= p))) return Null (Type); /* Over/under-flowed. */
+ return *p;
+ }
+ inline Type& operator [] (ssize_t i)
+ {
+ const Type *p = &arrayZ[i];
+ if (unlikely ((0 <= i) != (arrayZ <= p))) return Crap (Type); /* Over/under-flowed. */
+ return *p;
+ }
template <typename T> inline operator T * (void) { return arrayZ; }
template <typename T> inline operator const T * (void) const { return arrayZ; }