Skip to content

Commit

Permalink
String Public Key (#395)
Browse files Browse the repository at this point in the history
* Handle public key being string on older versions

* Update version comment

* One more comment
  • Loading branch information
ds5678 authored Dec 13, 2024
1 parent 3c1e235 commit ac99859
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 7 deletions.
98 changes: 96 additions & 2 deletions LibCpp2IL/Metadata/Il2CppAssemblyNameDefinition.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;

namespace LibCpp2IL.Metadata;
Expand Down Expand Up @@ -28,8 +30,100 @@ public byte[]? PublicKey
{
get
{
var result = LibCpp2IlMain.TheMetadata!.GetByteArrayFromIndex(publicKeyIndex);
return result.Length == 0 ? null : result;
// The difference between these two options can be seen in the header files.
// const uint8_t* public_key;
// const char* public_key;

if (IsAtLeast(24.4f) || Is(24.15f))
{
// 2018.4.34 until 2019 (24.15)
// 2019.4.15 until 2020 (24.4)
// 2020.1.11 until 2020.2.0 (24.4)
// 2020.2.0b7 and later (27+)
var result = LibCpp2IlMain.TheMetadata!.GetByteArrayFromIndex(publicKeyIndex);
return result.Length == 0 ? null : result;
}
else
{
var str = LibCpp2IlMain.TheMetadata!.GetStringFromIndex(publicKeyIndex);

if (str is "NULL")
return null; // No public key

// mscorlib example:
// "\x0\x0\x0\x0\x0\x0\x0\x0\x4\x0\x0\x0\x0\x0\x0\x0"
// The string above is verbatim, so the backslashes are not escape characters and the quotes are part of the string.
if (str.Length > 2 && str[0] is '"' && str[^1] is '"' && TryParseByteArray(str.AsSpan()[1..^1], out var result))
return result;

return null; // Parsing failed
}

static bool IsHexDigit(char c) => c is (>= '0' and <= '9') or (>= 'A' and <= 'F') or (>= 'a' and <= 'f');

static bool TryParseByte(ReadOnlySpan<char> characters, out byte result)
{
#if NET6_0_OR_GREATER
return byte.TryParse(characters, System.Globalization.NumberStyles.HexNumber, null, out result);
#else
return byte.TryParse(characters.ToString(), System.Globalization.NumberStyles.HexNumber, null, out result);
#endif
}

static bool TryParseByteArray(ReadOnlySpan<char> characters, [NotNullWhen(true)] out byte[]? result)
{
var bytes = new List<byte>();

var i = 0;
while (i < characters.Length)
{
// Each byte is represented by 3 or 4 characters.
// The first one is backslash.
// The second one is 'x'.
// The third and fourth (if present) ones are the hexadecimal representation of the byte.
if (i > characters.Length - 3 || characters[i] is not '\\' || characters[i + 1] is not 'x')
{
result = null;
return false;
}

i += 2;

if (!IsHexDigit(characters[i]))
{
result = null;
return false;
}

ReadOnlySpan<char> hexCharacters;
if (i + 1 < characters.Length && characters[i + 1] is not '\\')
{
if (!IsHexDigit(characters[i + 1]))
{
result = null;
return false;
}
hexCharacters = characters.Slice(i, 2);
i += 2;
}
else
{
hexCharacters = characters.Slice(i, 1);
i += 1;
}

if (!TryParseByte(hexCharacters, out var b))
{
result = null;
return false;
}

bytes.Add(b);
}

result = bytes.ToArray();
return true;
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions LibCpp2IL/ReadableClass.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using System;
using System;

namespace LibCpp2IL;

public abstract class ReadableClass
{
protected bool IsAtLeast(float vers) => LibCpp2IlMain.MetadataVersion >= vers;
protected bool IsLessThan(float vers) => LibCpp2IlMain.MetadataVersion < vers;
protected bool IsAtMost(float vers) => LibCpp2IlMain.MetadataVersion <= vers;
protected bool IsNot(float vers) => Math.Abs(LibCpp2IlMain.MetadataVersion - vers) > 0.001f;
protected static bool IsAtLeast(float vers) => LibCpp2IlMain.MetadataVersion >= vers;
protected static bool IsLessThan(float vers) => LibCpp2IlMain.MetadataVersion < vers;
protected static bool IsAtMost(float vers) => LibCpp2IlMain.MetadataVersion <= vers;
protected static bool IsNot(float vers) => Math.Abs(LibCpp2IlMain.MetadataVersion - vers) > 0.001f;
protected static bool Is(float vers) => Math.Abs(LibCpp2IlMain.MetadataVersion - vers) < 0.001f;

public abstract void Read(ClassReadingBinaryReader reader);
}

0 comments on commit ac99859

Please sign in to comment.