C#’s inheritance and versioning model can be easily sabotaged by a third-party class. The code in this page is included to aid understanding of the sabotage process, and is not an implementation of the process itself.
Suppose a base class, BaseClass, has three methods MethodToOverrideA and MethodToOverrideB, both of which are virtual, and UseMethodsToOverride, which calls the other two methods:
public class BaseClass{
public virtual void MethodToOverrideA(){
System.Console.WriteLine("BaseClass.MethodToOverrideA()");
}
public virtual void MethodToOverrideB(){
System.Console.WriteLine("BaseClass.MethodToOverrideB()");
}
public void UseMethodsToOverride(){
System.Console.WriteLine("BaseClass.UseMethodsToOverride()");
MethodToOverrideA();
MethodToOverrideB();
}
}
A third-party class, ThirdPartyClass, adds a useful new method MethodClientFindsUseful:
public class ThirdPartyClass: BaseClass{
public virtual void MethodClientFindsUseful(){
System.Console.WriteLine("ThirdPartyClass.MethodClientFindsUseful()");
}
}
A client class, ClientClass, inherits from ThirdPartyClass in order to be able to use the method MethodClientFindsUseful, and also overrides the methods MethodToOverrideA and MethodToOverrideB:
public class ClientClass: ThirdPartyClass{
public override void MethodToOverrideA(){
System.Console.WriteLine("ClientClass.MethodToOverrideA()");
}
public override void MethodToOverrideB(){
System.Console.WriteLine("ClientClass.MethodToOverrideB()");
base.MethodToOverrideB();
}
}
In one method it calls the base method to use the functionality of the original class.
Now the third party releases a new version of the DLL their class, claiming that it fixes a bug.
Administrators install it without examining it using a disassembler, unaware that the new version includes methods MethodToOverrideA and MethodToOverrideB:
public class ThirdPartyClass: BaseClass{
public virtual new void MethodToOverrideA(){
System.Console.WriteLine("ThirdPartyClass.MethodToOverrideA()");
}
public override void MethodToOverrideB(){
System.Console.WriteLine("ThirdPartyClass.MethodToOverrideB()");
base.MethodToOverrideB();
}
public virtual void MethodClientFindsUseful(){
System.Console.WriteLine("ThirdPartyClass.MethodClientFindsUseful()");
}
}
The result of calling UseMethodsToOverride is no longer the expected:
BaseClass.UseMethodsToOverride()
ClientClass.MethodToOverrideA()
ClientClass.MethodToOverrideB()
BaseClass.MethodToOverrideB()
Now the call results in:
BaseClass.UseMethodsToOverride()
BaseClass.MethodToOverrideA()
ClientClass.MethodToOverrideB()
ThirdPartyClass.MethodToOverrideB()
BaseClass.MethodToOverrideB()
The sabotaged version of MethodToOverrideA effectively erases the version of MethodToOverrideA in the client class.
The sabotaged version of MethodToOverrideB only has an effect if the client class calls the base method, but it is much more powerful.
By intercepting the call to the base method, the third-party class can perform much more subtle sabotage. For example, it could pass on the data to the base class (giving the result the client expects) while recording it for later retrieval. Alternatively, if it just aimed to cause disruption it could randomly change the data being passed on one time in a thousand — infrequently enough to avoid immediate detection.