Skip to content

Commit

Permalink
New async constructor design
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderOMara committed Jan 20, 2025
1 parent 67f4911 commit ad3d265
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 47 deletions.
55 changes: 22 additions & 33 deletions macho/macho.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,14 @@ for (const { kind, arch, file, archs } of fixtures) {
const [macho] = await fixtureMacho(kind, arch, [file]);
const blob = new Blob([macho]);
for (const [arc, info] of archs) {
const m = new MachO();

assertEquals(m.isOpen(), false, arc);
assertEquals(m.offset(), 0, arc);
assertEquals(m.length(), 0, arc);
assertEquals(m.signingExtent(), 0, arc);
assertEquals(m.isSuspicious(), false, arc);

const bin = thin(macho, ...CPU_ARCHITECTURES.get(arc)!);
const offset = bin.byteOffset;
const length = offset ? bin.byteLength : blob.size;
if (offset) {
const m = offset
// deno-lint-ignore no-await-in-loop
await m.open(blob, offset, length);
} else {
? await MachO.MachO(blob, offset, length)
// deno-lint-ignore no-await-in-loop
await m.open(blob);
}
: await MachO.MachO(blob);

assertEquals(m.isOpen(), true, arc);
assertEquals(m.offset(), offset, arc);
Expand Down Expand Up @@ -87,13 +77,11 @@ for (const { kind, arch, file, archs } of fixtures) {
});
}

Deno.test('open under', async () => {
const macho = new MachO();

Deno.test('read under', async () => {
let mh = new MachHeader(new ArrayBuffer(MachHeader.BYTE_LENGTH - 1));

await assertRejects(
() => macho.open(new Blob([mh.buffer])),
() => MachO.MachO(new Blob([mh.buffer])),
RangeError,
'Invalid header',
);
Expand All @@ -102,7 +90,7 @@ Deno.test('open under', async () => {
mh.magic = MH_MAGIC_64;

await assertRejects(
() => macho.open(new Blob([mh.buffer])),
() => MachO.MachO(new Blob([mh.buffer])),
RangeError,
'Invalid header',
);
Expand All @@ -113,7 +101,7 @@ Deno.test('open under', async () => {
mh.sizeofcmds = 2;

await assertRejects(
() => macho.open(new Blob([mh.buffer])),
() => MachO.MachO(new Blob([mh.buffer])),
RangeError,
'Invalid commands',
);
Expand All @@ -136,20 +124,22 @@ Deno.test('validateStructure LC_SYMTAB', async () => {
cmd.stroff = MachHeader.BYTE_LENGTH + SymtabCommand.BYTE_LENGTH;
cmd.strsize = extra;

let macho = new MachO();
await macho.open(new Blob([buffer]));

assertEquals(macho.isSuspicious(), false);

macho = new MachO();
await macho.open(new Blob([buffer, new ArrayBuffer(1)]));

assertEquals(macho.isSuspicious(), true);
{
const macho = await MachO.MachO(new Blob([buffer]));
assertEquals(macho.isSuspicious(), false);
}

macho = new MachO();
await macho.open(new Blob([buffer.slice(0, buffer.byteLength - 1)]));
{
const macho = await MachO.MachO(new Blob([buffer, new ArrayBuffer(1)]));
assertEquals(macho.isSuspicious(), true);
}

assertEquals(macho.isSuspicious(), true);
{
const macho = await MachO.MachO(
new Blob([buffer.slice(0, buffer.byteLength - 1)]),
);
assertEquals(macho.isSuspicious(), true);
}
});

Deno.test('validateStructure bad command size', async () => {
Expand All @@ -175,10 +165,9 @@ Deno.test('validateStructure bad command size', async () => {
cmd.cmd = LC;
cmd.cmdsize = cmdsize;

const macho = new MachO();
// deno-lint-ignore no-await-in-loop
await assertRejects(
() => macho.open(new Blob([buffer])),
() => MachO.MachO(new Blob([buffer])),
RangeError,
'Invalid command size',
tag,
Expand Down
33 changes: 31 additions & 2 deletions macho/macho.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,25 @@ export class MachO extends MachOBase {
private mSuspicious = false;

/**
* Open binary.
* Create uninitialized Mach-O instance.
*/
protected constructor() {
super();
}

/**
* Initialize instance.
*
* @param reader Reader object.
* @param offset Offset for subsection.
* @param length Length of subsection, requires offset.
* @returns This instance.
*/
public async open(reader: Reader, offset = 0, length = 0): Promise<void> {
protected async MachO(
reader: Reader,
offset = 0,
length = 0,
): Promise<MachO> {
offset = (+offset || 0) - (offset % 1 || 0);
length = (+length || 0) - (length % 1 || 0);
this.mReader = reader;
Expand Down Expand Up @@ -86,6 +98,7 @@ export class MachO extends MachOBase {
if (mLength) {
this.validateStructure();
}
return this;
}

/**
Expand Down Expand Up @@ -235,4 +248,20 @@ export class MachO extends MachOBase {
public isSuspicious(): boolean {
return this.mSuspicious;
}

/**
* Create Mach-O binary over a reader.
*
* @param reader Reader object.
* @param offset Offset for subsection.
* @param length Length of subsection, requires offset.
* @returns Mach-O binary.
*/
public static async MachO(
reader: Reader,
offset = 0,
length = 0,
): Promise<MachO> {
return await new MachO().MachO(reader, offset, length);
}
}
22 changes: 10 additions & 12 deletions macho/universal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,23 +257,17 @@ export class Universal {
if (typeof a === 'number') {
if (this.isUniversal()) {
const length = this.lengthOfSlice(a);
const macho = new MachO();
await macho.open(this.mReader!, a, length);
return this.make(macho);
return this.make(await MachO.MachO(this.mReader!, a, length));
}
if (a === this.mBase) {
const macho = new MachO();
await macho.open(this.mReader!);
return macho;
return MachO.MachO(this.mReader!);
}
} else {
if (this.isUniversal()) {
return this.findImage(a);
}
if (this.mThinArch!.matches(a)) {
const macho = new MachO();
await macho.open(this.mReader!, this.mBase, this.mLength);
return macho;
return MachO.MachO(this.mReader!, this.mBase, this.mLength);
}
}
throw new RangeError('Architecture not found');
Expand Down Expand Up @@ -448,9 +442,13 @@ export class Universal {
*/
private async findImage(target: Const<Architecture>): Promise<MachO> {
const arch = this.findArch(target);
const macho = new MachO();
await macho.open(this.mReader!, this.mBase + arch.offset, arch.size);
return this.make(macho);
return this.make(
await MachO.MachO(
this.mReader!,
this.mBase + arch.offset,
arch.size,
),
);
}

/**
Expand Down

0 comments on commit ad3d265

Please sign in to comment.