mirror of
https://github.com/Redot-Engine/redot-engine.git
synced 2025-12-06 07:17:42 -05:00
Core ubsan fixes
This fixes UBSAN errors reported by running our testsuite, importing the TPS demo, and running the TPS demo. I have tried, wherever possible, to fix issues related to reported issues but not directly reported by UBSAN because thse code paths just happened to not have been exercised in these cases. These fixes apply only to errors reported, and caused by, core/ The following things have been changed: * Make sure there are no implicit sign changing casts in core. * Explicitly type enums that are part of a public API such that users of the API cannot pass in wrongly-sized values leading to potential stack corruption. * Ensure that memcpy is never called with invalid or null pointers as this is undefined behavior, and when the engine is built with optimizations turned on leads to memory corruption and hard to debug crashes. * Replace enum values only used as static values with constexpr static const values instead. This has no runtime overhead. This makes it so that the size of the enums is explicit. * Make sure that nan and inf is handled consistently in String. * Implement a _to_int template to ensure that all of the paths use the same algorhithm, and correct the negative integer case. * Changed the way the json serializer precision work, and added tests to verify the new behavior. The behavior doesn't quite match master in particulary for negative doubles as the original code tried to cast -inf to an int. This then led to negative doubles losing all but one of their decimal points when serializing. Behavior in GDScript remains unchanged.
This commit is contained in:
@@ -339,7 +339,9 @@ class CommandQueueMT {
|
||||
template <typename T>
|
||||
T *allocate() {
|
||||
// alloc size is size+T+safeguard
|
||||
uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1));
|
||||
static_assert(sizeof(T) < UINT32_MAX, "Type too large to fit in the command queue.");
|
||||
|
||||
uint32_t alloc_size = ((sizeof(T) + 8U - 1U) & ~(8U - 1U));
|
||||
uint64_t size = command_mem.size();
|
||||
command_mem.resize(size + alloc_size + 8);
|
||||
*(uint64_t *)&command_mem[size] = alloc_size;
|
||||
|
||||
@@ -323,9 +323,9 @@ struct HashMapHasherDefault {
|
||||
|
||||
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(p_wchar); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(uint32_t(p_wchar)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.get_data()); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
|
||||
@@ -333,31 +333,31 @@ struct HashMapHasherDefault {
|
||||
static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
|
||||
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(uint64_t(p_int)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_murmur3_one_float(p_float); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_murmur3_one_double(p_double); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return hash_fmix32(p_int); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(p_int); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(p_int); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(p_int); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(p_int); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(p_int); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(uint32_t(p_int)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(uint32_t(p_int)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(uint32_t(p_int)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(uint32_t(p_int)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(uint32_t(p_int)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) {
|
||||
uint32_t h = hash_murmur3_one_32(p_vec.x);
|
||||
h = hash_murmur3_one_32(p_vec.y, h);
|
||||
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
|
||||
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) {
|
||||
uint32_t h = hash_murmur3_one_32(p_vec.x);
|
||||
h = hash_murmur3_one_32(p_vec.y, h);
|
||||
h = hash_murmur3_one_32(p_vec.z, h);
|
||||
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
|
||||
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
|
||||
h = hash_murmur3_one_32(uint32_t(p_vec.z), h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
static _FORCE_INLINE_ uint32_t hash(const Vector4i &p_vec) {
|
||||
uint32_t h = hash_murmur3_one_32(p_vec.x);
|
||||
h = hash_murmur3_one_32(p_vec.y, h);
|
||||
h = hash_murmur3_one_32(p_vec.z, h);
|
||||
h = hash_murmur3_one_32(p_vec.w, h);
|
||||
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
|
||||
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
|
||||
h = hash_murmur3_one_32(uint32_t(p_vec.z), h);
|
||||
h = hash_murmur3_one_32(uint32_t(p_vec.w), h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) {
|
||||
@@ -379,10 +379,10 @@ struct HashMapHasherDefault {
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) {
|
||||
uint32_t h = hash_murmur3_one_32(p_rect.position.x);
|
||||
h = hash_murmur3_one_32(p_rect.position.y, h);
|
||||
h = hash_murmur3_one_32(p_rect.size.x, h);
|
||||
h = hash_murmur3_one_32(p_rect.size.y, h);
|
||||
uint32_t h = hash_murmur3_one_32(uint32_t(p_rect.position.x));
|
||||
h = hash_murmur3_one_32(uint32_t(p_rect.position.y), h);
|
||||
h = hash_murmur3_one_32(uint32_t(p_rect.size.x), h);
|
||||
h = hash_murmur3_one_32(uint32_t(p_rect.size.y), h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) {
|
||||
|
||||
@@ -297,7 +297,9 @@ public:
|
||||
Vector<T> ret;
|
||||
ret.resize(size());
|
||||
T *w = ret.ptrw();
|
||||
memcpy(w, data, sizeof(T) * count);
|
||||
if (w) {
|
||||
memcpy(w, data, sizeof(T) * count);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -305,7 +307,9 @@ public:
|
||||
Vector<uint8_t> ret;
|
||||
ret.resize(count * sizeof(T));
|
||||
uint8_t *w = ret.ptrw();
|
||||
memcpy(w, data, sizeof(T) * count);
|
||||
if (w) {
|
||||
memcpy(w, data, sizeof(T) * count);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,8 +156,11 @@ public:
|
||||
if (is_empty()) {
|
||||
return ret;
|
||||
}
|
||||
ret.resize(size() * sizeof(T));
|
||||
memcpy(ret.ptrw(), ptr(), sizeof(T) * size());
|
||||
size_t alloc_size = size() * sizeof(T);
|
||||
ret.resize(alloc_size);
|
||||
if (alloc_size) {
|
||||
memcpy(ret.ptrw(), ptr(), alloc_size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user