Merge pull request #2067 from harfbuzz/null-size

Avoid undefined-behavior, another try
This commit is contained in:
Behdad Esfahbod 2021-04-16 14:35:04 -06:00 committed by GitHub
commit 19e096aa97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 5 deletions

View File

@ -219,7 +219,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
unsigned P = sizeof (Type),
hb_enable_if (P == 1)>
const T *as () const
{ return length < hb_null_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
{ return length < hb_min_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
template <typename T,
unsigned P = sizeof (Type),

View File

@ -39,8 +39,11 @@
#define HB_NULL_POOL_SIZE 384
/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
* otherwise return sizeof(T). */
/* Use SFINAE to sniff whether T has min_size; in which case return the larger
* of sizeof(T) and T::null_size, otherwise return sizeof(T).
*
* The main purpose of this is to let structs communicate that they are not nullable,
* by defining min_size but *not* null_size. */
/* The hard way...
* https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
@ -49,8 +52,9 @@
template <typename T, typename>
struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
template <typename T>
struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::null_size> {};
struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>>
: hb_integral_constant<unsigned,
(sizeof (T) > T::null_size ? sizeof (T) : T::null_size)> {};
template <typename T>
using hb_null_size = _hb_null_size<T, void>;
#define hb_null_size(T) hb_null_size<T>::value
@ -68,6 +72,14 @@ template <typename T>
using hb_static_size = _hb_static_size<T, void>;
#define hb_static_size(T) hb_static_size<T>::value
template <typename T, typename>
struct _hb_min_size : hb_integral_constant<unsigned, sizeof (T)> {};
template <typename T>
struct _hb_min_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::min_size> {};
template <typename T>
using hb_min_size = _hb_min_size<T, void>;
#define hb_min_size(T) hb_min_size<T>::value
/*
* Null()