Harden UE Wingman request handling and numeric property conversion.
Switch the Wingman protocol to null-delimited JSON, rework the server's socket buffering and send logic, and document the bugs found during the review. Also refactor WingProperty's numeric setters into clearer helper paths while preserving the existing conversion rules.
This commit is contained in:
@@ -46,52 +46,61 @@ bool FWingProperty::SetObject(UObject *Obj, WingOut Errors) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FWingProperty::SetDoubleInternal(
|
||||
FNumericProperty *NProp, void *Container, double D, WingOut Errors)
|
||||
{
|
||||
uint8 buffer[16];
|
||||
NProp->SetFloatingPointPropertyValue(buffer, D);
|
||||
if (!FMath::IsFinite(NProp->GetFloatingPointPropertyValue(buffer)))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lf\n"),
|
||||
*WingUtils::FormatName(NProp), *NProp->GetCPPType(), D);
|
||||
return false;
|
||||
}
|
||||
NProp->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FWingProperty::SetInt64Internal(
|
||||
FNumericProperty *NProp, void *Container, int64 I, WingOut Errors)
|
||||
{
|
||||
uint8 buffer[16];
|
||||
if ((I < 0) && IsUnsigned(NProp))
|
||||
{
|
||||
Errors.Printf(TEXT(
|
||||
"ERROR: Cannot store signed %lld in unsigned property %s\n"),
|
||||
I, *WingUtils::FormatName(NProp));
|
||||
return false;
|
||||
}
|
||||
NProp->SetIntPropertyValue(buffer, I);
|
||||
if (NProp->GetSignedIntPropertyValue(buffer) != I)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(NProp), *NProp->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
NProp->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FWingProperty::SetDouble(double D, WingOut Errors) const
|
||||
{
|
||||
if (!CheckEditable(Errors)) return false;
|
||||
FNumericProperty *NProp = CastField<FNumericProperty>(Prop);
|
||||
if (!NProp)
|
||||
if (NProp == nullptr)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("double"), Errors);
|
||||
return false;
|
||||
}
|
||||
if (NProp->IsFloatingPoint())
|
||||
else if (NProp->IsFloatingPoint())
|
||||
{
|
||||
uint8 buffer[16];
|
||||
NProp->SetFloatingPointPropertyValue(buffer, D);
|
||||
if (!FMath::IsFinite(NProp->GetFloatingPointPropertyValue(buffer)))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lf\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), D);
|
||||
return false;
|
||||
}
|
||||
Prop->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
return SetDoubleInternal(NProp, Container, D, Errors);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 buffer[16];
|
||||
if (FMath::Floor(D) != D)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("double"), Errors);
|
||||
return false;
|
||||
}
|
||||
if (FMath::Abs(D) > (double)((1LL)<<53))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: To store very large numbers in '%s', do not pass them as double. Use string or int.\n"),
|
||||
*WingUtils::FormatName(Prop));
|
||||
return false;
|
||||
}
|
||||
int64 I = (int64)D;
|
||||
NProp->SetIntPropertyValue(buffer, I);
|
||||
if (NProp->GetSignedIntPropertyValue(buffer) != I)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
NProp->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
int64 I;
|
||||
if (!LosslessDoubleToInt64(D, I, Errors)) return false;
|
||||
return SetInt64Internal(NProp, Container, I, Errors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,38 +108,20 @@ bool FWingProperty::SetInt64(int64 I, WingOut Errors) const
|
||||
{
|
||||
if (!CheckEditable(Errors)) return false;
|
||||
FNumericProperty *NProp = CastField<FNumericProperty>(Prop);
|
||||
if (!NProp)
|
||||
if (NProp == nullptr)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("int"), Errors);
|
||||
return false;
|
||||
}
|
||||
if (NProp->IsFloatingPoint())
|
||||
else if (NProp->IsFloatingPoint())
|
||||
{
|
||||
uint8 buffer[16];
|
||||
double D = I;
|
||||
NProp->SetFloatingPointPropertyValue(buffer, D);
|
||||
int64 RT = (int64)NProp->GetFloatingPointPropertyValue(buffer);
|
||||
if (RT != I)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
Prop->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
double D;
|
||||
if (!LosslessInt64ToDouble(I, D, Errors)) return false;
|
||||
return SetDoubleInternal(NProp, Container, D, Errors);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 buffer[16];
|
||||
NProp->SetIntPropertyValue(buffer, I);
|
||||
if (NProp->GetSignedIntPropertyValue(buffer) != I)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
NProp->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
return SetInt64Internal(NProp, Container, I, Errors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,4 +588,43 @@ bool FWingProperty::CheckEditable(WingOut Errors) const
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FWingProperty::IsUnsigned(FNumericProperty* Prop)
|
||||
{
|
||||
return
|
||||
CastField<FByteProperty>(Prop) ||
|
||||
CastField<FUInt16Property>(Prop) ||
|
||||
CastField<FUInt32Property>(Prop) ||
|
||||
CastField<FUInt64Property>(Prop);
|
||||
}
|
||||
|
||||
bool FWingProperty::LosslessDoubleToInt64(double D, int64 &I, WingOut Errors)
|
||||
{
|
||||
if (FMath::Floor(D) != D)
|
||||
{
|
||||
Errors.Printf(TEXT(
|
||||
"ERROR: Converting double %.4lf to integer would lose precision\n"), D);
|
||||
return false;
|
||||
}
|
||||
if (FMath::Abs(D) > (double)((1LL)<<53))
|
||||
{
|
||||
Errors.Printf(TEXT(
|
||||
"ERROR: Converting huge double %lf to integer would lose data.\n"), D);
|
||||
return false;
|
||||
}
|
||||
I = (int64)D;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FWingProperty::LosslessInt64ToDouble(int64 I, double &D, WingOut Errors)
|
||||
{
|
||||
D = (double)I;
|
||||
if ((int64)D != I)
|
||||
{
|
||||
Errors.Printf(TEXT(
|
||||
"ERROR: Converting huge integer %lld to floating point would lose data.\n"), I);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user