Hi Evain,
I am facing another issue and since I am new to Cecil, I cannot find
what solution would be.
Now I am injecting a method in an assembly (currently it just returns
the string value passed to it as it is) which can be found in
following text.
Than I go through assembly and patch all "ldstr" so that the original
strings are passed to the injected methods and then the rturned value
is used by original ldstr. I got this technique from ncloak.
Now have a look at the following Search method which I have extracted
from my application. I have also posted the decompiled version of the
same method (using reflector). Also I have posted the decompiled
version of the "patched" Search method. Now it all looks ok to me BUT
I am getting following exception
System.InvalidProgramException: Common Language Runtime detected
an invalid program.
at WindowsFormsApplication1.Form1.Search(String criteria)
at WindowsFormsApplication1.Form1.button1_Click(Object sender,
EventArgs e)
This code is being run from a winform application using just a button
whose event handler is
private void button1_Click(object sender, EventArgs e)
{
Search("blah");
}
And it happens only which I have complex (i mean more than just 2-3)
string concatinations which leads to creation of IL comprising of an
array of strings which gets concatenated at the end.
Hope I have explained my issue properly.
Thanks
Vijay
Original Search method
public static void Search(string criteria)
{
var parameters = new ArrayList();
var isNumeric = true;
var query = "from "
+ "blah1 " + " src"
+ " where ("
+ " src." + "blah2" + " like ?"
+ (isNumeric ? " or src." + "blah3" + " = ?" :
string.Empty)
+ ((parameters != null && parameters.Count != 0) ? "
or src." + "blah4" + " in (" + "?" + ")" : string.Empty)
+ ")";
query = query.ToLower();
query += "from "
+ "blah1 " + " src"
+ " where ("
+ " src." + "blah2" + " like ?"
+ (isNumeric ? " or src." + "blah3" + " = ?" :
string.Empty)
+ ((parameters != null && parameters.Count != 0) ? "
or src." + "blah4" + " in (" + "?" + ")" : string.Empty)
+ ")";
foreach (var c in query)
{
Console.WriteLine(c.ToString());
}
}
Original Search method decompiled (C#) (reflector):
public static void Search(string criteria)
{
ArrayList parameters = new ArrayList();
bool isNumeric = true;
string CS$0$0000 = ("from blah1 src where ( src.blah2 like ?" +
(isNumeric ? " or src.blah3 = ?" : string.Empty) + (((parameters !=
null) && (parameters.Count != 0)) ? " or src.blah4 in (?)" :
string.Empty) + ")").ToLower();
string[] CS$0$0001 = new string[] { CS$0$0000, "from blah1 src
where ( src.blah2 like ?", isNumeric ? " or src.blah3 = ?" :
string.Empty, ((parameters != null) && (parameters.Count != 0)) ? " or
src.blah4 in (?)" : string.Empty, ")" };
string query = string.Concat(CS$0$0001);
foreach (char c in query)
{
Console.WriteLine(c.ToString());
}
}
Original Search method decompiled (IL) (reflector):
.method public hidebysig static void Search(string criteria) cil
managed
{
.maxstack 4
.locals init (
[0] class [mscorlib]System.Collections.ArrayList parameters,
[1] bool isNumeric,
[2] string query,
[3] char c,
[4] string CS$0$0000,
[5] string[] CS$0$0001,
[6] string CS$6$0002,
[7] int32 CS$7$0003,
[8] bool CS$4$0004)
L_0000: nop
L_0001: newobj instance void
[mscorlib]System.Collections.ArrayList::.ctor()
L_0006: stloc.0
L_0007: ldc.i4.1
L_0008: stloc.1
L_0009: ldstr "from blah1 src where ( src.blah2 like ?"
L_000e: ldloc.1
L_000f: brtrue.s L_0018
L_0011: ldsfld string [mscorlib]System.String::Empty
L_0016: br.s L_001d
L_0018: ldstr " or src.blah3 = ?"
L_001d: ldloc.0
L_001e: brfalse.s L_0028
L_0020: ldloc.0
L_0021: callvirt instance int32
[mscorlib]System.Collections.ArrayList::get_Count()
L_0026: brtrue.s L_002f
L_0028: ldsfld string [mscorlib]System.String::Empty
L_002d: br.s L_0034
L_002f: ldstr " or src.blah4 in (?)"
L_0034: ldstr ")"
L_0039: call string [mscorlib]System.String::Concat(string,
string, string, string)
L_003e: stloc.2
L_003f: ldloc.2
L_0040: callvirt instance string
[mscorlib]System.String::ToLower()
L_0045: stloc.2
L_0046: ldloc.2
L_0047: stloc.s CS$0$0000
L_0049: ldc.i4.5
L_004a: newarr string
L_004f: stloc.s CS$0$0001
L_0051: ldloc.s CS$0$0001
L_0053: ldc.i4.0
L_0054: ldloc.s CS$0$0000
L_0056: stelem.ref
L_0057: ldloc.s CS$0$0001
L_0059: ldc.i4.1
L_005a: ldstr "from blah1 src where ( src.blah2 like ?"
L_005f: stelem.ref
L_0060: ldloc.s CS$0$0001
L_0062: ldc.i4.2
L_0063: ldloc.1
L_0064: brtrue.s L_006d
L_0066: ldsfld string [mscorlib]System.String::Empty
L_006b: br.s L_0072
L_006d: ldstr " or src.blah3 = ?"
L_0072: stelem.ref
L_0073: ldloc.s CS$0$0001
L_0075: ldc.i4.3
L_0076: ldloc.0
L_0077: brfalse.s L_0081
L_0079: ldloc.0
L_007a: callvirt instance int32
[mscorlib]System.Collections.ArrayList::get_Count()
L_007f: brtrue.s L_0088
L_0081: ldsfld string [mscorlib]System.String::Empty
L_0086: br.s L_008d
L_0088: ldstr " or src.blah4 in (?)"
L_008d: stelem.ref
L_008e: ldloc.s CS$0$0001
L_0090: ldc.i4.4
L_0091: ldstr ")"
L_0096: stelem.ref
L_0097: ldloc.s CS$0$0001
L_0099: call string [mscorlib]System.String::Concat(string[])
L_009e: stloc.2
L_009f: nop
L_00a0: ldloc.2
L_00a1: stloc.s CS$6$0002
L_00a3: ldc.i4.0
L_00a4: stloc.s CS$7$0003
L_00a6: br.s L_00c7
L_00a8: ldloc.s CS$6$0002
L_00aa: ldloc.s CS$7$0003
L_00ac: callvirt instance char
[mscorlib]System.String::get_Chars(int32)
L_00b1: stloc.3
L_00b2: nop
L_00b3: ldloca.s c
L_00b5: call instance string [mscorlib]System.Char::ToString()
L_00ba: call void [mscorlib]System.Console::WriteLine(string)
L_00bf: nop
L_00c0: nop
L_00c1: ldloc.s CS$7$0003
L_00c3: ldc.i4.1
L_00c4: add
L_00c5: stloc.s CS$7$0003
L_00c7: ldloc.s CS$7$0003
L_00c9: ldloc.s CS$6$0002
L_00cb: callvirt instance int32
[mscorlib]System.String::get_Length()
L_00d0: clt
L_00d2: stloc.s CS$4$0004
L_00d4: ldloc.s CS$4$0004
L_00d6: brtrue.s L_00a8
L_00d8: ret
}
Injected method (C#) (Added to <Module>)
public static string ExtractString(string v, int s)
{
return v;
}
Injected method (IL) (Added to <Module>)
.method public hidebysig static string ExtractString(string v, int32
s) cil managed
{
.maxstack 1
.locals init (
[0] string str)
L_0000: nop
L_0001: ldarg.0
L_0002: stloc.0
L_0003: br.s L_0005
L_0005: ldloc.0
L_0006: ret
}
Decompiled new method (C#)
public static void Search(string criteria)
{
ArrayList list = new ArrayList();
bool flag = true;
string str2 = (ExtractString("from blah1 src where ( src.blah2
like ?", 0x170e) + (flag ? ExtractString(" or src.blah3 = ?",
0x1f76) : string.Empty) + (((list != null) && (list.Count != 0)) ?
ExtractString(" or src.blah4 in (?)", 0x1791) : string.Empty) +
ExtractString(")", 0x1801)).ToLower();
string[] strArray = new string[] { str2, ExtractString("from
blah1 src where ( src.blah2 like ?", 0x269a), flag ? ExtractString("
or src.blah3 = ?", 0x1c2e) : string.Empty, ((list != null) &&
(list.Count != 0)) ? ExtractString(" or src.blah4 in (?)", 0x216e) :
string.Empty, ExtractString(")", 0x1acb) };
string str = string.Concat(strArray);
foreach (char ch in str)
{
Console.WriteLine(ch.ToString());
}
}
Decompiled new method (IL)
.method public hidebysig static void Search(string criteria) cil
managed
{
.maxstack 3
.locals init (
[0] class [mscorlib]System.Collections.ArrayList list,
[1] bool flag,
[2] string str,
[3] char ch,
[4] string str2,
[5] string[] strArray,
[6] string str3,
[7] int32 num,
[8] bool flag2)
L_0000: nop
L_0001: newobj instance void
[mscorlib]System.Collections.ArrayList::.ctor()
L_0006: stloc.0
L_0007: ldc.i4.1
L_0008: stloc.1
L_0009: ldstr "from blah1 src where ( src.blah2 like ?"
L_000e: ldc.i4 0x170e
L_0013: call string <Module>::ExtractString(string, int32)
L_0018: ldloc.1
L_0019: brtrue.s L_0022
L_001b: ldsfld string [mscorlib]System.String::Empty
L_0020: br.s L_0031
L_0022: ldstr " or src.blah3 = ?"
L_0027: ldc.i4 0x1f76
L_002c: call string <Module>::ExtractString(string, int32)
L_0031: ldloc.0
L_0032: brfalse.s L_003c
L_0034: ldloc.0
L_0035: callvirt instance int32
[mscorlib]System.Collections.ArrayList::get_Count()
L_003a: brtrue.s L_0043
L_003c: ldsfld string [mscorlib]System.String::Empty
L_0041: br.s L_0052
L_0043: ldstr " or src.blah4 in (?)"
L_0048: ldc.i4 0x1791
L_004d: call string <Module>::ExtractString(string, int32)
L_0052: ldstr ")"
L_0057: ldc.i4 0x1801
L_005c: call string <Module>::ExtractString(string, int32)
L_0061: call string [mscorlib]System.String::Concat(string,
string, string, string)
L_0066: stloc.2
L_0067: ldloc.2
L_0068: callvirt instance string
[mscorlib]System.String::ToLower()
L_006d: stloc.2
L_006e: ldloc.2
L_006f: stloc.s str2
L_0071: ldc.i4.5
L_0072: newarr string
L_0077: stloc.s strArray
L_0079: ldloc.s strArray
L_007b: ldc.i4.0
L_007c: ldloc.s str2
L_007e: stelem.ref
L_007f: ldloc.s strArray
L_0081: ldc.i4.1
L_0082: ldstr "from blah1 src where ( src.blah2 like ?"
L_0087: ldc.i4 0x269a
L_008c: call string <Module>::ExtractString(string, int32)
L_0091: stelem.ref
L_0092: ldloc.s strArray
L_0094: ldc.i4.2
L_0095: ldloc.1
L_0096: brtrue.s L_009f
L_0098: ldsfld string [mscorlib]System.String::Empty
L_009d: br.s L_00ae
L_009f: ldstr " or src.blah3 = ?"
L_00a4: ldc.i4 0x1c2e
L_00a9: call string <Module>::ExtractString(string, int32)
L_00ae: stelem.ref
L_00af: ldloc.s strArray
L_00b1: ldc.i4.3
L_00b2: ldloc.0
L_00b3: brfalse.s L_00bd
L_00b5: ldloc.0
L_00b6: callvirt instance int32
[mscorlib]System.Collections.ArrayList::get_Count()
L_00bb: brtrue.s L_00c4
L_00bd: ldsfld string [mscorlib]System.String::Empty
L_00c2: br.s L_00d3
L_00c4: ldstr " or src.blah4 in (?)"
L_00c9: ldc.i4 0x216e
L_00ce: call string <Module>::ExtractString(string, int32)
L_00d3: stelem.ref
L_00d4: ldloc.s strArray
L_00d6: ldc.i4.4
L_00d7: ldstr ")"
L_00dc: ldc.i4 0x1acb
L_00e1: call string <Module>::ExtractString(string, int32)
L_00e6: stelem.ref
L_00e7: ldloc.s strArray
L_00e9: call string [mscorlib]System.String::Concat(string[])
L_00ee: stloc.2
L_00ef: nop
L_00f0: ldloc.2
L_00f1: stloc.s str3
L_00f3: ldc.i4.0
L_00f4: stloc.s num
L_00f6: br.s L_0117
L_00f8: ldloc.s str3
L_00fa: ldloc.s num
L_00fc: callvirt instance char
[mscorlib]System.String::get_Chars(int32)
L_0101: stloc.3
L_0102: nop
L_0103: ldloca.s ch
L_0105: call instance string [mscorlib]System.Char::ToString()
L_010a: call void [mscorlib]System.Console::WriteLine(string)
L_010f: nop
L_0110: nop
L_0111: ldloc.s num
L_0113: ldc.i4.1
L_0114: add
L_0115: stloc.s num
L_0117: ldloc.s num
L_0119: ldloc.s str3
L_011b: callvirt instance int32
[mscorlib]System.String::get_Length()
L_0120: clt
L_0122: stloc.s flag2
L_0124: ldloc.s flag2
L_0126: brtrue.s L_00f8
L_0128: ret
}
--
--
mono-cecil