In TechEd Israel 2006, I listened to Roy Osherove‘s excellent talk on the new reflection features in .NET 2.0 – a great assortment of topics on things ranging from DynamicMethods to the ReflectionOnly- set of properties.
One of the things he mentioned was that the GetCustomAttributes method that’s exposed by various reflection types was unsafe. When the method returns the collection of custom attributes, it has to instantiate each one of them, and this means calling the constructor on each one of them. This could be the “crack in the door” for an attacker to use an extensible plug-in architecture to slide his own code by inheriting a custom atttribute with malicious constructor code and decorating a class with it.
The solution in .NET 2.0 comes from the CustomAttributeData class, which has a single static method – GetCustomAttributes – which returns the list of attributes without calling their constructors. This seems a cleaner and safer solution, and I couldn’t wait to go and fix up my reflection code in the current project with it.
The problem with this implementation, as always, is in the little details. The GetCustomAttributes method we have on the reflection types are implemented via the ICustomAttributeProvider interface, which is implemented by Type, ParameterInfo, MethodInfo and all those other attribute-supporting constructs. The GetCustomAttribute method of the CustomAttributeData class, though, has several overloads taking MemberInfos, Assemblys, ParameterInfo or Module – the four classes that implement ICustomAttributeProvider. This means that while it is theoretically equivalent to the older method, it does not allow me to cast my member/type/assembly to an ICustomAttributeProvider and perform operations on it – I have several attribute-related functions that take either a Type or a Property, so in this case I can cast them both to MemberInfos and use that as my lowest common denominator. But what if I had needed to handle Assemblies as well?
A rather annoying ommision. Whenever I’m forced to use concrete classes rather than base-classes or interfaces, I get slightly nervous. It may be fine for the time being, but I know that somewhere down the line, I’ll try to refactor something and get bitten.
EDIT: searching Google, it seems that I am the very first to use the “Reflection.Omit” pun, or at least to publish it on a Googleable medium. Cool.