-
-
Notifications
You must be signed in to change notification settings - Fork 218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Array<T>
can hold values that are invalid representations of T
#805
Comments
Inside Godot, do If the only advantage between |
Yes, all arrays use
Not sure what exactly you mean, but
That's an option, but we also support these integer types in other places: parameters and return types of |
i think we should go for option 1 for a couple of reasons i think builtin types should match types that godot can represent. this is likely what people will assume anyway. with integer/float types there's a bit more leeway since those are rust types that we map to godot types, but even there godot does in fact have some cases where it tracks the different types. runtime type checking should ideally be cheap imo, constant time preferably. this is doable with with rust collections, you generally do have the property that any value stored in the collection will be a value of that type. so for i also think option 3 isn't something we can really hope to support. it'd make our arrays so much more complicated to deal with from a development and maintenance perspective. finally, people can always just make their own newtype array if they really need it for other types. both 2 and 4 should be doable with that. |
Here's the upstream PR that adds validates integer element types at runtime: godotengine/godot#95492 And here the local one: #855 |
Problem
Array<T>
andArray<U>
are indirectly convertible, viaVariant
.Integer conversions
They are even equal if
T
andU
map to the same variant type, like integers:However, this can be exploited to craft arrays with values that are not valid for the static element types.
Class casting
I have not tested yet if a similar issue exists with subclassing, i.e.
Array<Gd<T>>
andArray<Gd<U>>
. Although this is probably more rigorously checked, since we have access to the class name as part of the array type -- whereas the exact integer type is lost, it's justVariantType::INT
.Note that "array upcasting" is not safe, because arrays aren't covariant. If we allow converting
Array<Gd<Node3D>>
toArray<Gd<Node>>
, then someone could attempt to store differentNode
types in theNode3D
array.Possible solutions
One option is to limit
ArrayElement
to the canonical type, which matches the Godot representation (i.e.i64
for integers). This would then only allow 1 type perVariantType
(except for objects), but it would be more explicit.We could iterate through each element and check if conversion is possible. This can be expensive, but we could do it a bit smarter:
ArrayElement
types mapping to the sameVariantType
(e.g. integers)i64
will always succeed)This would mean we would still allow non-canonical
Array<T>
usages, however with a slight performance hit. People who care about this could then fall back to the canonical types.A complex system tracing arrays-in-variants via global metadata (then e.g.
i16
->i32
would be safe). It's not really something I'd like to get into though, as it has a million backdoors and edge cases, and I don't even know if it's possible to identify arrays in GDExtension.We accept the lowered type safety and resort to panics when accessing elements.
Variant
conversions are quite robust so they should catch these cases, but it's still not very nice to postpone/hide such logic errors.The text was updated successfully, but these errors were encountered: