Avoid undefined-behavior
If a struct had (because it's a union) sizeof that is larger than the null_size, we were providing only null_size bytes for its Null object. We know we'd never access beyond that, but is undefined-behavior nonetheless according to the standard. The alternative fix would have required use of flexible-arrays, which are not standard and have their own issues in various compiler. We've discussed that extensively in the follow Mozilla issue (currently locked; I've asked that it be opened): https://bugzilla.mozilla.org/show_bug.cgi?id=1577584 Part of https://github.com/harfbuzz/harfbuzz/pull/2067
This commit is contained in:
parent
499248c533
commit
23a28f5ad0
|
@ -39,8 +39,11 @@
|
||||||
|
|
||||||
#define HB_NULL_POOL_SIZE 384
|
#define HB_NULL_POOL_SIZE 384
|
||||||
|
|
||||||
/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
|
/* Use SFINAE to sniff whether T has min_size; in which case return the larger
|
||||||
* otherwise return sizeof(T). */
|
* 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...
|
/* The hard way...
|
||||||
* https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
|
* https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
|
||||||
|
@ -49,7 +52,9 @@
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
|
struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
|
||||||
template <typename 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>
|
template <typename T>
|
||||||
using hb_null_size = _hb_null_size<T, void>;
|
using hb_null_size = _hb_null_size<T, void>;
|
||||||
#define hb_null_size(T) hb_null_size<T>::value
|
#define hb_null_size(T) hb_null_size<T>::value
|
||||||
|
|
Loading…
Reference in New Issue