Skip to content

Commit ac99859

Browse files
authored
String Public Key (#395)
* Handle public key being string on older versions * Update version comment * One more comment
1 parent 3c1e235 commit ac99859

File tree

2 files changed

+102
-7
lines changed

2 files changed

+102
-7
lines changed

LibCpp2IL/Metadata/Il2CppAssemblyNameDefinition.cs

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
24
using System.Linq;
35

46
namespace LibCpp2IL.Metadata;
@@ -28,8 +30,100 @@ public byte[]? PublicKey
2830
{
2931
get
3032
{
31-
var result = LibCpp2IlMain.TheMetadata!.GetByteArrayFromIndex(publicKeyIndex);
32-
return result.Length == 0 ? null : result;
33+
// The difference between these two options can be seen in the header files.
34+
// const uint8_t* public_key;
35+
// const char* public_key;
36+
37+
if (IsAtLeast(24.4f) || Is(24.15f))
38+
{
39+
// 2018.4.34 until 2019 (24.15)
40+
// 2019.4.15 until 2020 (24.4)
41+
// 2020.1.11 until 2020.2.0 (24.4)
42+
// 2020.2.0b7 and later (27+)
43+
var result = LibCpp2IlMain.TheMetadata!.GetByteArrayFromIndex(publicKeyIndex);
44+
return result.Length == 0 ? null : result;
45+
}
46+
else
47+
{
48+
var str = LibCpp2IlMain.TheMetadata!.GetStringFromIndex(publicKeyIndex);
49+
50+
if (str is "NULL")
51+
return null; // No public key
52+
53+
// mscorlib example:
54+
// "\x0\x0\x0\x0\x0\x0\x0\x0\x4\x0\x0\x0\x0\x0\x0\x0"
55+
// The string above is verbatim, so the backslashes are not escape characters and the quotes are part of the string.
56+
if (str.Length > 2 && str[0] is '"' && str[^1] is '"' && TryParseByteArray(str.AsSpan()[1..^1], out var result))
57+
return result;
58+
59+
return null; // Parsing failed
60+
}
61+
62+
static bool IsHexDigit(char c) => c is (>= '0' and <= '9') or (>= 'A' and <= 'F') or (>= 'a' and <= 'f');
63+
64+
static bool TryParseByte(ReadOnlySpan<char> characters, out byte result)
65+
{
66+
#if NET6_0_OR_GREATER
67+
return byte.TryParse(characters, System.Globalization.NumberStyles.HexNumber, null, out result);
68+
#else
69+
return byte.TryParse(characters.ToString(), System.Globalization.NumberStyles.HexNumber, null, out result);
70+
#endif
71+
}
72+
73+
static bool TryParseByteArray(ReadOnlySpan<char> characters, [NotNullWhen(true)] out byte[]? result)
74+
{
75+
var bytes = new List<byte>();
76+
77+
var i = 0;
78+
while (i < characters.Length)
79+
{
80+
// Each byte is represented by 3 or 4 characters.
81+
// The first one is backslash.
82+
// The second one is 'x'.
83+
// The third and fourth (if present) ones are the hexadecimal representation of the byte.
84+
if (i > characters.Length - 3 || characters[i] is not '\\' || characters[i + 1] is not 'x')
85+
{
86+
result = null;
87+
return false;
88+
}
89+
90+
i += 2;
91+
92+
if (!IsHexDigit(characters[i]))
93+
{
94+
result = null;
95+
return false;
96+
}
97+
98+
ReadOnlySpan<char> hexCharacters;
99+
if (i + 1 < characters.Length && characters[i + 1] is not '\\')
100+
{
101+
if (!IsHexDigit(characters[i + 1]))
102+
{
103+
result = null;
104+
return false;
105+
}
106+
hexCharacters = characters.Slice(i, 2);
107+
i += 2;
108+
}
109+
else
110+
{
111+
hexCharacters = characters.Slice(i, 1);
112+
i += 1;
113+
}
114+
115+
if (!TryParseByte(hexCharacters, out var b))
116+
{
117+
result = null;
118+
return false;
119+
}
120+
121+
bytes.Add(b);
122+
}
123+
124+
result = bytes.ToArray();
125+
return true;
126+
}
33127
}
34128
}
35129

LibCpp2IL/ReadableClass.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
using System;
1+
using System;
22

33
namespace LibCpp2IL;
44

55
public abstract class ReadableClass
66
{
7-
protected bool IsAtLeast(float vers) => LibCpp2IlMain.MetadataVersion >= vers;
8-
protected bool IsLessThan(float vers) => LibCpp2IlMain.MetadataVersion < vers;
9-
protected bool IsAtMost(float vers) => LibCpp2IlMain.MetadataVersion <= vers;
10-
protected bool IsNot(float vers) => Math.Abs(LibCpp2IlMain.MetadataVersion - vers) > 0.001f;
7+
protected static bool IsAtLeast(float vers) => LibCpp2IlMain.MetadataVersion >= vers;
8+
protected static bool IsLessThan(float vers) => LibCpp2IlMain.MetadataVersion < vers;
9+
protected static bool IsAtMost(float vers) => LibCpp2IlMain.MetadataVersion <= vers;
10+
protected static bool IsNot(float vers) => Math.Abs(LibCpp2IlMain.MetadataVersion - vers) > 0.001f;
11+
protected static bool Is(float vers) => Math.Abs(LibCpp2IlMain.MetadataVersion - vers) < 0.001f;
1112

1213
public abstract void Read(ClassReadingBinaryReader reader);
1314
}

0 commit comments

Comments
 (0)