Created
November 8, 2013 00:13
-
-
Save urasandesu/7364167 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text.RegularExpressions; | |
using Mono.Cecil; | |
using Mono.Cecil.Cil; | |
namespace ConsoleApplication9 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var asm = AssemblyDefinition.ReadAssembly("ConsoleApplication9.exe"); | |
var mod = asm.MainModule; | |
var types = mod.Types; | |
var methods = types.Where(_ => _.Name == typeof(Target).Name).SelectMany(_ => _.Methods).Where(_ => _.IsStatic); | |
var bodies = methods.Select(_ => _.Body); | |
// | |
foreach (var body in bodies.Where(HasBadOperationForIDisposable)) | |
Console.WriteLine(body.Method.ToString()); | |
} | |
static bool HasBadOperationForIDisposable(MethodBody body) | |
{ | |
if (!body.HasExceptionHandlers) | |
return true; | |
var finallyClauses = body.ExceptionHandlers.Where(_ => _.HandlerType == ExceptionHandlerType.Finally); | |
if (!finallyClauses.Any()) | |
return true; | |
foreach (var inst in finallyClauses.SelectMany(_ => _.EnumerateInstructions())) | |
{ | |
var memberRef = inst.Operand as MemberReference; | |
if (Regex.IsMatch(memberRef + "", @"::Dispose\(\)")) | |
return false; | |
} | |
return true; | |
} | |
} | |
static class ExceptionHandlerMixin | |
{ | |
public static IEnumerable<Instruction> EnumerateInstructions(this ExceptionHandler clause) | |
{ | |
for (Instruction current = clause.HandlerStart, last = clause.HandlerEnd; | |
current.Offset <= last.Offset && current.Next != null; | |
current = current.Next) | |
{ | |
yield return current; | |
} | |
} | |
} | |
public class Target | |
{ | |
public static void GoodDispose1() | |
{ | |
using (var fs = new FileStream("", FileMode.Open)) { } | |
} | |
public static void GoodDispose2() | |
{ | |
try | |
{ | |
using (var fs = new FileStream("", FileMode.Open)) { } | |
} | |
catch | |
{ | |
throw; | |
} | |
} | |
public static void GoodDispose3() | |
{ | |
try | |
{ | |
using (var fs = new FileStream("", FileMode.Open)) { } | |
} | |
catch | |
{ | |
throw; | |
} | |
finally | |
{ | |
Console.WriteLine("終了!"); | |
} | |
} | |
public static void GoodDispose4() | |
{ | |
try | |
{ | |
var fs = default(FileStream); | |
try | |
{ | |
fs = new FileStream("", FileMode.Open); | |
} | |
finally | |
{ | |
if (fs != null) | |
fs.Dispose(); | |
} | |
} | |
catch | |
{ | |
throw; | |
} | |
finally | |
{ | |
Console.WriteLine("終了!"); | |
} | |
} | |
public static void BadDispose1() | |
{ | |
var fs = new FileStream("", FileMode.Open); | |
} | |
public static void BadDispose2() | |
{ | |
try | |
{ | |
var fs = new FileStream("", FileMode.Open); | |
} | |
catch | |
{ | |
throw; | |
} | |
} | |
public static void BadDispose3() | |
{ | |
try | |
{ | |
var fs = new FileStream("", FileMode.Open); | |
} | |
catch | |
{ | |
throw; | |
} | |
finally | |
{ | |
Console.WriteLine("終了!"); | |
} | |
} | |
public static void BadDispose4() | |
{ | |
try | |
{ | |
try | |
{ | |
var fs = new FileStream("", FileMode.Open); | |
fs.Dispose(); | |
} | |
finally | |
{ | |
} | |
} | |
catch | |
{ | |
throw; | |
} | |
finally | |
{ | |
Console.WriteLine("終了!"); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment