summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSai Nane <esainane+git@gmail.com>2024-08-09 05:05:36 +0000
committerSai Nane <esainane+git@gmail.com>2024-08-09 05:15:54 +0000
commite6a7c63125fcff9710899b8e72a990517639fb8d (patch)
tree72bcde8584c14f32b3a31f84e37249575754a036
parent739019e4e4a6e4763e37adfd9883a1c85d5f6249 (diff)
downloadredot-engine-e6a7c63125fcff9710899b8e72a990517639fb8d.tar.gz
binder_common: Fix uninitialized marshalling
C# uses `long`s to access many native values. With `PtrToArg<m_enum>` and `PtrToArg<bitfield<m_enum>>` this isn't a problem, as C++ code converts through a `*(int64_t*)` cast in assignment, so all 64-bits are initialized. However, with `PtrToArg<char32_t>`, value assignment happens through an `*(int *)` cast, leaving 32 bits uninitialized where `int` is 32 bits. On platforms where `int` is 16 bits, there are presumably 48 bits uninitialized, though there are very few platforms where this is still the case. The easiest way to see the practical effects of this is by looking at `EventInputKey.Unicode`: ```csharp public override void _Input(InputEvent @event) { if (@event is InputEventKey keyEvent) { if (keyEvent.IsPressed() && !keyEvent.Echo) { var raw = keyEvent.Unicode; var value = raw & 0xffffffff; GD.Print($"Key pressed: raw: {raw}; masked: {(char) value} ({value})"); } } } ``` Pressing 'a' emits the following line: ``` Key pressed: raw: -3617008645356650399; masked: a (97) ``` Examining execution flow in gdb shows this conversion going through the following line: ``` PtrToArg<char32_t>::encode (p_ptr=0x7ffcd5bb4b18, p_val=97 U'a') at ./core/variant/binder_common.h:221 221 *(int *)p_ptr = p_val; ``` Here, `p_val` is still 97, which is the value `InputEventKey.Unicode` is expected to have. After assignment, `p *(int64_t *)0x7ffcd5bb4b18` displays `-3617008645356650399`, with only the lower 32 bits being properly assigned, and is the value we see from C#. With this patch applied, the above testing `_Input` now prints: ``` Key pressed: raw: 97; masked: a (97) ``` Thank you to blujay1269 for asking about an unexpected value they saw in `EventInputKey.Unicode`, which prompted this investigation.
-rw-r--r--core/variant/binder_common.h4
1 files changed, 2 insertions, 2 deletions
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 61b90e2a26..fa49767d46 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -214,11 +214,11 @@ struct VariantCaster<char32_t> {
template <>
struct PtrToArg<char32_t> {
_FORCE_INLINE_ static char32_t convert(const void *p_ptr) {
- return char32_t(*reinterpret_cast<const int *>(p_ptr));
+ return char32_t(*reinterpret_cast<const int64_t *>(p_ptr));
}
typedef int64_t EncodeT;
_FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) {
- *(int *)p_ptr = p_val;
+ *(int64_t *)p_ptr = p_val;
}
};