Description

The FKey structure represents a user action input such as a keyboard key, a mouse button/wheel, or a gesture in VR. For the keyboard, it can represent any pressable key, such as letters, numbers, symbols, arrows, functions, and even modifiers. Some of these are referred to by a friendly name, such as "Left Bracket", while others are referred to by the single TCHAR associated with the key, such as "A" or "2". Importantly, the keys that are represented by a single TCHAR include some special characters, like "~" (tilde) and "´" (accent), which are selectable in the dropdown provided by property editors. Other "single-TCHAR" special characters can also be generated by clicking the keyboard icon provided by property editors and pressing the corresponding key on the keyboard.

When FKeys are used in array/set/map containers, and a property editor needs to import the container entries from a text representation, the parse will fail when an FKey refers to some "single-TCHAR" special characters, including the "~" (tilde) and "´" (accent) keys which are directly selectable in the dropdown. For sets and maps, this will result in the entire container contents being wiped out. For arrays, all array items that would come after the problematic special character will not be imported. This can effectively cause loss of data for the engine user.

The "import from text" operation happens, for example, when the engine user pastes the contents of a container (which might have been copied from another container or even from itself), or when the container property is read from a Config file. There might be other situations where it also happens.

The problem seems to arise from the parsing performed by the following functions:

FArrayProperty::ImportTextInnerItem()
FSetProperty::ImportText_Internal()
FMapProperty::ImportText_Internal()

The functions above iterate over the textual representation of the container elements, while making sure that this representation is well-formed by checking for the appropriate parentheses and commas. This triggers the following call chain:

UScriptStruct::ImportText()
FKey::ImportTextItem()
FPropertyHelpers::ReadToken()
IsValidTokenStart()

In the problematic case, IsValidTokenStart() returns false. Then, FPropertyHelpers::ReadToken() reads a single character from the input buffer but does not advance its position by one. As a result, the container function fails to find the next comma delimiter or closing parentheses, and the parse fails.

Note: Changing the behaviors above could cause side-effects elsewhere in the engine. To avoid this possibility, the user on the linked case implemented a local fix in FMapProperty::ImportText_Internal().

Steps to Reproduce

1 - Create and edit an Actor BP named "BP_Test"
2 - Add the following container variables:
2.1 - "MyKeyArray" - An array where each element is of type "Key"
2.2 - "MyKeySet" - A set where each element is of type "Key"
2.3 - "MyKeyMap" - A map from a "Key" structure to any type
3 - Compile the BP
4 - Add some entries to the container defaults, including one entry with key ~ or ´
4.1 - Note that the keys mentioned above are directly selectable on the dropdown
4.2 - Try to have regular keys before and after the special keys. Example: A B ~ C D ´ E F
5 - Compile and save the BP
6 - For each container default, right-click and "copy" the whole container, then "paste" it over itself
6.1 - The set and map will lose all their entries and become empty. The array will lose all entries after the first special key.

--> This dropping of entries also happens when the Editor reads such values from a Config file, and any other cases where the property is imported from a text representation.

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-228883 in the post.

0
Login to Vote

Unresolved
ComponentUE - Gameplay - Input
Affects Versions5.4.4
Target Fix5.6
CreatedOct 28, 2024
UpdatedDec 6, 2024
View Jira Issue