Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/darwin/verify-macho.js
3520 views
1
"use strict";
2
var __importDefault = (this && this.__importDefault) || function (mod) {
3
return (mod && mod.__esModule) ? mod : { "default": mod };
4
};
5
Object.defineProperty(exports, "__esModule", { value: true });
6
/*---------------------------------------------------------------------------------------------
7
* Copyright (c) Microsoft Corporation. All rights reserved.
8
* Licensed under the MIT License. See License.txt in the project root for license information.
9
*--------------------------------------------------------------------------------------------*/
10
const assert_1 = __importDefault(require("assert"));
11
const path_1 = __importDefault(require("path"));
12
const promises_1 = require("fs/promises");
13
const cross_spawn_promise_1 = require("@malept/cross-spawn-promise");
14
const minimatch_1 = __importDefault(require("minimatch"));
15
const MACHO_PREFIX = 'Mach-O ';
16
const MACHO_64_MAGIC_LE = 0xfeedfacf;
17
const MACHO_UNIVERSAL_MAGIC_LE = 0xbebafeca;
18
const MACHO_ARM64_CPU_TYPE = new Set([
19
0x0c000001,
20
0x0100000c,
21
]);
22
const MACHO_X86_64_CPU_TYPE = new Set([
23
0x07000001,
24
0x01000007,
25
]);
26
// Files to skip during architecture validation
27
const FILES_TO_SKIP = [
28
// MSAL runtime files are only present in ARM64 builds
29
'**/extensions/microsoft-authentication/dist/libmsalruntime.dylib',
30
'**/extensions/microsoft-authentication/dist/msal-node-runtime.node',
31
];
32
function isFileSkipped(file) {
33
return FILES_TO_SKIP.some(pattern => (0, minimatch_1.default)(file, pattern));
34
}
35
async function read(file, buf, offset, length, position) {
36
let filehandle;
37
try {
38
filehandle = await (0, promises_1.open)(file);
39
await filehandle.read(buf, offset, length, position);
40
}
41
finally {
42
await filehandle?.close();
43
}
44
}
45
async function checkMachOFiles(appPath, arch) {
46
const visited = new Set();
47
const invalidFiles = [];
48
const header = Buffer.alloc(8);
49
const file_header_entry_size = 20;
50
const checkx86_64Arch = (arch === 'x64');
51
const checkArm64Arch = (arch === 'arm64');
52
const checkUniversalArch = (arch === 'universal');
53
const traverse = async (p) => {
54
p = await (0, promises_1.realpath)(p);
55
if (visited.has(p)) {
56
return;
57
}
58
visited.add(p);
59
const info = await (0, promises_1.stat)(p);
60
if (info.isSymbolicLink()) {
61
return;
62
}
63
if (info.isFile()) {
64
let fileOutput = '';
65
try {
66
fileOutput = await (0, cross_spawn_promise_1.spawn)('file', ['--brief', '--no-pad', p]);
67
}
68
catch (e) {
69
if (e instanceof cross_spawn_promise_1.ExitCodeError) {
70
/* silently accept error codes from "file" */
71
}
72
else {
73
throw e;
74
}
75
}
76
if (fileOutput.startsWith(MACHO_PREFIX)) {
77
console.log(`Verifying architecture of ${p}`);
78
read(p, header, 0, 8, 0).then(_ => {
79
const header_magic = header.readUInt32LE();
80
if (header_magic === MACHO_64_MAGIC_LE) {
81
const cpu_type = header.readUInt32LE(4);
82
if (checkUniversalArch) {
83
invalidFiles.push(p);
84
}
85
else if (checkArm64Arch && !MACHO_ARM64_CPU_TYPE.has(cpu_type)) {
86
invalidFiles.push(p);
87
}
88
else if (checkx86_64Arch && !MACHO_X86_64_CPU_TYPE.has(cpu_type)) {
89
invalidFiles.push(p);
90
}
91
}
92
else if (header_magic === MACHO_UNIVERSAL_MAGIC_LE) {
93
const num_binaries = header.readUInt32BE(4);
94
assert_1.default.equal(num_binaries, 2);
95
const file_entries_size = file_header_entry_size * num_binaries;
96
const file_entries = Buffer.alloc(file_entries_size);
97
read(p, file_entries, 0, file_entries_size, 8).then(_ => {
98
for (let i = 0; i < num_binaries; i++) {
99
const cpu_type = file_entries.readUInt32LE(file_header_entry_size * i);
100
if (!MACHO_ARM64_CPU_TYPE.has(cpu_type) && !MACHO_X86_64_CPU_TYPE.has(cpu_type)) {
101
invalidFiles.push(p);
102
}
103
}
104
});
105
}
106
});
107
}
108
}
109
if (info.isDirectory()) {
110
for (const child of await (0, promises_1.readdir)(p)) {
111
await traverse(path_1.default.resolve(p, child));
112
}
113
}
114
};
115
await traverse(appPath);
116
return invalidFiles;
117
}
118
const archToCheck = process.argv[2];
119
(0, assert_1.default)(process.env['APP_PATH'], 'APP_PATH not set');
120
(0, assert_1.default)(archToCheck === 'x64' || archToCheck === 'arm64' || archToCheck === 'universal', `Invalid architecture ${archToCheck} to check`);
121
checkMachOFiles(process.env['APP_PATH'], archToCheck).then(invalidFiles => {
122
// Filter out files that should be skipped
123
const actualInvalidFiles = invalidFiles.filter(file => !isFileSkipped(file));
124
if (actualInvalidFiles.length > 0) {
125
console.error('\x1b[31mThese files are built for the wrong architecture:\x1b[0m');
126
actualInvalidFiles.forEach(file => console.error(`\x1b[31m${file}\x1b[0m`));
127
process.exit(1);
128
}
129
else {
130
console.log('\x1b[32mAll files are valid\x1b[0m');
131
}
132
}).catch(err => {
133
console.error(err);
134
process.exit(1);
135
});
136
//# sourceMappingURL=verify-macho.js.map
137