Skip to content

Instantly share code, notes, and snippets.

@urasandesu
Created November 8, 2013 00:13
Show Gist options
  • Save urasandesu/7364167 to your computer and use it in GitHub Desktop.
Save urasandesu/7364167 to your computer and use it in GitHub Desktop.
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