@flighthq/abc 0.3.0-edge.1516.1b4fb2b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abcFile.d.ts +3 -0
- package/dist/abcFile.d.ts.map +1 -0
- package/dist/abcFile.js +388 -0
- package/dist/abcFile.js.map +1 -0
- package/dist/abcInstruction.d.ts +3 -0
- package/dist/abcInstruction.d.ts.map +1 -0
- package/dist/abcInstruction.js +267 -0
- package/dist/abcInstruction.js.map +1 -0
- package/dist/contract.d.ts +3 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +3 -0
- package/dist/contract.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
- package/src/abcFile.test.ts +214 -0
- package/src/abcInstruction.test.ts +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abcFile.d.ts","sourceRoot":"","sources":["../src/abcFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,OAAO,EAWR,MAAM,0BAA0B,CAAC;AAWlC,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,IAAI,CAmE9D"}
|
package/dist/abcFile.js
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import { AbcMultinameKind, AbcTraitKind } from '@flighthq/types/contract';
|
|
2
|
+
// Reads an ABC (AVM2 bytecode) container into plain data, or null when the bytes are not a readable one.
|
|
3
|
+
// This parses; it never executes. What comes back is the file's own tables — constant pool, methods,
|
|
4
|
+
// classes, instances, scripts, and method bodies — with every cross-reference left as the index the format
|
|
5
|
+
// stored, so a consumer resolves only what it needs.
|
|
6
|
+
//
|
|
7
|
+
// Method bodies keep their instruction stream as raw bytes. Decoding instructions needs the whole opcode
|
|
8
|
+
// table and belongs in its own step, so a caller that only wants class names or trait layout never pays
|
|
9
|
+
// for it.
|
|
10
|
+
export function readAbcFile(source) {
|
|
11
|
+
const reader = new AbcReader(source);
|
|
12
|
+
const minorVersion = reader.readUint16();
|
|
13
|
+
const majorVersion = reader.readUint16();
|
|
14
|
+
if (!reader.valid)
|
|
15
|
+
return null;
|
|
16
|
+
const constantPool = readAbcConstantPool(reader);
|
|
17
|
+
if (constantPool === null)
|
|
18
|
+
return null;
|
|
19
|
+
const methods = [];
|
|
20
|
+
const methodCount = reader.readVarUint();
|
|
21
|
+
if (!reader.valid || methodCount > MAX_ENTRIES)
|
|
22
|
+
return null;
|
|
23
|
+
for (let i = 0; i < methodCount; i++) {
|
|
24
|
+
const method = readAbcMethod(reader);
|
|
25
|
+
if (method === null)
|
|
26
|
+
return null;
|
|
27
|
+
methods.push(method);
|
|
28
|
+
}
|
|
29
|
+
const metadata = [];
|
|
30
|
+
const metadataCount = reader.readVarUint();
|
|
31
|
+
if (!reader.valid || metadataCount > MAX_ENTRIES)
|
|
32
|
+
return null;
|
|
33
|
+
for (let i = 0; i < metadataCount; i++) {
|
|
34
|
+
const entry = readAbcMetadata(reader);
|
|
35
|
+
if (entry === null)
|
|
36
|
+
return null;
|
|
37
|
+
metadata.push(entry);
|
|
38
|
+
}
|
|
39
|
+
// Instances and classes are parallel lists sharing one count: every class has exactly one instance, and
|
|
40
|
+
// the format writes all instances before all classes.
|
|
41
|
+
const classCount = reader.readVarUint();
|
|
42
|
+
if (!reader.valid || classCount > MAX_ENTRIES)
|
|
43
|
+
return null;
|
|
44
|
+
const instances = [];
|
|
45
|
+
for (let i = 0; i < classCount; i++) {
|
|
46
|
+
const instance = readAbcInstance(reader);
|
|
47
|
+
if (instance === null)
|
|
48
|
+
return null;
|
|
49
|
+
instances.push(instance);
|
|
50
|
+
}
|
|
51
|
+
const classes = [];
|
|
52
|
+
for (let i = 0; i < classCount; i++) {
|
|
53
|
+
const initializer = reader.readVarUint();
|
|
54
|
+
const traits = readAbcTraits(reader);
|
|
55
|
+
if (traits === null)
|
|
56
|
+
return null;
|
|
57
|
+
classes.push({ initializer, traits });
|
|
58
|
+
}
|
|
59
|
+
const scripts = [];
|
|
60
|
+
const scriptCount = reader.readVarUint();
|
|
61
|
+
if (!reader.valid || scriptCount > MAX_ENTRIES)
|
|
62
|
+
return null;
|
|
63
|
+
for (let i = 0; i < scriptCount; i++) {
|
|
64
|
+
const initializer = reader.readVarUint();
|
|
65
|
+
const traits = readAbcTraits(reader);
|
|
66
|
+
if (traits === null)
|
|
67
|
+
return null;
|
|
68
|
+
scripts.push({ initializer, traits });
|
|
69
|
+
}
|
|
70
|
+
const methodBodies = [];
|
|
71
|
+
const bodyCount = reader.readVarUint();
|
|
72
|
+
if (!reader.valid || bodyCount > MAX_ENTRIES)
|
|
73
|
+
return null;
|
|
74
|
+
for (let i = 0; i < bodyCount; i++) {
|
|
75
|
+
const body = readAbcMethodBody(reader);
|
|
76
|
+
if (body === null)
|
|
77
|
+
return null;
|
|
78
|
+
methodBodies.push(body);
|
|
79
|
+
}
|
|
80
|
+
return reader.valid
|
|
81
|
+
? { classes, constantPool, instances, majorVersion, metadata, methodBodies, methods, minorVersion, scripts }
|
|
82
|
+
: null;
|
|
83
|
+
}
|
|
84
|
+
// Every constant pool is 1-based: the format writes a count that is one more than the number of entries
|
|
85
|
+
// stored, and index 0 is a reserved placeholder no entry ever occupies. The placeholders are materialized
|
|
86
|
+
// here so a consumer can index the arrays directly with the indices the file carries.
|
|
87
|
+
function readAbcConstantPool(reader) {
|
|
88
|
+
const integers = [0];
|
|
89
|
+
if (!readAbcPool(reader, integers, () => reader.readVarInt()))
|
|
90
|
+
return null;
|
|
91
|
+
const unsignedIntegers = [0];
|
|
92
|
+
if (!readAbcPool(reader, unsignedIntegers, () => reader.readVarUint()))
|
|
93
|
+
return null;
|
|
94
|
+
const doubles = [Number.NaN];
|
|
95
|
+
if (!readAbcPool(reader, doubles, () => reader.readDouble()))
|
|
96
|
+
return null;
|
|
97
|
+
const strings = [''];
|
|
98
|
+
if (!readAbcPool(reader, strings, () => reader.readString()))
|
|
99
|
+
return null;
|
|
100
|
+
const namespaces = [{ kind: 0, name: 0 }];
|
|
101
|
+
if (!readAbcPool(reader, namespaces, () => ({ kind: reader.readUint8(), name: reader.readVarUint() })))
|
|
102
|
+
return null;
|
|
103
|
+
const namespaceSets = [[]];
|
|
104
|
+
if (!readAbcPool(reader, namespaceSets, () => {
|
|
105
|
+
const count = reader.readVarUint();
|
|
106
|
+
if (count > MAX_ENTRIES)
|
|
107
|
+
return null;
|
|
108
|
+
const set = [];
|
|
109
|
+
for (let i = 0; i < count; i++)
|
|
110
|
+
set.push(reader.readVarUint());
|
|
111
|
+
return set;
|
|
112
|
+
})) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const multinames = [createAbcMultiname(0)];
|
|
116
|
+
if (!readAbcPool(reader, multinames, () => readAbcMultiname(reader)))
|
|
117
|
+
return null;
|
|
118
|
+
return reader.valid ? { doubles, integers, multinames, namespaceSets, namespaces, strings, unsignedIntegers } : null;
|
|
119
|
+
}
|
|
120
|
+
function readAbcPool(reader, out, read) {
|
|
121
|
+
const count = reader.readVarUint();
|
|
122
|
+
if (!reader.valid || count > MAX_ENTRIES)
|
|
123
|
+
return false;
|
|
124
|
+
for (let i = 1; i < count; i++) {
|
|
125
|
+
const entry = read();
|
|
126
|
+
if (entry === null || !reader.valid)
|
|
127
|
+
return false;
|
|
128
|
+
out.push(entry);
|
|
129
|
+
}
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
function createAbcMultiname(kind) {
|
|
133
|
+
return { kind, name: 0, namespace: 0, namespaceSet: 0, parameters: [], typeName: 0 };
|
|
134
|
+
}
|
|
135
|
+
function readAbcMultiname(reader) {
|
|
136
|
+
const multiname = createAbcMultiname(reader.readUint8());
|
|
137
|
+
if (multiname.kind === AbcMultinameKind.QName || multiname.kind === AbcMultinameKind.QNameA) {
|
|
138
|
+
multiname.namespace = reader.readVarUint();
|
|
139
|
+
multiname.name = reader.readVarUint();
|
|
140
|
+
}
|
|
141
|
+
else if (multiname.kind === AbcMultinameKind.RtqName || multiname.kind === AbcMultinameKind.RtqNameA) {
|
|
142
|
+
multiname.name = reader.readVarUint();
|
|
143
|
+
}
|
|
144
|
+
else if (multiname.kind === AbcMultinameKind.RtqNameL || multiname.kind === AbcMultinameKind.RtqNameLA) {
|
|
145
|
+
// Both parts come off the operand stack at runtime, so the record carries nothing.
|
|
146
|
+
}
|
|
147
|
+
else if (multiname.kind === AbcMultinameKind.Multiname || multiname.kind === AbcMultinameKind.MultinameA) {
|
|
148
|
+
multiname.name = reader.readVarUint();
|
|
149
|
+
multiname.namespaceSet = reader.readVarUint();
|
|
150
|
+
}
|
|
151
|
+
else if (multiname.kind === AbcMultinameKind.MultinameL || multiname.kind === AbcMultinameKind.MultinameLA) {
|
|
152
|
+
multiname.namespaceSet = reader.readVarUint();
|
|
153
|
+
}
|
|
154
|
+
else if (multiname.kind === AbcMultinameKind.TypeName) {
|
|
155
|
+
multiname.typeName = reader.readVarUint();
|
|
156
|
+
const count = reader.readVarUint();
|
|
157
|
+
if (count > MAX_ENTRIES)
|
|
158
|
+
return null;
|
|
159
|
+
for (let i = 0; i < count; i++)
|
|
160
|
+
multiname.parameters.push(reader.readVarUint());
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return reader.valid ? multiname : null;
|
|
166
|
+
}
|
|
167
|
+
function readAbcMethod(reader) {
|
|
168
|
+
const parameterCount = reader.readVarUint();
|
|
169
|
+
if (!reader.valid || parameterCount > MAX_ENTRIES)
|
|
170
|
+
return null;
|
|
171
|
+
const returnType = reader.readVarUint();
|
|
172
|
+
const parameterTypes = [];
|
|
173
|
+
for (let i = 0; i < parameterCount; i++)
|
|
174
|
+
parameterTypes.push(reader.readVarUint());
|
|
175
|
+
const name = reader.readVarUint();
|
|
176
|
+
const flags = reader.readUint8();
|
|
177
|
+
if (!reader.valid)
|
|
178
|
+
return null;
|
|
179
|
+
const optionalValues = [];
|
|
180
|
+
if ((flags & METHOD_HAS_OPTIONAL) !== 0) {
|
|
181
|
+
const count = reader.readVarUint();
|
|
182
|
+
if (!reader.valid || count > MAX_ENTRIES)
|
|
183
|
+
return null;
|
|
184
|
+
for (let i = 0; i < count; i++)
|
|
185
|
+
optionalValues.push({ kind: 0, value: reader.readVarUint() });
|
|
186
|
+
for (const optional of optionalValues)
|
|
187
|
+
optional.kind = reader.readUint8();
|
|
188
|
+
}
|
|
189
|
+
const parameterNames = [];
|
|
190
|
+
if ((flags & METHOD_HAS_PARAM_NAMES) !== 0) {
|
|
191
|
+
for (let i = 0; i < parameterCount; i++)
|
|
192
|
+
parameterNames.push(reader.readVarUint());
|
|
193
|
+
}
|
|
194
|
+
return reader.valid ? { flags, name, optionalValues, parameterNames, parameterTypes, returnType } : null;
|
|
195
|
+
}
|
|
196
|
+
function readAbcMetadata(reader) {
|
|
197
|
+
const name = reader.readVarUint();
|
|
198
|
+
const count = reader.readVarUint();
|
|
199
|
+
if (!reader.valid || count > MAX_ENTRIES)
|
|
200
|
+
return null;
|
|
201
|
+
const items = [];
|
|
202
|
+
for (let i = 0; i < count; i++)
|
|
203
|
+
items.push({ key: reader.readVarUint(), value: reader.readVarUint() });
|
|
204
|
+
return reader.valid ? { items, name } : null;
|
|
205
|
+
}
|
|
206
|
+
function readAbcInstance(reader) {
|
|
207
|
+
const name = reader.readVarUint();
|
|
208
|
+
const superName = reader.readVarUint();
|
|
209
|
+
const flags = reader.readUint8();
|
|
210
|
+
const protectedNamespace = (flags & INSTANCE_PROTECTED_NAMESPACE) !== 0 ? reader.readVarUint() : 0;
|
|
211
|
+
const interfaceCount = reader.readVarUint();
|
|
212
|
+
if (!reader.valid || interfaceCount > MAX_ENTRIES)
|
|
213
|
+
return null;
|
|
214
|
+
const interfaces = [];
|
|
215
|
+
for (let i = 0; i < interfaceCount; i++)
|
|
216
|
+
interfaces.push(reader.readVarUint());
|
|
217
|
+
const initializer = reader.readVarUint();
|
|
218
|
+
const traits = readAbcTraits(reader);
|
|
219
|
+
if (traits === null)
|
|
220
|
+
return null;
|
|
221
|
+
return { flags, initializer, interfaces, name, protectedNamespace, superName, traits };
|
|
222
|
+
}
|
|
223
|
+
function readAbcTraits(reader) {
|
|
224
|
+
const count = reader.readVarUint();
|
|
225
|
+
if (!reader.valid || count > MAX_ENTRIES)
|
|
226
|
+
return null;
|
|
227
|
+
const traits = [];
|
|
228
|
+
for (let i = 0; i < count; i++) {
|
|
229
|
+
const trait = readAbcTrait(reader);
|
|
230
|
+
if (trait === null)
|
|
231
|
+
return null;
|
|
232
|
+
traits.push(trait);
|
|
233
|
+
}
|
|
234
|
+
return traits;
|
|
235
|
+
}
|
|
236
|
+
function readAbcTrait(reader) {
|
|
237
|
+
const name = reader.readVarUint();
|
|
238
|
+
const packed = reader.readUint8();
|
|
239
|
+
if (!reader.valid)
|
|
240
|
+
return null;
|
|
241
|
+
const kind = packed & 0x0f;
|
|
242
|
+
const trait = {
|
|
243
|
+
attributes: packed >> 4,
|
|
244
|
+
classIndex: 0,
|
|
245
|
+
dispatchId: 0,
|
|
246
|
+
kind,
|
|
247
|
+
metadata: [],
|
|
248
|
+
methodIndex: 0,
|
|
249
|
+
name,
|
|
250
|
+
slotId: 0,
|
|
251
|
+
typeName: 0,
|
|
252
|
+
valueIndex: 0,
|
|
253
|
+
valueKind: 0,
|
|
254
|
+
};
|
|
255
|
+
if (kind === AbcTraitKind.Slot || kind === AbcTraitKind.Const) {
|
|
256
|
+
trait.slotId = reader.readVarUint();
|
|
257
|
+
trait.typeName = reader.readVarUint();
|
|
258
|
+
trait.valueIndex = reader.readVarUint();
|
|
259
|
+
// A default of index 0 has no kind byte, because there is no value to name a pool for.
|
|
260
|
+
if (trait.valueIndex !== 0)
|
|
261
|
+
trait.valueKind = reader.readUint8();
|
|
262
|
+
}
|
|
263
|
+
else if (kind === AbcTraitKind.Class) {
|
|
264
|
+
trait.slotId = reader.readVarUint();
|
|
265
|
+
trait.classIndex = reader.readVarUint();
|
|
266
|
+
}
|
|
267
|
+
else if (kind === AbcTraitKind.Function) {
|
|
268
|
+
trait.slotId = reader.readVarUint();
|
|
269
|
+
trait.methodIndex = reader.readVarUint();
|
|
270
|
+
}
|
|
271
|
+
else if (kind === AbcTraitKind.Method || kind === AbcTraitKind.Getter || kind === AbcTraitKind.Setter) {
|
|
272
|
+
trait.dispatchId = reader.readVarUint();
|
|
273
|
+
trait.methodIndex = reader.readVarUint();
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
if ((trait.attributes & TRAIT_ATTRIBUTE_METADATA) !== 0) {
|
|
279
|
+
const count = reader.readVarUint();
|
|
280
|
+
if (!reader.valid || count > MAX_ENTRIES)
|
|
281
|
+
return null;
|
|
282
|
+
for (let i = 0; i < count; i++)
|
|
283
|
+
trait.metadata.push(reader.readVarUint());
|
|
284
|
+
}
|
|
285
|
+
return reader.valid ? trait : null;
|
|
286
|
+
}
|
|
287
|
+
function readAbcMethodBody(reader) {
|
|
288
|
+
const method = reader.readVarUint();
|
|
289
|
+
const maxStack = reader.readVarUint();
|
|
290
|
+
const localCount = reader.readVarUint();
|
|
291
|
+
const initScopeDepth = reader.readVarUint();
|
|
292
|
+
const maxScopeDepth = reader.readVarUint();
|
|
293
|
+
const codeLength = reader.readVarUint();
|
|
294
|
+
if (!reader.valid || codeLength > reader.remaining())
|
|
295
|
+
return null;
|
|
296
|
+
const code = reader.readBytes(codeLength);
|
|
297
|
+
const exceptionCount = reader.readVarUint();
|
|
298
|
+
if (!reader.valid || exceptionCount > MAX_ENTRIES)
|
|
299
|
+
return null;
|
|
300
|
+
const exceptions = [];
|
|
301
|
+
for (let i = 0; i < exceptionCount; i++) {
|
|
302
|
+
exceptions.push({
|
|
303
|
+
exceptionType: 0,
|
|
304
|
+
from: reader.readVarUint(),
|
|
305
|
+
target: 0,
|
|
306
|
+
to: reader.readVarUint(),
|
|
307
|
+
variableName: 0,
|
|
308
|
+
});
|
|
309
|
+
const exception = exceptions[i];
|
|
310
|
+
exception.target = reader.readVarUint();
|
|
311
|
+
exception.exceptionType = reader.readVarUint();
|
|
312
|
+
exception.variableName = reader.readVarUint();
|
|
313
|
+
}
|
|
314
|
+
const traits = readAbcTraits(reader);
|
|
315
|
+
if (traits === null)
|
|
316
|
+
return null;
|
|
317
|
+
return { code, exceptions, initScopeDepth, localCount, maxScopeDepth, maxStack, method, traits };
|
|
318
|
+
}
|
|
319
|
+
// A bounded little-endian reader over the primitives ABC is written in. Like the rest of Flight's byte
|
|
320
|
+
// readers it reports an overrun through `valid` rather than throwing, so a caller checks once after a
|
|
321
|
+
// group of reads instead of testing each one.
|
|
322
|
+
class AbcReader {
|
|
323
|
+
source;
|
|
324
|
+
pos = 0;
|
|
325
|
+
valid = true;
|
|
326
|
+
constructor(source) {
|
|
327
|
+
this.source = source;
|
|
328
|
+
}
|
|
329
|
+
readBytes(count) {
|
|
330
|
+
if (this.pos + count > this.source.length) {
|
|
331
|
+
this.valid = false;
|
|
332
|
+
return new Uint8Array(0);
|
|
333
|
+
}
|
|
334
|
+
const value = this.source.subarray(this.pos, this.pos + count);
|
|
335
|
+
this.pos += count;
|
|
336
|
+
return value;
|
|
337
|
+
}
|
|
338
|
+
readDouble() {
|
|
339
|
+
if (this.pos + 8 > this.source.length) {
|
|
340
|
+
this.valid = false;
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
const value = new DataView(this.source.buffer, this.source.byteOffset + this.pos, 8).getFloat64(0, true);
|
|
344
|
+
this.pos += 8;
|
|
345
|
+
return value;
|
|
346
|
+
}
|
|
347
|
+
// The format's variable-length integer: seven bits per byte, least significant group first, at most five
|
|
348
|
+
// bytes. Read as a signed 32-bit value.
|
|
349
|
+
readVarInt() {
|
|
350
|
+
return this.readVarUint() | 0;
|
|
351
|
+
}
|
|
352
|
+
readString() {
|
|
353
|
+
const length = this.readVarUint();
|
|
354
|
+
return this.valid ? _decoder.decode(this.readBytes(length)) : '';
|
|
355
|
+
}
|
|
356
|
+
readUint8() {
|
|
357
|
+
if (this.pos >= this.source.length) {
|
|
358
|
+
this.valid = false;
|
|
359
|
+
return 0;
|
|
360
|
+
}
|
|
361
|
+
return this.source[this.pos++];
|
|
362
|
+
}
|
|
363
|
+
readUint16() {
|
|
364
|
+
const low = this.readUint8();
|
|
365
|
+
return low + this.readUint8() * 0x100;
|
|
366
|
+
}
|
|
367
|
+
readVarUint() {
|
|
368
|
+
let value = 0;
|
|
369
|
+
for (let i = 0; i < VAR_UINT_MAX_BYTES; i++) {
|
|
370
|
+
const byte = this.readUint8();
|
|
371
|
+
value += (byte & 0x7f) * 2 ** (7 * i);
|
|
372
|
+
if ((byte & 0x80) === 0)
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
return this.valid ? value : 0;
|
|
376
|
+
}
|
|
377
|
+
remaining() {
|
|
378
|
+
return this.source.length - this.pos;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const INSTANCE_PROTECTED_NAMESPACE = 0x08;
|
|
382
|
+
const MAX_ENTRIES = 1_000_000;
|
|
383
|
+
const METHOD_HAS_OPTIONAL = 0x08;
|
|
384
|
+
const METHOD_HAS_PARAM_NAMES = 0x80;
|
|
385
|
+
const TRAIT_ATTRIBUTE_METADATA = 0x04;
|
|
386
|
+
const VAR_UINT_MAX_BYTES = 5;
|
|
387
|
+
const _decoder = new TextDecoder();
|
|
388
|
+
//# sourceMappingURL=abcFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abcFile.js","sourceRoot":"","sources":["../src/abcFile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abcInstruction.d.ts","sourceRoot":"","sources":["../src/abcInstruction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAY/D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,cAAc,EAAE,GAAG,IAAI,CAoDvF"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { AbcOpcode } from '@flighthq/types/contract';
|
|
2
|
+
// Decodes a method body's instruction stream into a flat list, or null when it does not decode cleanly.
|
|
3
|
+
//
|
|
4
|
+
// Walking AVM2 bytecode requires knowing every opcode's operand shape, because instructions are variable
|
|
5
|
+
// width and there is no way to resynchronize after a miss — an unrecognized opcode therefore stops the
|
|
6
|
+
// walk and reports null rather than guessing a width and returning plausible nonsense.
|
|
7
|
+
//
|
|
8
|
+
// The operand-shape table below is written from the published bytecode format description. An opcode's
|
|
9
|
+
// number and the operands it declares are facts about the format; nothing here is derived from any
|
|
10
|
+
// implementation of it, so this carries no third-party licence obligation.
|
|
11
|
+
export function readAbcInstructions(code) {
|
|
12
|
+
const source = code;
|
|
13
|
+
const instructions = [];
|
|
14
|
+
let pos = 0;
|
|
15
|
+
while (pos < source.length) {
|
|
16
|
+
const offset = pos;
|
|
17
|
+
const opcode = source[pos++];
|
|
18
|
+
const operands = [];
|
|
19
|
+
if (opcode === AbcOpcode.LookupSwitch) {
|
|
20
|
+
// The one variable-length instruction: a default target, a case count, and one more target than the
|
|
21
|
+
// count says, because the count is the highest index rather than the number of cases.
|
|
22
|
+
const target = readAbcSignedOffset(source, pos);
|
|
23
|
+
if (target === null)
|
|
24
|
+
return null;
|
|
25
|
+
operands.push(target);
|
|
26
|
+
pos += 3;
|
|
27
|
+
const count = readAbcVarUint(source, pos);
|
|
28
|
+
if (count === null || count.value > MAX_SWITCH_CASES)
|
|
29
|
+
return null;
|
|
30
|
+
operands.push(count.value);
|
|
31
|
+
pos = count.pos;
|
|
32
|
+
for (let i = 0; i <= count.value; i++) {
|
|
33
|
+
const caseTarget = readAbcSignedOffset(source, pos);
|
|
34
|
+
if (caseTarget === null)
|
|
35
|
+
return null;
|
|
36
|
+
operands.push(caseTarget);
|
|
37
|
+
pos += 3;
|
|
38
|
+
}
|
|
39
|
+
instructions.push({ offset, opcode, operands });
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const shape = OPERAND_SHAPES[opcode];
|
|
43
|
+
if (shape === undefined)
|
|
44
|
+
return null;
|
|
45
|
+
for (const kind of shape) {
|
|
46
|
+
if (kind === OPERAND_BYTE) {
|
|
47
|
+
if (pos >= source.length)
|
|
48
|
+
return null;
|
|
49
|
+
operands.push(source[pos++]);
|
|
50
|
+
}
|
|
51
|
+
else if (kind === OPERAND_SIGNED_OFFSET) {
|
|
52
|
+
const value = readAbcSignedOffset(source, pos);
|
|
53
|
+
if (value === null)
|
|
54
|
+
return null;
|
|
55
|
+
operands.push(value);
|
|
56
|
+
pos += 3;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const value = readAbcVarUint(source, pos);
|
|
60
|
+
if (value === null)
|
|
61
|
+
return null;
|
|
62
|
+
operands.push(value.value);
|
|
63
|
+
pos = value.pos;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
instructions.push({ offset, opcode, operands });
|
|
67
|
+
}
|
|
68
|
+
return instructions;
|
|
69
|
+
}
|
|
70
|
+
// A branch target: three bytes, little-endian, sign-extended from 24 bits. Targets are relative to the
|
|
71
|
+
// instruction that follows the branch.
|
|
72
|
+
function readAbcSignedOffset(source, pos) {
|
|
73
|
+
if (pos + 3 > source.length)
|
|
74
|
+
return null;
|
|
75
|
+
const value = source[pos] + source[pos + 1] * 0x100 + source[pos + 2] * 0x10000;
|
|
76
|
+
return value >= 0x800000 ? value - 0x1000000 : value;
|
|
77
|
+
}
|
|
78
|
+
function readAbcVarUint(source, pos) {
|
|
79
|
+
let value = 0;
|
|
80
|
+
let cursor = pos;
|
|
81
|
+
for (let i = 0; i < VAR_UINT_MAX_BYTES; i++) {
|
|
82
|
+
if (cursor >= source.length)
|
|
83
|
+
return null;
|
|
84
|
+
const byte = source[cursor++];
|
|
85
|
+
value += (byte & 0x7f) * 2 ** (7 * i);
|
|
86
|
+
if ((byte & 0x80) === 0)
|
|
87
|
+
return { pos: cursor, value };
|
|
88
|
+
}
|
|
89
|
+
return { pos: cursor, value };
|
|
90
|
+
}
|
|
91
|
+
const OPERAND_BYTE = 0;
|
|
92
|
+
const OPERAND_SIGNED_OFFSET = 1;
|
|
93
|
+
const OPERAND_VAR_UINT = 2;
|
|
94
|
+
const NONE = [];
|
|
95
|
+
const ONE_VAR_UINT = [OPERAND_VAR_UINT];
|
|
96
|
+
const TWO_VAR_UINT = [OPERAND_VAR_UINT, OPERAND_VAR_UINT];
|
|
97
|
+
const ONE_OFFSET = [OPERAND_SIGNED_OFFSET];
|
|
98
|
+
const ONE_BYTE = [OPERAND_BYTE];
|
|
99
|
+
// Opcode to operand shape. Every opcode the format defines appears here; anything absent stops a walk.
|
|
100
|
+
const OPERAND_SHAPES = {
|
|
101
|
+
[AbcOpcode.Add]: NONE,
|
|
102
|
+
[AbcOpcode.AddInt]: NONE,
|
|
103
|
+
[AbcOpcode.ApplyType]: ONE_VAR_UINT,
|
|
104
|
+
[AbcOpcode.AsType]: ONE_VAR_UINT,
|
|
105
|
+
[AbcOpcode.AsTypeLate]: NONE,
|
|
106
|
+
[AbcOpcode.BitAnd]: NONE,
|
|
107
|
+
[AbcOpcode.BitNot]: NONE,
|
|
108
|
+
[AbcOpcode.BitOr]: NONE,
|
|
109
|
+
[AbcOpcode.BitXor]: NONE,
|
|
110
|
+
[AbcOpcode.Breakpoint]: NONE,
|
|
111
|
+
[AbcOpcode.BreakpointLine]: ONE_VAR_UINT,
|
|
112
|
+
[AbcOpcode.Call]: ONE_VAR_UINT,
|
|
113
|
+
[AbcOpcode.CallMethod]: TWO_VAR_UINT,
|
|
114
|
+
[AbcOpcode.CallPropLex]: TWO_VAR_UINT,
|
|
115
|
+
[AbcOpcode.CallPropVoid]: TWO_VAR_UINT,
|
|
116
|
+
[AbcOpcode.CallProperty]: TWO_VAR_UINT,
|
|
117
|
+
[AbcOpcode.CallStatic]: TWO_VAR_UINT,
|
|
118
|
+
[AbcOpcode.CallSuper]: TWO_VAR_UINT,
|
|
119
|
+
[AbcOpcode.CallSuperVoid]: TWO_VAR_UINT,
|
|
120
|
+
[AbcOpcode.CheckFilter]: NONE,
|
|
121
|
+
[AbcOpcode.Coerce]: ONE_VAR_UINT,
|
|
122
|
+
[AbcOpcode.CoerceAny]: NONE,
|
|
123
|
+
[AbcOpcode.CoerceBoolean]: NONE,
|
|
124
|
+
[AbcOpcode.CoerceDouble]: NONE,
|
|
125
|
+
[AbcOpcode.CoerceInt]: NONE,
|
|
126
|
+
[AbcOpcode.CoerceObject]: NONE,
|
|
127
|
+
[AbcOpcode.CoerceString]: NONE,
|
|
128
|
+
[AbcOpcode.CoerceUint]: NONE,
|
|
129
|
+
[AbcOpcode.Construct]: ONE_VAR_UINT,
|
|
130
|
+
[AbcOpcode.ConstructProp]: TWO_VAR_UINT,
|
|
131
|
+
[AbcOpcode.ConstructSuper]: ONE_VAR_UINT,
|
|
132
|
+
[AbcOpcode.ConvertBoolean]: NONE,
|
|
133
|
+
[AbcOpcode.ConvertDouble]: NONE,
|
|
134
|
+
[AbcOpcode.ConvertInt]: NONE,
|
|
135
|
+
[AbcOpcode.ConvertObject]: NONE,
|
|
136
|
+
[AbcOpcode.ConvertString]: NONE,
|
|
137
|
+
[AbcOpcode.ConvertUint]: NONE,
|
|
138
|
+
[AbcOpcode.Debug]: [OPERAND_BYTE, OPERAND_VAR_UINT, OPERAND_BYTE, OPERAND_VAR_UINT],
|
|
139
|
+
[AbcOpcode.DebugFile]: ONE_VAR_UINT,
|
|
140
|
+
[AbcOpcode.DebugLine]: ONE_VAR_UINT,
|
|
141
|
+
[AbcOpcode.DecLocal]: ONE_VAR_UINT,
|
|
142
|
+
[AbcOpcode.DecLocalInt]: ONE_VAR_UINT,
|
|
143
|
+
[AbcOpcode.Decrement]: NONE,
|
|
144
|
+
[AbcOpcode.DecrementInt]: NONE,
|
|
145
|
+
[AbcOpcode.DeleteProperty]: ONE_VAR_UINT,
|
|
146
|
+
[AbcOpcode.Divide]: NONE,
|
|
147
|
+
[AbcOpcode.Dup]: NONE,
|
|
148
|
+
[AbcOpcode.Dxns]: ONE_VAR_UINT,
|
|
149
|
+
[AbcOpcode.DxnsLate]: NONE,
|
|
150
|
+
[AbcOpcode.Equals]: NONE,
|
|
151
|
+
[AbcOpcode.FindDef]: ONE_VAR_UINT,
|
|
152
|
+
[AbcOpcode.FindPropStrict]: ONE_VAR_UINT,
|
|
153
|
+
[AbcOpcode.FindProperty]: ONE_VAR_UINT,
|
|
154
|
+
[AbcOpcode.GetDescendants]: ONE_VAR_UINT,
|
|
155
|
+
[AbcOpcode.GetGlobalScope]: NONE,
|
|
156
|
+
[AbcOpcode.GetGlobalSlot]: ONE_VAR_UINT,
|
|
157
|
+
[AbcOpcode.GetLex]: ONE_VAR_UINT,
|
|
158
|
+
[AbcOpcode.GetLocal]: ONE_VAR_UINT,
|
|
159
|
+
[AbcOpcode.GetLocal0]: NONE,
|
|
160
|
+
[AbcOpcode.GetLocal1]: NONE,
|
|
161
|
+
[AbcOpcode.GetLocal2]: NONE,
|
|
162
|
+
[AbcOpcode.GetLocal3]: NONE,
|
|
163
|
+
[AbcOpcode.GetProperty]: ONE_VAR_UINT,
|
|
164
|
+
[AbcOpcode.GetScopeObject]: ONE_BYTE,
|
|
165
|
+
[AbcOpcode.GetSlot]: ONE_VAR_UINT,
|
|
166
|
+
[AbcOpcode.GetSuper]: ONE_VAR_UINT,
|
|
167
|
+
[AbcOpcode.GreaterEquals]: NONE,
|
|
168
|
+
[AbcOpcode.GreaterThan]: NONE,
|
|
169
|
+
[AbcOpcode.HasNext]: NONE,
|
|
170
|
+
[AbcOpcode.HasNext2]: TWO_VAR_UINT,
|
|
171
|
+
[AbcOpcode.IfEq]: ONE_OFFSET,
|
|
172
|
+
[AbcOpcode.IfFalse]: ONE_OFFSET,
|
|
173
|
+
[AbcOpcode.IfGe]: ONE_OFFSET,
|
|
174
|
+
[AbcOpcode.IfGt]: ONE_OFFSET,
|
|
175
|
+
[AbcOpcode.IfLe]: ONE_OFFSET,
|
|
176
|
+
[AbcOpcode.IfLt]: ONE_OFFSET,
|
|
177
|
+
[AbcOpcode.IfNe]: ONE_OFFSET,
|
|
178
|
+
[AbcOpcode.IfNge]: ONE_OFFSET,
|
|
179
|
+
[AbcOpcode.IfNgt]: ONE_OFFSET,
|
|
180
|
+
[AbcOpcode.IfNle]: ONE_OFFSET,
|
|
181
|
+
[AbcOpcode.IfNlt]: ONE_OFFSET,
|
|
182
|
+
[AbcOpcode.IfStrictEq]: ONE_OFFSET,
|
|
183
|
+
[AbcOpcode.IfStrictNe]: ONE_OFFSET,
|
|
184
|
+
[AbcOpcode.IfTrue]: ONE_OFFSET,
|
|
185
|
+
[AbcOpcode.In]: NONE,
|
|
186
|
+
[AbcOpcode.IncLocal]: ONE_VAR_UINT,
|
|
187
|
+
[AbcOpcode.IncLocalInt]: ONE_VAR_UINT,
|
|
188
|
+
[AbcOpcode.Increment]: NONE,
|
|
189
|
+
[AbcOpcode.IncrementInt]: NONE,
|
|
190
|
+
[AbcOpcode.InitProperty]: ONE_VAR_UINT,
|
|
191
|
+
[AbcOpcode.InstanceOf]: NONE,
|
|
192
|
+
[AbcOpcode.IsType]: ONE_VAR_UINT,
|
|
193
|
+
[AbcOpcode.IsTypeLate]: NONE,
|
|
194
|
+
[AbcOpcode.Jump]: ONE_OFFSET,
|
|
195
|
+
[AbcOpcode.Kill]: ONE_VAR_UINT,
|
|
196
|
+
[AbcOpcode.LShift]: NONE,
|
|
197
|
+
[AbcOpcode.Label]: NONE,
|
|
198
|
+
[AbcOpcode.LessEquals]: NONE,
|
|
199
|
+
[AbcOpcode.LessThan]: NONE,
|
|
200
|
+
[AbcOpcode.LoadFloat32]: NONE,
|
|
201
|
+
[AbcOpcode.LoadFloat64]: NONE,
|
|
202
|
+
[AbcOpcode.LoadInt16]: NONE,
|
|
203
|
+
[AbcOpcode.LoadInt32]: NONE,
|
|
204
|
+
[AbcOpcode.LoadInt8]: NONE,
|
|
205
|
+
[AbcOpcode.Modulo]: NONE,
|
|
206
|
+
[AbcOpcode.Multiply]: NONE,
|
|
207
|
+
[AbcOpcode.MultiplyInt]: NONE,
|
|
208
|
+
[AbcOpcode.Negate]: NONE,
|
|
209
|
+
[AbcOpcode.NegateInt]: NONE,
|
|
210
|
+
[AbcOpcode.NewActivation]: NONE,
|
|
211
|
+
[AbcOpcode.NewArray]: ONE_VAR_UINT,
|
|
212
|
+
[AbcOpcode.NewCatch]: ONE_VAR_UINT,
|
|
213
|
+
[AbcOpcode.NewClass]: ONE_VAR_UINT,
|
|
214
|
+
[AbcOpcode.NewFunction]: ONE_VAR_UINT,
|
|
215
|
+
[AbcOpcode.NewObject]: ONE_VAR_UINT,
|
|
216
|
+
[AbcOpcode.NextName]: NONE,
|
|
217
|
+
[AbcOpcode.NextValue]: NONE,
|
|
218
|
+
[AbcOpcode.Nop]: NONE,
|
|
219
|
+
[AbcOpcode.Not]: NONE,
|
|
220
|
+
[AbcOpcode.Pop]: NONE,
|
|
221
|
+
[AbcOpcode.PopScope]: NONE,
|
|
222
|
+
[AbcOpcode.PushByte]: ONE_BYTE,
|
|
223
|
+
[AbcOpcode.PushDouble]: ONE_VAR_UINT,
|
|
224
|
+
[AbcOpcode.PushFalse]: NONE,
|
|
225
|
+
[AbcOpcode.PushInt]: ONE_VAR_UINT,
|
|
226
|
+
[AbcOpcode.PushNamespace]: ONE_VAR_UINT,
|
|
227
|
+
[AbcOpcode.PushNan]: NONE,
|
|
228
|
+
[AbcOpcode.PushNull]: NONE,
|
|
229
|
+
[AbcOpcode.PushScope]: NONE,
|
|
230
|
+
[AbcOpcode.PushShort]: ONE_VAR_UINT,
|
|
231
|
+
[AbcOpcode.PushString]: ONE_VAR_UINT,
|
|
232
|
+
[AbcOpcode.PushTrue]: NONE,
|
|
233
|
+
[AbcOpcode.PushUint]: ONE_VAR_UINT,
|
|
234
|
+
[AbcOpcode.PushUndefined]: NONE,
|
|
235
|
+
[AbcOpcode.PushWith]: NONE,
|
|
236
|
+
[AbcOpcode.RShift]: NONE,
|
|
237
|
+
[AbcOpcode.ReturnValue]: NONE,
|
|
238
|
+
[AbcOpcode.ReturnVoid]: NONE,
|
|
239
|
+
[AbcOpcode.SetGlobalSlot]: ONE_VAR_UINT,
|
|
240
|
+
[AbcOpcode.SetLocal]: ONE_VAR_UINT,
|
|
241
|
+
[AbcOpcode.SetLocal0]: NONE,
|
|
242
|
+
[AbcOpcode.SetLocal1]: NONE,
|
|
243
|
+
[AbcOpcode.SetLocal2]: NONE,
|
|
244
|
+
[AbcOpcode.SetLocal3]: NONE,
|
|
245
|
+
[AbcOpcode.SetProperty]: ONE_VAR_UINT,
|
|
246
|
+
[AbcOpcode.SetSlot]: ONE_VAR_UINT,
|
|
247
|
+
[AbcOpcode.SetSuper]: ONE_VAR_UINT,
|
|
248
|
+
[AbcOpcode.SignExtend1]: NONE,
|
|
249
|
+
[AbcOpcode.SignExtend16]: NONE,
|
|
250
|
+
[AbcOpcode.SignExtend8]: NONE,
|
|
251
|
+
[AbcOpcode.StoreFloat32]: NONE,
|
|
252
|
+
[AbcOpcode.StoreFloat64]: NONE,
|
|
253
|
+
[AbcOpcode.StoreInt16]: NONE,
|
|
254
|
+
[AbcOpcode.StoreInt32]: NONE,
|
|
255
|
+
[AbcOpcode.StoreInt8]: NONE,
|
|
256
|
+
[AbcOpcode.StrictEquals]: NONE,
|
|
257
|
+
[AbcOpcode.Subtract]: NONE,
|
|
258
|
+
[AbcOpcode.SubtractInt]: NONE,
|
|
259
|
+
[AbcOpcode.Swap]: NONE,
|
|
260
|
+
[AbcOpcode.Throw]: NONE,
|
|
261
|
+
[AbcOpcode.Timestamp]: ONE_VAR_UINT,
|
|
262
|
+
[AbcOpcode.TypeOf]: NONE,
|
|
263
|
+
[AbcOpcode.URShift]: NONE,
|
|
264
|
+
};
|
|
265
|
+
const MAX_SWITCH_CASES = 100_000;
|
|
266
|
+
const VAR_UINT_MAX_BYTES = 5;
|
|
267
|
+
//# sourceMappingURL=abcInstruction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abcInstruction.js","sourceRoot":"","sources":["../src/abcInstruction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC"}
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flighthq/abc",
|
|
3
|
+
"version": "0.3.0-edge.1516.1b4fb2b",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/flighthq/flight.git",
|
|
7
|
+
"directory": "packages/abc"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./contract": {
|
|
18
|
+
"types": "./dist/contract.d.ts",
|
|
19
|
+
"default": "./dist/contract.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"src/**/*.test.ts",
|
|
25
|
+
"!dist/**/*.test.js",
|
|
26
|
+
"!dist/**/*.test.d.ts",
|
|
27
|
+
"!dist/**/*.test.js.map",
|
|
28
|
+
"!dist/**/*.test.d.ts.map"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc -b",
|
|
32
|
+
"clean": "tsc -b --clean",
|
|
33
|
+
"test": "vitest run --config vitest.config.ts",
|
|
34
|
+
"test:watch": "vitest --watch --config vitest.config.ts",
|
|
35
|
+
"prepack": "npm run clean && npm run clean:dist && npm run build",
|
|
36
|
+
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@flighthq/types": "0.3.0-edge.1516.1b4fb2b"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"typescript": "^5.3.0"
|
|
43
|
+
},
|
|
44
|
+
"description": "ABC (AVM2) bytecode container parsing into plain data",
|
|
45
|
+
"sideEffects": false
|
|
46
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { AbcMultinameKind, AbcTraitKind } from '@flighthq/types/contract';
|
|
2
|
+
|
|
3
|
+
import { readAbcFile } from './abcFile';
|
|
4
|
+
|
|
5
|
+
describe('readAbcFile', () => {
|
|
6
|
+
it('reads the version and the whole constant pool, keeping the reserved zero entry', () => {
|
|
7
|
+
const file = readAbcFile(buildAbc());
|
|
8
|
+
|
|
9
|
+
expect(file?.minorVersion).toBe(16);
|
|
10
|
+
expect(file?.majorVersion).toBe(46);
|
|
11
|
+
// Index 0 of every pool is the placeholder the format reserves, so pool indices in the file's own
|
|
12
|
+
// records can be used directly.
|
|
13
|
+
expect(file?.constantPool.strings[0]).toBe('');
|
|
14
|
+
expect(file?.constantPool.strings.slice(1)).toEqual(['Main', 'stop', 'flash.display']);
|
|
15
|
+
expect(file?.constantPool.integers).toEqual([0, -7]);
|
|
16
|
+
expect(file?.constantPool.unsignedIntegers).toEqual([0, 9]);
|
|
17
|
+
expect(file?.constantPool.doubles[1]).toBeCloseTo(1.5);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('reads namespaces, namespace sets, and both multiname shapes', () => {
|
|
21
|
+
const file = readAbcFile(buildAbc());
|
|
22
|
+
|
|
23
|
+
expect(file?.constantPool.namespaces[1]).toEqual({ kind: 0x16, name: 3 });
|
|
24
|
+
expect(file?.constantPool.namespaceSets[1]).toEqual([1]);
|
|
25
|
+
|
|
26
|
+
const qualified = file!.constantPool.multinames[1];
|
|
27
|
+
expect(qualified.kind).toBe(AbcMultinameKind.QName);
|
|
28
|
+
expect(qualified.namespace).toBe(1);
|
|
29
|
+
expect(file?.constantPool.strings[qualified.name]).toBe('Main');
|
|
30
|
+
|
|
31
|
+
const multiname = file!.constantPool.multinames[2];
|
|
32
|
+
expect(multiname.kind).toBe(AbcMultinameKind.Multiname);
|
|
33
|
+
expect(file?.constantPool.strings[multiname.name]).toBe('stop');
|
|
34
|
+
expect(multiname.namespaceSet).toBe(1);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('reads methods with their optional defaults and parameter names', () => {
|
|
38
|
+
const file = readAbcFile(buildAbc());
|
|
39
|
+
|
|
40
|
+
expect(file?.methods).toHaveLength(2);
|
|
41
|
+
expect(file?.methods[0]).toMatchObject({ name: 2, parameterTypes: [], returnType: 0 });
|
|
42
|
+
expect(file?.methods[1].optionalValues).toEqual([{ kind: 0x03, value: 1 }]);
|
|
43
|
+
expect(file?.methods[1].parameterNames).toEqual([1]);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('reads instances and classes as parallel lists sharing one count', () => {
|
|
47
|
+
const file = readAbcFile(buildAbc());
|
|
48
|
+
|
|
49
|
+
expect(file?.instances).toHaveLength(1);
|
|
50
|
+
expect(file?.classes).toHaveLength(1);
|
|
51
|
+
expect(file?.instances[0]).toMatchObject({ initializer: 1, name: 1, superName: 1 });
|
|
52
|
+
expect(file?.instances[0].traits[0]).toMatchObject({ kind: AbcTraitKind.Method, methodIndex: 0 });
|
|
53
|
+
expect(file?.classes[0].initializer).toBe(0);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('reads script and method-body tables, keeping instruction bytes unparsed', () => {
|
|
57
|
+
const file = readAbcFile(buildAbc());
|
|
58
|
+
|
|
59
|
+
expect(file?.scripts[0]).toMatchObject({ initializer: 0 });
|
|
60
|
+
expect(file?.methodBodies).toHaveLength(1);
|
|
61
|
+
const body = file!.methodBodies[0];
|
|
62
|
+
expect(body).toMatchObject({ localCount: 1, maxStack: 2, method: 0 });
|
|
63
|
+
// The instruction stream is handed back whole: decoding it needs an opcode table and is a later step.
|
|
64
|
+
expect([...body.code]).toEqual([0xd0, 0x30, 0x47]);
|
|
65
|
+
expect(body.exceptions).toEqual([]);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('returns null rather than throwing for input that is not a readable container', () => {
|
|
69
|
+
expect(readAbcFile(new Uint8Array())).toBeNull();
|
|
70
|
+
expect(readAbcFile(new Uint8Array([0x10, 0x00, 0x2e, 0x00]))).toBeNull();
|
|
71
|
+
// Truncated part-way through the constant pool.
|
|
72
|
+
expect(readAbcFile(buildAbc().subarray(0, 12))).toBeNull();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('never throws on arbitrary bytes, whatever they happen to encode', () => {
|
|
76
|
+
// The reader's whole error contract is a null sentinel, and a container this size is mostly counts
|
|
77
|
+
// and indices, so the property worth asserting is that no byte sequence produces an exception.
|
|
78
|
+
let seed = 0x2f6a51b3;
|
|
79
|
+
const next = (): number => {
|
|
80
|
+
seed = (seed * 1664525 + 1013904223) >>> 0;
|
|
81
|
+
return seed;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
for (let i = 0; i < 500; i++) {
|
|
85
|
+
const bytes = new Uint8Array(next() % 200);
|
|
86
|
+
for (let b = 0; b < bytes.length; b++) bytes[b] = next() & 0xff;
|
|
87
|
+
expect(() => readAbcFile(bytes)).not.toThrow();
|
|
88
|
+
}
|
|
89
|
+
// And the same for mutations of a file that is otherwise well formed.
|
|
90
|
+
for (let i = 0; i < 500; i++) {
|
|
91
|
+
const mutant = buildAbc();
|
|
92
|
+
for (let f = 0; f < 3; f++) mutant[next() % mutant.length] = next() & 0xff;
|
|
93
|
+
expect(() => readAbcFile(mutant)).not.toThrow();
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('rejects a multiname whose kind the format does not define', () => {
|
|
98
|
+
const bytes = buildAbc();
|
|
99
|
+
// Overwrite the first multiname's kind byte with one no version of the format uses.
|
|
100
|
+
const index = bytes.indexOf(AbcMultinameKind.QName, 20);
|
|
101
|
+
bytes[index] = 0x7f;
|
|
102
|
+
|
|
103
|
+
expect(readAbcFile(bytes)).toBeNull();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Builds a small but structurally complete ABC file: three strings, one namespace and set, two multinames,
|
|
108
|
+
// two methods (one with an optional default and a parameter name), one class and instance with a method
|
|
109
|
+
// trait, one script, and one method body whose code is `getlocal_0; pushscope; returnvoid`.
|
|
110
|
+
function buildAbc(): Uint8Array {
|
|
111
|
+
const bytes: number[] = [];
|
|
112
|
+
const u8 = (value: number): void => void bytes.push(value & 0xff);
|
|
113
|
+
const u16 = (value: number): void => {
|
|
114
|
+
u8(value);
|
|
115
|
+
u8(value >> 8);
|
|
116
|
+
};
|
|
117
|
+
const u30 = (value: number): void => {
|
|
118
|
+
let remaining = value;
|
|
119
|
+
do {
|
|
120
|
+
const byte = remaining % 0x80;
|
|
121
|
+
remaining = Math.floor(remaining / 0x80);
|
|
122
|
+
u8(remaining > 0 ? byte | 0x80 : byte);
|
|
123
|
+
} while (remaining > 0);
|
|
124
|
+
};
|
|
125
|
+
const str = (value: string): void => {
|
|
126
|
+
const encoded = new TextEncoder().encode(value);
|
|
127
|
+
u30(encoded.length);
|
|
128
|
+
for (const byte of encoded) u8(byte);
|
|
129
|
+
};
|
|
130
|
+
const double = (value: number): void => {
|
|
131
|
+
const buffer = new ArrayBuffer(8);
|
|
132
|
+
new DataView(buffer).setFloat64(0, value, true);
|
|
133
|
+
for (const byte of new Uint8Array(buffer)) u8(byte);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
u16(16); // minor version
|
|
137
|
+
u16(46); // major version
|
|
138
|
+
|
|
139
|
+
u30(2); // int pool: one entry after the reserved slot
|
|
140
|
+
// A signed constant is written as its full 32-bit two's complement in the same seven-bits-per-byte
|
|
141
|
+
// form, so -7 occupies five bytes rather than one.
|
|
142
|
+
u30(0xfffffff9);
|
|
143
|
+
u30(2); // uint pool
|
|
144
|
+
u30(9);
|
|
145
|
+
u30(2); // double pool
|
|
146
|
+
double(1.5);
|
|
147
|
+
u30(4); // string pool
|
|
148
|
+
str('Main');
|
|
149
|
+
str('stop');
|
|
150
|
+
str('flash.display');
|
|
151
|
+
u30(2); // namespace pool
|
|
152
|
+
u8(0x16);
|
|
153
|
+
u30(3);
|
|
154
|
+
u30(2); // namespace set pool
|
|
155
|
+
u30(1);
|
|
156
|
+
u30(1);
|
|
157
|
+
u30(3); // multiname pool
|
|
158
|
+
u8(AbcMultinameKind.QName);
|
|
159
|
+
u30(1);
|
|
160
|
+
u30(1);
|
|
161
|
+
u8(AbcMultinameKind.Multiname);
|
|
162
|
+
u30(2);
|
|
163
|
+
u30(1);
|
|
164
|
+
|
|
165
|
+
u30(2); // method count
|
|
166
|
+
u30(0); // no parameters
|
|
167
|
+
u30(0); // return type
|
|
168
|
+
u30(2); // name -> 'stop'
|
|
169
|
+
u8(0); // flags
|
|
170
|
+
u30(1); // one parameter
|
|
171
|
+
u30(0);
|
|
172
|
+
u30(1);
|
|
173
|
+
u30(1);
|
|
174
|
+
u8(0x08 | 0x80); // has optional defaults, has parameter names
|
|
175
|
+
u30(1);
|
|
176
|
+
u30(1); // optional value index
|
|
177
|
+
u8(0x03); // optional value kind
|
|
178
|
+
u30(1); // parameter name
|
|
179
|
+
|
|
180
|
+
u30(0); // metadata count
|
|
181
|
+
|
|
182
|
+
u30(1); // class count
|
|
183
|
+
u30(1); // instance name
|
|
184
|
+
u30(1); // super name
|
|
185
|
+
u8(0); // flags
|
|
186
|
+
u30(0); // interface count
|
|
187
|
+
u30(1); // instance initializer
|
|
188
|
+
u30(1); // trait count
|
|
189
|
+
u30(2); // trait name
|
|
190
|
+
u8(AbcTraitKind.Method);
|
|
191
|
+
u30(0); // dispatch id
|
|
192
|
+
u30(0); // method index
|
|
193
|
+
u30(0); // class initializer
|
|
194
|
+
u30(0); // class trait count
|
|
195
|
+
|
|
196
|
+
u30(1); // script count
|
|
197
|
+
u30(0); // script initializer
|
|
198
|
+
u30(0); // script trait count
|
|
199
|
+
|
|
200
|
+
u30(1); // method body count
|
|
201
|
+
u30(0); // method
|
|
202
|
+
u30(2); // max stack
|
|
203
|
+
u30(1); // local count
|
|
204
|
+
u30(1); // init scope depth
|
|
205
|
+
u30(2); // max scope depth
|
|
206
|
+
u30(3); // code length
|
|
207
|
+
u8(0xd0);
|
|
208
|
+
u8(0x30);
|
|
209
|
+
u8(0x47);
|
|
210
|
+
u30(0); // exception count
|
|
211
|
+
u30(0); // trait count
|
|
212
|
+
|
|
213
|
+
return new Uint8Array(bytes);
|
|
214
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { AbcOpcode } from '@flighthq/types/contract';
|
|
2
|
+
|
|
3
|
+
import { readAbcInstructions } from './abcInstruction';
|
|
4
|
+
|
|
5
|
+
describe('readAbcInstructions', () => {
|
|
6
|
+
it('decodes the constructor prologue every compiled method opens with', () => {
|
|
7
|
+
const instructions = readAbcInstructions(new Uint8Array([0xd0, 0x30, 0x47]));
|
|
8
|
+
|
|
9
|
+
expect(instructions).toEqual([
|
|
10
|
+
{ offset: 0, opcode: AbcOpcode.GetLocal0, operands: [] },
|
|
11
|
+
{ offset: 1, opcode: AbcOpcode.PushScope, operands: [] },
|
|
12
|
+
{ offset: 2, opcode: AbcOpcode.ReturnVoid, operands: [] },
|
|
13
|
+
]);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('reads the operand shapes a call site uses, including two-operand calls', () => {
|
|
17
|
+
// findpropstrict <multiname 5>; pushbyte 2; callpropvoid <multiname 5>, 1
|
|
18
|
+
const instructions = readAbcInstructions(new Uint8Array([0x5d, 0x05, 0x24, 0x02, 0x4f, 0x05, 0x01]));
|
|
19
|
+
|
|
20
|
+
expect(instructions).toEqual([
|
|
21
|
+
{ offset: 0, opcode: AbcOpcode.FindPropStrict, operands: [5] },
|
|
22
|
+
{ offset: 2, opcode: AbcOpcode.PushByte, operands: [2] },
|
|
23
|
+
{ offset: 4, opcode: AbcOpcode.CallPropVoid, operands: [5, 1] },
|
|
24
|
+
]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('widens a multi-byte variable-length operand', () => {
|
|
28
|
+
// pushint with a two-byte operand: 0x81 0x01 encodes 129.
|
|
29
|
+
expect(readAbcInstructions(new Uint8Array([0x2d, 0x81, 0x01]))).toEqual([
|
|
30
|
+
{ offset: 0, opcode: AbcOpcode.PushInt, operands: [129] },
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('sign-extends a backward branch target', () => {
|
|
35
|
+
// jump -4, as three little-endian bytes.
|
|
36
|
+
expect(readAbcInstructions(new Uint8Array([0x10, 0xfc, 0xff, 0xff]))).toEqual([
|
|
37
|
+
{ offset: 0, opcode: AbcOpcode.Jump, operands: [-4] },
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('reads a lookupswitch, whose case count is one less than its target count', () => {
|
|
42
|
+
// default +7, case count 1, then two targets.
|
|
43
|
+
const instructions = readAbcInstructions(
|
|
44
|
+
new Uint8Array([0x1b, 0x07, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x0d, 0x00, 0x00]),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(instructions).toEqual([{ offset: 0, opcode: AbcOpcode.LookupSwitch, operands: [7, 1, 10, 13] }]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('stops rather than guessing when an opcode is not one the format defines', () => {
|
|
51
|
+
// There is no way to resynchronize a variable-width stream after an unknown opcode, so returning a
|
|
52
|
+
// partial decode would be returning plausible nonsense.
|
|
53
|
+
expect(readAbcInstructions(new Uint8Array([0xd0, 0xff, 0x47]))).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('reports a truncated operand rather than reading past the body', () => {
|
|
57
|
+
expect(readAbcInstructions(new Uint8Array([0x4f, 0x05]))).toBeNull();
|
|
58
|
+
expect(readAbcInstructions(new Uint8Array([0x10, 0xfc]))).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('places the deprecated typed coerce forms compilers still emit', () => {
|
|
62
|
+
// Found by decoding real compiler output: omitting these desynchronizes the rest of the body, because
|
|
63
|
+
// the walk then reads the following opcode as an operand.
|
|
64
|
+
expect(readAbcInstructions(new Uint8Array([0x81, 0x83, 0x84, 0x88, 0x89, 0x47]))).toEqual([
|
|
65
|
+
{ offset: 0, opcode: AbcOpcode.CoerceBoolean, operands: [] },
|
|
66
|
+
{ offset: 1, opcode: AbcOpcode.CoerceInt, operands: [] },
|
|
67
|
+
{ offset: 2, opcode: AbcOpcode.CoerceDouble, operands: [] },
|
|
68
|
+
{ offset: 3, opcode: AbcOpcode.CoerceUint, operands: [] },
|
|
69
|
+
{ offset: 4, opcode: AbcOpcode.CoerceObject, operands: [] },
|
|
70
|
+
{ offset: 5, opcode: AbcOpcode.ReturnVoid, operands: [] },
|
|
71
|
+
]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('decodes an empty body as no instructions', () => {
|
|
75
|
+
expect(readAbcInstructions(new Uint8Array())).toEqual([]);
|
|
76
|
+
});
|
|
77
|
+
});
|