GetPropertyText fails beyond 1024+x chars

Discussions about Coding and Scripting
Post Reply
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

GetPropertyText fails beyond 1024+x chars

Post by Barbie »

GetPropertyText() causes an UT crash if the text exceeds 1024+some more. Is there a possibility to clamp the text at - lets say 1023 characters?

Core of my test code (there is a SpecialEvent with a text of a length of 1030):

Code: Select all

if (FindActorByName('SpecialEvent0', SE)) {
	// this works:
	//TextLen = Len(SpecialEvent(SE).Message);
	// but this not:
	TextLen = Len(SE.GetPropertyText("Message"));
	BroadcastMessage(SE @ "text lenght is" @ TextLen);
}
Test map is attached (beware - it will crash your UT if you touch the Trigger.)
Attachments
TestTextLenBeyound1024.unr
It will crash your UT if you touch the Trigger.
(8.1 KiB) Downloaded 43 times
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Chris
Experienced
Posts: 134
Joined: Mon Nov 24, 2014 9:27 am

Re: GetPropertyText fails beyond 1024+x chars

Post by Chris »

The native side of UT sometimes relies on the function

Code: Select all

GetStaticString1024();
This is intended to interface a static string stack for temporary strings to avoid allocating/deallocating strings heavily due to the cost of malloc/dealloc.
It's very useful in that it saves a lot of processor time. The downside is that the blocksize is limited. Thus each string is limited to 1024 (1023 + nullterminator). In most cases it doesn't hurt to use more than 1023 in terms of risking
heap corruption because, if I recall, the stack is [512][1024], so there are 512 x 1024 * sizeof(wchar_t) (which is 2 on MSVC). So unless you're on the last row in the stack, it wont go out of bounds completely. Of course, when the function is called next time it will overwrite anything beyond 1024 and destroy the null-terminator, thus causing havoc in other ways.

Conclusion? Don't ever use strings larger than 1023, Ever!
A string that large is very rare, and would most often never be seen other than during testing. It also takes forever to process for obvious reasons.

You can clamp the text using Str = Left(Str, 1023);
It may or may not help, depends on GetPropertyText and how it handles the result.
The string itself isn't limited, but the static string stack is, thus any function that uses it together with a string larger than 1023 will cause corruption.
So don't use GetPropertyText here, use the member access operator and then clamp the message using Left().

P.S That special event should be thrown away and tucked under something that will never see daylight again. :loool:
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: GetPropertyText fails beyond 1024+x chars

Post by Higor »

It uses a local stack buffer, and they knew exactly what they were doing (check the //!! comment)

Code: Select all

void UObject::execGetPropertyText( FFrame& Stack, RESULT_DECL )
{
	P_GET_STR(PropName);
	P_FINISH;

	UProperty* Property=FindField<UProperty>( Class, *PropName );
	if( Property && (Property->GetFlags() & RF_Public) )
	{
		TCHAR Temp[1024]=TEXT("");//!!
		Property->ExportText( 0, Temp, (BYTE*)this, (BYTE*)this, PPF_Localized );
		*(FString*)Result = Temp;
	}
	else *(FString*)Result = TEXT("");
}
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: GetPropertyText fails beyond 1024+x chars

Post by Barbie »

I run into this on the attempt to patch a map on loading: Because the Translator does not work in UT I wanted to add a Trigger/SpecialEvent at every TranslatorEvent, copy the properties, and display the message if a player touches the Trigger. Unfortunately the mapper has used a custom version of TranslatorEvent and did it not as a sub class of TranslatorEvent. So I had to read the message via "GetPropertyText()".

It seems there will be no way to do that via UScript...
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Chris
Experienced
Posts: 134
Joined: Mon Nov 24, 2014 9:27 am

Re: GetPropertyText fails beyond 1024+x chars

Post by Chris »

Higor wrote:It uses a local stack buffer, and they knew exactly what they were doing (check the //!! comment)

Code: Select all

void UObject::execGetPropertyText( FFrame& Stack, RESULT_DECL )
{
	P_GET_STR(PropName);
	P_FINISH;

	UProperty* Property=FindField<UProperty>( Class, *PropName );
	if( Property && (Property->GetFlags() & RF_Public) )
	{
		TCHAR Temp[1024]=TEXT("");//!!
		Property->ExportText( 0, Temp, (BYTE*)this, (BYTE*)this, PPF_Localized );
		*(FString*)Result = Temp;
	}
	else *(FString*)Result = TEXT("");
}
They may have known what they were doing, yet they failed to make sure a stack corruption would never occur. It could easily have been avoided by not writing outside the buffer.
Post Reply