如何防范代码的 finalizer() 漏洞?
刚看了一篇文章,讲在java世界里析构方法可能引起的漏洞以及如何防范。
马上在C#中试了一下,发现.net也有同样的问题。代码如下
1 using System;
2 using System.Threading;
3
4 namespace TestProj
5 {
6
7
8 class Vulnerable
9 {
10 int value = 0;
11
12 public Vulnerable(int value)
13 {
14 if (value <= 0)
15 {
16 throw new ArgumentException("Vulnerable value must be positive");
17 }
18 this.value = value;
19 }
20 public override string ToString()
21 {
22 return (value.ToString());
23 }
24 }
25
26 class AttackVulnerable : Vulnerable
27 {
28 static Vulnerable vulnerable;
29
30 public AttackVulnerable(int value)
31 : base(value)
32 {
33 }
34
35 ~AttackVulnerable()
36 {
37 vulnerable = this;
38 }
39
40 public static void Main(string[] args)
41 {
42 try
43 {
44 new AttackVulnerable(-1);
45 }
46 catch (Exception e)
47 {
48 Console.WriteLine(e.Message);
49 }
50 GC.Collect();
51 Thread.Sleep(1000);//wait for gc to complete
52 if (vulnerable != null)
53 {
54 Console.WriteLine("Vulnerable object " + vulnerable + " created!");
55 }
56 Console.ReadLine();
57 }
58 }
2 using System.Threading;
3
4 namespace TestProj
5 {
6
7
8 class Vulnerable
9 {
10 int value = 0;
11
12 public Vulnerable(int value)
13 {
14 if (value <= 0)
15 {
16 throw new ArgumentException("Vulnerable value must be positive");
17 }
18 this.value = value;
19 }
20 public override string ToString()
21 {
22 return (value.ToString());
23 }
24 }
25
26 class AttackVulnerable : Vulnerable
27 {
28 static Vulnerable vulnerable;
29
30 public AttackVulnerable(int value)
31 : base(value)
32 {
33 }
34
35 ~AttackVulnerable()
36 {
37 vulnerable = this;
38 }
39
40 public static void Main(string[] args)
41 {
42 try
43 {
44 new AttackVulnerable(-1);
45 }
46 catch (Exception e)
47 {
48 Console.WriteLine(e.Message);
49 }
50 GC.Collect();
51 Thread.Sleep(1000);//wait for gc to complete
52 if (vulnerable != null)
53 {
54 Console.WriteLine("Vulnerable object " + vulnerable + " created!");
55 }
56 Console.ReadLine();
57 }
58 }
59 }
运行结果如下
很明显结果是漏洞存在。
关键是原文中给出的java世界的解决办法不知在C#中有无对应的实现?真心求教博客园各位高人。
java世界中可以在调用自身构造器和调用object构造器(其实是基类构造器啦)中间执行一段static代码感觉挺牛的。不知道java中的那个Void怎么在c#中实现呢?
[Update].net中可以这样实现
1 using System;
2 using System.Threading;
3
4 namespace TestProj
5 {
6 class Invulnerable
7 {
8 int value = 0;
9
10 public Invulnerable(int value)
11 {
12 GC.SuppressFinalize(this);
13 if (value <= 0)
14 {
15 throw new ArgumentException("Invulnerable value must be positive");
16 }
17 this.value = value;
18 }
19
20 public override string ToString()
21 {
22 return (value.ToString());
23 }
24 }
25
26 class AttackInvulnerable : Invulnerable
27 {
28 static Invulnerable vulnerable;
29
30 public AttackInvulnerable(int value)
31 : base(value)
32 {
33 }
34
35 ~AttackInvulnerable()
36 {
37 vulnerable = this;
38 }
39
40 public static void Main(string[] args)
41 {
42 try
43 {
44 new AttackInvulnerable(-1);
45 }
46 catch (Exception e)
47 {
48 Console.WriteLine(e.Message);
49 }
50
51 GC.Collect();
52 Thread.Sleep(1000);//wait for gc to complete
53 if (vulnerable != null)
54 {
55 Console.WriteLine("Vulnerable object " + vulnerable + " created!");
56 }
57 else
58 {
59 Console.WriteLine("Attack failed");
60 }
61 Console.ReadLine();
62 }
63 }
2 using System.Threading;
3
4 namespace TestProj
5 {
6 class Invulnerable
7 {
8 int value = 0;
9
10 public Invulnerable(int value)
11 {
12 GC.SuppressFinalize(this);
13 if (value <= 0)
14 {
15 throw new ArgumentException("Invulnerable value must be positive");
16 }
17 this.value = value;
18 }
19
20 public override string ToString()
21 {
22 return (value.ToString());
23 }
24 }
25
26 class AttackInvulnerable : Invulnerable
27 {
28 static Invulnerable vulnerable;
29
30 public AttackInvulnerable(int value)
31 : base(value)
32 {
33 }
34
35 ~AttackInvulnerable()
36 {
37 vulnerable = this;
38 }
39
40 public static void Main(string[] args)
41 {
42 try
43 {
44 new AttackInvulnerable(-1);
45 }
46 catch (Exception e)
47 {
48 Console.WriteLine(e.Message);
49 }
50
51 GC.Collect();
52 Thread.Sleep(1000);//wait for gc to complete
53 if (vulnerable != null)
54 {
55 Console.WriteLine("Vulnerable object " + vulnerable + " created!");
56 }
57 else
58 {
59 Console.WriteLine("Attack failed");
60 }
61 Console.ReadLine();
62 }
63 }
64 }