Breaking the Singleton Design Pattern

A little more about reflection: Another post in my blog
More about singleton: Wikipedia: Singleton pattern

This semester, I have taken part in a course in Master program at HCMUT. Recently, the lecturer is disappointed because the number of students attending the class is so low. So I went to class this morning.

The lecture was about design patterns. At the moment I entered the room, the lecturer demonstrated Singleton patterns and the content was quite simple. When he said that the constructor of the class must be non public so that the outside world wouldn't be able to instantiate a new instance of that class, the first thing came into my mind: REFLECTION. What if there is a man in the outside world, try attacking the principle of singleton by reflection.

The lecturer prefers C# and by chance, I am working with that language, so I will use it as the language of all code in this entry. Also, in this entry, I will play 2 roles: the man trying attacking singleton pattern and the man maintaining the correctness of the pattern.

I prepared a Double-Check Locking implementation of Singleton Pattern. You can find the original from here on Microsoft website. All I did was renaming the class into Girlfriend.

    public sealed class Girlfriend
    {
        private static volatile Girlfriend instance;
        private static object syncRoot = new Object();

        private Girlfriend() {}

        public static Girlfriend Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new Girlfriend();
                    }
                }

                return instance;
            }
        }
    }
Figure 1 - Original Singleton implementation

You see, you may not have a girlfriend, or if you have, you have only one at a time.

Round 1 - Reflection v1 vs Singleton v1

My role here is the attacker.
Firstly, I get an instance of Girlfriend for comparing later. I also prepare a place for another girl.

Girlfriend gf1 = Girlfriend.Instance;
Girlfriend gf2 = null;

Secondly, I write a comparing method. And here is the sub-program that will show the comparation result between girls.

void ShowComparation(string, title, Girlfriend gf1, Girlfriend gf2)
{
    Console.WriteLine(title);
    Console.WriteLine("Gf1 is null = " + (gf1 == null));
    Console.WriteLine("Gf2 is null = " + (gf2 == null));
    Console.WriteLine("Gf1 is Gf2 = " + (gf1 == gf2));
    Console.ReadLine();
}
Figure 2 - Comparing method

Then, I analyze the code, which is available on the internet. I know that the constructor is set private, so I can not simply call it for creating another Girlfriend instance.
Reflection technique may help in this situation, here what I do: get the constructor, then invoke it.

Type type = typeof(Girlfriend);
if (type != null)
{
    ConstructorInfo ci = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
    if (ci != null)
    {
        try {
            gf2 = (Girlfriend)ci.Invoke(null);
        } catch {}
    }
}


Lastly, I call the comparing method to observe the result:

I got 2 girls and they are different. The singleton pattern implementation goes wrong.
Reflection 1 - 0 Singleton

Round 2 - Singleton v2 vs Reflection v1

My role here is the defender.
Because my current implementation goes wrong when someone invoked my private constructor successfully, I will set up a condition there.
The constructor now has to check if the instance is created. If it exists, the constructor must throw an exception to interrupt the initiating of a new object.
Here is the new constructor.

        private Girlfriend()
        {
            if (instance != null)
            {
                throw new Exception("Can not have 2 girldfriends at the same time");
            }
        }
Replace the one constructor by the new one, I have the modified Double-Check Locking implementation of Singleton pattern:
    public sealed class Girlfriend
    {
        private static volatile Girlfriend instance;
        private static object syncRoot = new Object();

        private Girlfriend() 
        {
            if (instance != null)
            {
                throw new Exception("Can not have 2 girldfriends at the same time");
            }
        }

        public static Girlfriend Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new Girlfriend();
                    }
                }

                return instance;
            }
        }
    }
Figure 3 - Modified Singleton implementation

Ok, let the attacker run his code again and wait for the result:

He got only 1 girlfriend who is gf1 and gf2 is not available for him now.
Reflection 1 - 1 Singleton

Round 3 - Reflection v2 vs Singleton v2 

I am the attacker again.
By a little debugging, I recognize that when I invoke the constructor of Girlfriend class, an exception thrown preventing me create my second Girlfriend object.
Logically, I think that the defender changed code inside the constructor to throw an exception whenever a Girlfriend instance exists.
Or, I don't have to think, I just use decompiler to read the modified in code.
I think of a strategy with 3 steps:
Step 1: I copy the instance to a backup and set it to null
Step 2: I invoke the constructor normally
Step 3: I restore the instance like nothing happened

Here we go:
Type type = typeof(Girlfriend);
if (type != null)
{
    // step 1 copy the instance to a backup and set it to null
    Girlfriend backup = null;
    FieldInfo fi = type.GetField("instance", BindingFlags.NonPublic | BindingFlags.Static);
    if (fi != null)
    {
        backup = (Girlfriend)fi.GetValue(null);
        fi.SetValue(null, null);
    }

    // step 2 invoke the constructor normally
    ConstructorInfo ci = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
    if (ci != null)
    {
        try
        {
            gf2 = (Girlfriend)ci.Invoke(null);
        }
        catch { }
    }

    // step 3 restore backup
    if (fi != null)
    {
        fi.SetValue(null, backup);
    }
}
ShowComparation("Round 2", gf1, gf2);
Figure 4 - Attacking code, finally

Now see the result:

I did it one more time and got 2 girls.
Reflection 2 - 1 Singleton

Round 4 - Singleton with a little Reflection a.k.a Singleton v3

The attacker's code is ahead mine again. As the one who keeps the implementation goes right. What should I do? I am thinking. No idea shows up. So I write a blog post and ask for help.
One of my friends suggest me to check the invokers which invoke the constructor and allow only ones those are inside the definition of Girlfriend class.

To do so, I have to complete these works:
- Generate a privacy helper class that comparing 2 invokers' info
- Get the name of every invokers at the beginning of every constructions
- Allow only invokers those are members of the class, otherwise, throw another exception.

Th attacker used reflection to attack and break my Singleton twice. Now is the time I use reflection in my defense and fight back.
The below code is how I improve my code:

public class MethodBaseComparer : IEqualityComparer<MethodBase>
{
    private string GetMethodIdentifier(MethodBase mb)
    {
        return mb.Name + ":" + String.Join(";", mb.GetParameters().Select(paramInfo => paramInfo.Name).ToArray());
    }

    public bool Equals(MethodBase m1, MethodBase m2)
    {
        return this.GetMethodIdentifier(m1) == this.GetMethodIdentifier(m2);
    }

    public int GetHashCode(MethodBase mb)
    {
        return this.GetMethodIdentifier(mb).GetHashCode();
    }
}

public class PrivacyHelper
{
    public static bool IsInvocationAllowed<T>()
    {
        Type curType = typeof(T);
        MethodBase[] lstMethod = curType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).ToArray();
        MethodBase invoker = new StackTrace().GetFrame(2).GetMethod();
        if (lstMethod == null) 
            return false;
        else
            return lstMethod.Contains(invoker, new MethodBaseComparer());
    }
}
Figure 4 - Privacy helper and comparer classes

You can easily understand the classes. There is only 1 point that need to be explained. In the method IsInvocationAllowed, I call new StackTrace().GetFrame(2) ? Do you wonder why?
My intent is that when the Constructor called, it will call the method IsInvocationAllowed from helper class to verify something and when IsInvocationAllowed executed, the CallStack will be like this
position 0 - IsInvocationAllowed method
position 1 - Girlfriend constructor
position 2 - the invoker invoking the constructor

It's clearly that getting frame number 2 gives me the invoker's infomation.
After my improvement, the attacker will not be able to create the second girlfriend any more, and here is the result:

The score is equalized: Reflection 2 - 2 Singleton

Round 5 - The attacker is so stupid

Hi, it's me, the attacker. The last time I run my code, I see that gf2 is no longer available. I review my steps with debugger to find where thing goes wrong.
First step is ok, the static Girlfriend instance of the class is set to null successfully.
Second step is not ok, an exception is thrown again.

And after hours of thinking, I know that I am so stupid. When the static instance is null, why do I have to call the constructor myself? Just let the Singleton itself generates another Girlfriend for me.

I am not sure if this is working. But at least it decreases the possibility of being failed, because it reduces the amount of works that reflection does and let the Singleton generator does some.

Temporarily I have no other way to pass the condition checking from the defender. So I try this idea. modifying the second step into "Let the singleton does its job"

The line
gf2 = (Girlfriend)ci.Invoke(null);
is replaced by
gf2 = Girlfriend.Instance;

Then I run the code

What have we here? Two girls, available, and different from each other, and both mine.
This round I win, again. The defender must work harder to protect his code from being breaking.

Comments

Popular posts from this blog

New Admob for Android: Switching from Admob SDK to Google Play Services API

How to wrap a C# library for using in Java, a folk tale about an idiot coding at midnight.