Skip to content

Commit 5347ec6

Browse files
committed
Android binary XML parser (for in-package AndroidManifest.xml)
A big buggy still, TBC
1 parent d4df563 commit 5347ec6

9 files changed

+799
-8
lines changed

tools/apput/src/Android/ARSCHeader.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using System.IO;
3+
4+
namespace ApplicationUtility;
5+
6+
class ARSCHeader
7+
{
8+
// This is the minimal size such a header must have. There might be other header data too!
9+
const long MinimumSize = 2 + 2 + 4;
10+
11+
readonly long start;
12+
readonly uint size;
13+
readonly ushort type;
14+
readonly ushort headerSize;
15+
readonly bool unknownType;
16+
17+
public AndroidManifestChunkType Type => unknownType ? AndroidManifestChunkType.Null : (AndroidManifestChunkType)type;
18+
public ushort TypeRaw => type;
19+
public ushort HeaderSize => headerSize;
20+
public uint Size => size;
21+
public long End => start + (long)size;
22+
23+
public ARSCHeader (Stream data, AndroidManifestChunkType? expectedType = null)
24+
{
25+
start = data.Position;
26+
if (data.Length < start + MinimumSize) {
27+
throw new InvalidDataException ($"Input data not large enough. Offset: {start}");
28+
}
29+
30+
// Data in AXML is little-endian, which is fortuitous as that's the only format BinaryReader understands.
31+
using BinaryReader reader = Utilities.GetReaderAndRewindStream (data);
32+
33+
// ushort: type
34+
// ushort: header_size
35+
// uint: size
36+
type = reader.ReadUInt16 ();
37+
headerSize = reader.ReadUInt16 ();
38+
39+
// Total size of the chunk, including the header
40+
size = reader.ReadUInt32 ();
41+
42+
if (expectedType != null && type != (ushort)expectedType) {
43+
throw new InvalidOperationException ($"Header type is not equal to the expected type ({expectedType}): got 0x{type:x}, expected 0x{(ushort)expectedType:x}");
44+
}
45+
46+
unknownType = !Enum.IsDefined (typeof(AndroidManifestChunkType), type);
47+
48+
if (headerSize < MinimumSize) {
49+
throw new InvalidDataException ($"Declared header size is smaller than required size of {MinimumSize}. Offset: {start}");
50+
}
51+
52+
if (size < MinimumSize) {
53+
throw new InvalidDataException ($"Declared chunk size is smaller than required size of {MinimumSize}. Offset: {start}");
54+
}
55+
56+
if (size < headerSize) {
57+
throw new InvalidDataException ($"Declared chunk size ({size}) is smaller than header size ({headerSize})! Offset: {start}");
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)