-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Strict enum value checking #1231
Comments
The implementation could be something along the lines of this (not working, but for showing the idea) public static class EnumHelper
{
public static T StrictEnumFrom<T>(int value) where T : Enum
{
T state = (T)value;
if (!EnumValueCache<T>.DefinedValues.Contains(state))
throw new FormatException();
return state;
}
private static class EnumValueCache<T> where T : Enum
{
public static readonly HashSet<T> DefinedValues = new HashSet<T>((T[])Enum.GetValues(typeof(T)));
}
}
|
I like it, only when the enum is not a flag. |
Sometimes we do this check neo/neo/Network/P2P/Payloads/InvPayload.cs Lines 39 to 41 in af85f3c
|
It is great that we at least do it sometimes, but I hope we can get to some coding rule where we say "Every non-flag enum in NEO should be strict" and then to make it easy have some helper function to take care of it. @shargon is there any reason why we couldn't make an equivalent helper for neo/neo/SmartContract/InteropService.cs Line 576 in f1d6434
PS: If you happen to know a solution for |
If is fast, we can do it.. otherwise what could be the problem with flag, every time you will check the expected flag, so if is not included you won't do anything |
Could you create the PR for see easy your problem? |
I guess the only benefit would be saving computational resources by aborting VM execution on invalid data.
I can't really create a PR yet because the helper function doesn't work (see the last 2 lines of #1231 (comment)) if (!Enum.IsDefined(typeof(object_type), Type))
throw new FormatException(); to all locations that are not using it but should. |
Try with public static class EnumHelper
{
public static T StrictEnumFrom<T>(int value) where T : Enum
{
T state = (T)Enum.ToObject(typeof(T), value);
if (!EnumValueCache<T>.DefinedValues.Contains(state))
throw new FormatException();
return state;
}
public static T StrictEnumFrom<T>(byte value) where T : Enum
{
T state = (T)Enum.ToObject(typeof(T), value);
if (!EnumValueCache<T>.DefinedValues.Contains(state))
throw new FormatException();
return state;
}
private static class EnumValueCache<T> where T : Enum
{
public static readonly HashSet<T> DefinedValues = new HashSet<T>((T[])Enum.GetValues(typeof(T)));
}
} |
Please do some benchmarks with |
Don't mind my C# benchmark skills 😅 private static void func1(int i)
{
VMState state = EnumHelper.StrictFrom<VMState>(i);
}
private static void func2(int i)
{
VMState value = (VMState)i;
if (!Enum.IsDefined(typeof(VMState), value))
throw new FormatException();
} var watch = new Stopwatch();
List<int> indice = new List<int> { 0, 1, 2, 4 };
// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
watch.Start();
for (int i = 0; i < 5000; i++)
{
func2(indice[i%4]);
}
watch.Stop();
Console.WriteLine(" Time Elapsed {0} ms", watch.Elapsed.TotalMilliseconds); 3 runs of the above code |
Any update @ixje ? |
I'll try to PR this week. First have to finish some other task. |
@shargon I wanted to implement it in NEO but I'm getting the error:
So this means the whole NEO project needs to be upgraded to use C# language version 7.3 or greater. This sounds like a big change, so before I continue I'd like to hear if that is acceptable. |
In master we are using the preview version... it's weird Line 20 in 8ccc5e9
|
Summary
Enum's in C# are not strict when it comes to casting. e.g.
This can lead to various issues or performance degradation;
ContractParameterType
(I'm running neo-cli (2.7.4.0) and ApplicationLogs are not created! #228). The impact for this specific case was low but could be worse.Do you have any solution you want to propose?
I'd like to suggest we create some helper method that does strict Enum value checking and throws an exception if it is out of bounds.
So the above could look something like
Where in the software does this update applies to?
Everywhere
I'm interested to hear thoughts on the idea
The text was updated successfully, but these errors were encountered: