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.
This commit is contained in:
Behdad Esfahbod 2018-11-16 16:41:59 -08:00
parent 6910ff03e6
commit 52f61cdb87
1 changed files with 16 additions and 5 deletions

View File

@ -339,16 +339,27 @@ struct UnsizedArrayOf
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type); HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
/* Unlikely other places, use "int i" instead of "unsigned int i" for our /* Unlikely other places, use "ssize_t i" instead of "unsigned int i" for our
* indexing operator. For two reasons: * indexing operator. For three reasons:
* 1. For UnsizedArrayOf, it's not totally unimaginable to want to look * 1. For UnsizedArrayOf, it's not totally unimaginable to want to look
* at items before the start of current array. * 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])). * 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 * I suppose I could fix that by replacing 0 with 0u, but like this fix
* more now. */ * more now. */
inline const Type& operator [] (int i) const { return arrayZ[i]; } inline const Type& operator [] (ssize_t i) const
inline Type& operator [] (int i) { return arrayZ[i]; } {
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 T * (void) { return arrayZ; }
template <typename T> inline operator const T * (void) const { return arrayZ; } template <typename T> inline operator const T * (void) const { return arrayZ; }