@patrickdk77/archive-defuse 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +345 -2
- package/dist/aes7z.d.ts +16 -0
- package/dist/aes7z.js +131 -0
- package/dist/alone.d.ts +21 -0
- package/dist/alone.js +65 -0
- package/dist/bcj2.d.ts +21 -0
- package/dist/bcj2.js +140 -0
- package/dist/bzip2.d.ts +21 -0
- package/dist/bzip2.js +688 -0
- package/dist/cab.d.ts +63 -0
- package/dist/cab.js +493 -0
- package/dist/checks.d.ts +23 -0
- package/dist/checks.js +123 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +364 -0
- package/dist/codecs.d.ts +39 -0
- package/dist/codecs.js +124 -0
- package/dist/coders.d.ts +58 -0
- package/dist/coders.js +392 -0
- package/dist/crc32.d.ts +8 -0
- package/dist/crc32.js +59 -0
- package/dist/encoder.d.ts +44 -0
- package/dist/encoder.js +114 -0
- package/dist/engine.d.ts +44 -0
- package/dist/engine.js +753 -0
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +98 -0
- package/dist/filters.d.ts +34 -0
- package/dist/filters.js +385 -0
- package/dist/findings.d.ts +26 -0
- package/dist/findings.js +176 -0
- package/dist/formats.d.ts +14 -0
- package/dist/formats.js +97 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +50 -0
- package/dist/index.mjs +3 -0
- package/dist/inflate64.d.ts +6 -0
- package/dist/inflate64.js +388 -0
- package/dist/io.d.ts +78 -0
- package/dist/io.js +379 -0
- package/dist/lzma-formats.d.ts +75 -0
- package/dist/lzma-formats.js +373 -0
- package/dist/lzma-sniff.d.ts +20 -0
- package/dist/lzma-sniff.js +73 -0
- package/dist/lzma-writers.d.ts +35 -0
- package/dist/lzma-writers.js +276 -0
- package/dist/lzma1/LICENSE +201 -0
- package/dist/lzma1/NOTICE +36 -0
- package/dist/lzma1/crc32.d.ts +4 -0
- package/dist/lzma1/crc32.js +19 -0
- package/dist/lzma1/hash234.d.ts +22 -0
- package/dist/lzma1/hash234.js +75 -0
- package/dist/lzma1/hc4.d.ts +30 -0
- package/dist/lzma1/hc4.js +142 -0
- package/dist/lzma1/header.d.ts +32 -0
- package/dist/lzma1/header.js +73 -0
- package/dist/lzma1/lz-decoder.d.ts +41 -0
- package/dist/lzma1/lz-decoder.js +128 -0
- package/dist/lzma1/lz-encoder.d.ts +87 -0
- package/dist/lzma1/lz-encoder.js +166 -0
- package/dist/lzma1/lzma-coder.d.ts +107 -0
- package/dist/lzma1/lzma-coder.js +162 -0
- package/dist/lzma1/lzma-decoder.d.ts +36 -0
- package/dist/lzma1/lzma-decoder.js +484 -0
- package/dist/lzma1/lzma-encoder-fast.d.ts +13 -0
- package/dist/lzma1/lzma-encoder-fast.js +114 -0
- package/dist/lzma1/lzma-encoder.d.ts +105 -0
- package/dist/lzma1/lzma-encoder.js +497 -0
- package/dist/lzma1/lzma2-decoder.d.ts +85 -0
- package/dist/lzma1/lzma2-decoder.js +249 -0
- package/dist/lzma1/range-coder.d.ts +18 -0
- package/dist/lzma1/range-coder.js +23 -0
- package/dist/lzma1/range-decoder.d.ts +41 -0
- package/dist/lzma1/range-decoder.js +78 -0
- package/dist/lzma1/range-encoder.d.ts +53 -0
- package/dist/lzma1/range-encoder.js +269 -0
- package/dist/lzma1-stream.d.ts +60 -0
- package/dist/lzma1-stream.js +202 -0
- package/dist/model.d.ts +141 -0
- package/dist/model.js +16 -0
- package/dist/names.d.ts +13 -0
- package/dist/names.js +66 -0
- package/dist/pack.d.ts +72 -0
- package/dist/pack.js +514 -0
- package/dist/plugins.d.ts +13 -0
- package/dist/plugins.js +55 -0
- package/dist/rules.d.ts +25 -0
- package/dist/rules.js +403 -0
- package/dist/score.d.ts +17 -0
- package/dist/score.js +58 -0
- package/dist/seven.d.ts +75 -0
- package/dist/seven.js +492 -0
- package/dist/sevenzip.d.ts +133 -0
- package/dist/sevenzip.js +529 -0
- package/dist/single.d.ts +103 -0
- package/dist/single.js +453 -0
- package/dist/sniff.d.ts +20 -0
- package/dist/sniff.js +224 -0
- package/dist/stream-meter.d.ts +39 -0
- package/dist/stream-meter.js +54 -0
- package/dist/tar.d.ts +102 -0
- package/dist/tar.js +765 -0
- package/dist/types.d.ts +284 -0
- package/dist/types.js +133 -0
- package/dist/unpack.d.ts +67 -0
- package/dist/unpack.js +194 -0
- package/dist/xz.d.ts +25 -0
- package/dist/xz.js +333 -0
- package/dist/zip-lzma.d.ts +15 -0
- package/dist/zip-lzma.js +137 -0
- package/dist/zip-writer.d.ts +41 -0
- package/dist/zip-writer.js +263 -0
- package/dist/zip.d.ts +99 -0
- package/dist/zip.js +901 -0
- package/dist/zipcrypt.d.ts +47 -0
- package/dist/zipcrypt.js +233 -0
- package/dist/zstd.d.ts +25 -0
- package/dist/zstd.js +160 -0
- package/package.json +94 -4
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ArchiveCategory, ArchiveDetail } from './types';
|
|
2
|
+
/** The run passed its deadline. The code makes every package of the family pass it up instead of treating it as one plugin failing. */
|
|
3
|
+
export declare class TimeLimitError extends Error {
|
|
4
|
+
readonly code = "DEFUSE_LIMIT";
|
|
5
|
+
readonly limit = "time";
|
|
6
|
+
}
|
|
7
|
+
/** A file sits deeper in the upload than `limits.nestingDepth` allows. The code makes every package pass it up. */
|
|
8
|
+
export declare class NestingLimitError extends Error {
|
|
9
|
+
readonly code = "DEFUSE_LIMIT";
|
|
10
|
+
readonly limit = "nesting";
|
|
11
|
+
}
|
|
12
|
+
/** An I/O error inside a nested file's own run, carried up so the upload's run fails on it as on its own. */
|
|
13
|
+
export declare class NestedIoError extends Error {
|
|
14
|
+
readonly code = "DEFUSE_IO";
|
|
15
|
+
constructor(cause: unknown);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The code of an error that stops the whole tree of files, from any package: DEFUSE_LIMIT for a time or nesting
|
|
19
|
+
* limit, DEFUSE_IO for an I/O error. Packages cannot share error classes, so the code alone marks one.
|
|
20
|
+
*/
|
|
21
|
+
export declare function stopsTree(e: unknown): 'DEFUSE_LIMIT' | 'DEFUSE_IO' | undefined;
|
|
22
|
+
/** An error from the operating system, such as EIO or ENOSPC, which says nothing about the file. */
|
|
23
|
+
export declare const isIoError: (e: unknown) => boolean;
|
|
24
|
+
/**
|
|
25
|
+
* A refusal or a limit that stops the run. The engine turns it into the finding it names and rejects the file with
|
|
26
|
+
* no score, whatever the overrides say.
|
|
27
|
+
*/
|
|
28
|
+
export declare class StopError extends Error {
|
|
29
|
+
readonly category: ArchiveCategory;
|
|
30
|
+
readonly detail: ArchiveDetail;
|
|
31
|
+
readonly data?: Record<string, string | number> | undefined;
|
|
32
|
+
readonly location?: string | undefined;
|
|
33
|
+
constructor(category: ArchiveCategory, detail: ArchiveDetail, message: string, data?: Record<string, string | number> | undefined, location?: string | undefined);
|
|
34
|
+
}
|
|
35
|
+
/** Something wrong with the bytes of one entry or one stream: they do not decode, or not to what the headers say. */
|
|
36
|
+
export declare class DataError extends Error {
|
|
37
|
+
/** Set when the data ends before the stream does. */
|
|
38
|
+
readonly truncated: boolean;
|
|
39
|
+
constructor(message: string,
|
|
40
|
+
/** Set when the data ends before the stream does. */
|
|
41
|
+
truncated?: boolean);
|
|
42
|
+
}
|
|
43
|
+
/** A header or another structure of the file that cannot be read as the format defines it. */
|
|
44
|
+
export declare class ParseError extends DataError {
|
|
45
|
+
}
|
|
46
|
+
/** An integrity check that does not match. */
|
|
47
|
+
export declare class CheckError extends DataError {
|
|
48
|
+
/** Which check: CRC32, CRC64, SHA-256. */
|
|
49
|
+
readonly check: string;
|
|
50
|
+
constructor(message: string,
|
|
51
|
+
/** Which check: CRC32, CRC64, SHA-256. */
|
|
52
|
+
check: string);
|
|
53
|
+
}
|
|
54
|
+
/** Data in a method or with a feature this package has no decoder for, such as a zstd frame that needs a dictionary. */
|
|
55
|
+
export declare class UnsupportedError extends Error {
|
|
56
|
+
/** True for a compression method, coder or filter, false for another feature of the format. */
|
|
57
|
+
readonly method: boolean;
|
|
58
|
+
readonly data?: Record<string, string | number> | undefined;
|
|
59
|
+
constructor(message: string,
|
|
60
|
+
/** True for a compression method, coder or filter, false for another feature of the format. */
|
|
61
|
+
method?: boolean, data?: Record<string, string | number> | undefined);
|
|
62
|
+
}
|
|
63
|
+
/** Throws the time limit once `deadline`, a Date.now() value, has passed. */
|
|
64
|
+
export declare function checkTime(deadline: number | undefined): void;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnsupportedError = exports.CheckError = exports.ParseError = exports.DataError = exports.StopError = exports.isIoError = exports.NestedIoError = exports.NestingLimitError = exports.TimeLimitError = void 0;
|
|
4
|
+
exports.stopsTree = stopsTree;
|
|
5
|
+
exports.checkTime = checkTime;
|
|
6
|
+
/** The run passed its deadline. The code makes every package of the family pass it up instead of treating it as one plugin failing. */
|
|
7
|
+
class TimeLimitError extends Error {
|
|
8
|
+
code = 'DEFUSE_LIMIT';
|
|
9
|
+
limit = 'time';
|
|
10
|
+
}
|
|
11
|
+
exports.TimeLimitError = TimeLimitError;
|
|
12
|
+
/** A file sits deeper in the upload than `limits.nestingDepth` allows. The code makes every package pass it up. */
|
|
13
|
+
class NestingLimitError extends Error {
|
|
14
|
+
code = 'DEFUSE_LIMIT';
|
|
15
|
+
limit = 'nesting';
|
|
16
|
+
}
|
|
17
|
+
exports.NestingLimitError = NestingLimitError;
|
|
18
|
+
/** An I/O error inside a nested file's own run, carried up so the upload's run fails on it as on its own. */
|
|
19
|
+
class NestedIoError extends Error {
|
|
20
|
+
code = 'DEFUSE_IO';
|
|
21
|
+
constructor(cause) {
|
|
22
|
+
super(String(cause?.message ?? cause), { cause });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.NestedIoError = NestedIoError;
|
|
26
|
+
/**
|
|
27
|
+
* The code of an error that stops the whole tree of files, from any package: DEFUSE_LIMIT for a time or nesting
|
|
28
|
+
* limit, DEFUSE_IO for an I/O error. Packages cannot share error classes, so the code alone marks one.
|
|
29
|
+
*/
|
|
30
|
+
function stopsTree(e) {
|
|
31
|
+
const code = typeof e === 'object' && e !== null ? e.code : undefined;
|
|
32
|
+
return code === 'DEFUSE_LIMIT' || code === 'DEFUSE_IO' ? code : undefined;
|
|
33
|
+
}
|
|
34
|
+
/** An error from the operating system, such as EIO or ENOSPC, which says nothing about the file. */
|
|
35
|
+
const isIoError = (e) => typeof e?.code === 'string' && /^E[A-Z]+$/.test(e.code);
|
|
36
|
+
exports.isIoError = isIoError;
|
|
37
|
+
/**
|
|
38
|
+
* A refusal or a limit that stops the run. The engine turns it into the finding it names and rejects the file with
|
|
39
|
+
* no score, whatever the overrides say.
|
|
40
|
+
*/
|
|
41
|
+
class StopError extends Error {
|
|
42
|
+
category;
|
|
43
|
+
detail;
|
|
44
|
+
data;
|
|
45
|
+
location;
|
|
46
|
+
constructor(category, detail, message, data, location) {
|
|
47
|
+
super(message);
|
|
48
|
+
this.category = category;
|
|
49
|
+
this.detail = detail;
|
|
50
|
+
this.data = data;
|
|
51
|
+
this.location = location;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.StopError = StopError;
|
|
55
|
+
/** Something wrong with the bytes of one entry or one stream: they do not decode, or not to what the headers say. */
|
|
56
|
+
class DataError extends Error {
|
|
57
|
+
truncated;
|
|
58
|
+
constructor(message,
|
|
59
|
+
/** Set when the data ends before the stream does. */
|
|
60
|
+
truncated = false) {
|
|
61
|
+
super(message);
|
|
62
|
+
this.truncated = truncated;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.DataError = DataError;
|
|
66
|
+
/** A header or another structure of the file that cannot be read as the format defines it. */
|
|
67
|
+
class ParseError extends DataError {
|
|
68
|
+
}
|
|
69
|
+
exports.ParseError = ParseError;
|
|
70
|
+
/** An integrity check that does not match. */
|
|
71
|
+
class CheckError extends DataError {
|
|
72
|
+
check;
|
|
73
|
+
constructor(message,
|
|
74
|
+
/** Which check: CRC32, CRC64, SHA-256. */
|
|
75
|
+
check) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.check = check;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.CheckError = CheckError;
|
|
81
|
+
/** Data in a method or with a feature this package has no decoder for, such as a zstd frame that needs a dictionary. */
|
|
82
|
+
class UnsupportedError extends Error {
|
|
83
|
+
method;
|
|
84
|
+
data;
|
|
85
|
+
constructor(message,
|
|
86
|
+
/** True for a compression method, coder or filter, false for another feature of the format. */
|
|
87
|
+
method = true, data) {
|
|
88
|
+
super(message);
|
|
89
|
+
this.method = method;
|
|
90
|
+
this.data = data;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.UnsupportedError = UnsupportedError;
|
|
94
|
+
/** Throws the time limit once `deadline`, a Date.now() value, has passed. */
|
|
95
|
+
function checkTime(deadline) {
|
|
96
|
+
if (deadline !== undefined && Date.now() > deadline)
|
|
97
|
+
throw new TimeLimitError('Time limit exceeded');
|
|
98
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The delta filter and the branch converters (BCJ filters) of xz and 7z, decoding only.
|
|
3
|
+
*
|
|
4
|
+
* The converters are ported from XZ for Java (0BSD) by Lasse Collin and Igor Pavlov, org.tukaani.xz.simple and
|
|
5
|
+
* org.tukaani.xz.delta. Each `code` converts the instructions it can see whole and returns how many bytes it is done
|
|
6
|
+
* with. SimpleFilterStream holds the rest back until more data comes, and passes it on unchanged at the end, as XZ for
|
|
7
|
+
* Java's SimpleInputStream does.
|
|
8
|
+
*/
|
|
9
|
+
/** The branch converters by name. */
|
|
10
|
+
export type BranchFilter = 'x86' | 'powerpc' | 'ia64' | 'arm' | 'armthumb' | 'sparc' | 'arm64' | 'riscv';
|
|
11
|
+
/** A filter that decodes data as it arrives and keeps its size. */
|
|
12
|
+
export interface Transform {
|
|
13
|
+
/** Decodes `chunk`, which the transform may change in place, and returns what is ready. */
|
|
14
|
+
push(chunk: Uint8Array): Uint8Array;
|
|
15
|
+
/** Returns what was held back. */
|
|
16
|
+
end(): Uint8Array;
|
|
17
|
+
}
|
|
18
|
+
/** Runs a branch converter over data that arrives in pieces, as XZ for Java's SimpleInputStream does. */
|
|
19
|
+
export declare class SimpleFilterStream implements Transform {
|
|
20
|
+
private held;
|
|
21
|
+
private readonly filter;
|
|
22
|
+
constructor(kind: BranchFilter, start: number);
|
|
23
|
+
push(chunk: Uint8Array): Uint8Array;
|
|
24
|
+
end(): Uint8Array;
|
|
25
|
+
}
|
|
26
|
+
/** The delta filter's decoder: each byte is added to the one `distance` bytes before it. */
|
|
27
|
+
export declare class DeltaStream implements Transform {
|
|
28
|
+
private readonly distance;
|
|
29
|
+
private readonly history;
|
|
30
|
+
private pos;
|
|
31
|
+
constructor(distance: number);
|
|
32
|
+
push(chunk: Uint8Array): Uint8Array;
|
|
33
|
+
end(): Uint8Array;
|
|
34
|
+
}
|
package/dist/filters.js
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The delta filter and the branch converters (BCJ filters) of xz and 7z, decoding only.
|
|
4
|
+
*
|
|
5
|
+
* The converters are ported from XZ for Java (0BSD) by Lasse Collin and Igor Pavlov, org.tukaani.xz.simple and
|
|
6
|
+
* org.tukaani.xz.delta. Each `code` converts the instructions it can see whole and returns how many bytes it is done
|
|
7
|
+
* with. SimpleFilterStream holds the rest back until more data comes, and passes it on unchanged at the end, as XZ for
|
|
8
|
+
* Java's SimpleInputStream does.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.DeltaStream = exports.SimpleFilterStream = void 0;
|
|
12
|
+
const getIntLE = (b, i) => b[i] | (b[i + 1] << 8) | (b[i + 2] << 16) | (b[i + 3] << 24);
|
|
13
|
+
const getIntBE = (b, i) => (b[i] << 24) | (b[i + 1] << 16) | (b[i + 2] << 8) | b[i + 3];
|
|
14
|
+
function setIntLE(b, i, v) {
|
|
15
|
+
b[i] = v;
|
|
16
|
+
b[i + 1] = v >>> 8;
|
|
17
|
+
b[i + 2] = v >>> 16;
|
|
18
|
+
b[i + 3] = v >>> 24;
|
|
19
|
+
}
|
|
20
|
+
function setIntBE(b, i, v) {
|
|
21
|
+
b[i] = v >>> 24;
|
|
22
|
+
b[i + 1] = v >>> 16;
|
|
23
|
+
b[i + 2] = v >>> 8;
|
|
24
|
+
b[i + 3] = v;
|
|
25
|
+
}
|
|
26
|
+
const MASK_TO_ALLOWED_STATUS = [true, true, true, false, true, false, false, false];
|
|
27
|
+
const MASK_TO_BIT_NUMBER = [0, 1, 2, 2, 3, 3, 3, 3];
|
|
28
|
+
const test86MSByte = (b) => b === 0x00 || b === 0xff;
|
|
29
|
+
class X86 {
|
|
30
|
+
pos;
|
|
31
|
+
prevMask = 0;
|
|
32
|
+
constructor(startPos) {
|
|
33
|
+
this.pos = startPos + 5;
|
|
34
|
+
}
|
|
35
|
+
code(buf, off, len) {
|
|
36
|
+
let prevPos = off - 1;
|
|
37
|
+
const end = off + len - 5;
|
|
38
|
+
let i;
|
|
39
|
+
for (i = off; i <= end; ++i) {
|
|
40
|
+
if ((buf[i] & 0xfe) !== 0xe8)
|
|
41
|
+
continue;
|
|
42
|
+
prevPos = i - prevPos;
|
|
43
|
+
if ((prevPos & ~3) !== 0) {
|
|
44
|
+
this.prevMask = 0;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this.prevMask = (this.prevMask << (prevPos - 1)) & 7;
|
|
48
|
+
if (this.prevMask !== 0 && (!MASK_TO_ALLOWED_STATUS[this.prevMask] || test86MSByte(buf[i + 4 - MASK_TO_BIT_NUMBER[this.prevMask]]))) {
|
|
49
|
+
prevPos = i;
|
|
50
|
+
this.prevMask = (this.prevMask << 1) | 1;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
prevPos = i;
|
|
55
|
+
if (test86MSByte(buf[i + 4])) {
|
|
56
|
+
let src = getIntLE(buf, i + 1);
|
|
57
|
+
let dest;
|
|
58
|
+
for (;;) {
|
|
59
|
+
dest = (src - (this.pos + i - off)) | 0;
|
|
60
|
+
if (this.prevMask === 0)
|
|
61
|
+
break;
|
|
62
|
+
const index = MASK_TO_BIT_NUMBER[this.prevMask] * 8;
|
|
63
|
+
if (!test86MSByte((dest >>> (24 - index)) & 0xff))
|
|
64
|
+
break;
|
|
65
|
+
src = dest ^ ((1 << (32 - index)) - 1);
|
|
66
|
+
}
|
|
67
|
+
// Sign extend bit 24 to bits [31:24].
|
|
68
|
+
dest = (dest << 7) >> 7;
|
|
69
|
+
setIntLE(buf, i + 1, dest);
|
|
70
|
+
i += 4;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.prevMask = (this.prevMask << 1) | 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
prevPos = i - prevPos;
|
|
77
|
+
this.prevMask = (prevPos & ~3) !== 0 ? 0 : this.prevMask << (prevPos - 1);
|
|
78
|
+
i -= off;
|
|
79
|
+
this.pos += i;
|
|
80
|
+
return i;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
class PowerPC {
|
|
84
|
+
pos;
|
|
85
|
+
constructor(pos) {
|
|
86
|
+
this.pos = pos;
|
|
87
|
+
}
|
|
88
|
+
code(buf, off, len) {
|
|
89
|
+
const end = off + len - 4;
|
|
90
|
+
let i;
|
|
91
|
+
for (i = off; i <= end; i += 4) {
|
|
92
|
+
if ((buf[i] & 0xfc) === 0x48 && (buf[i + 3] & 0x03) === 0x01) {
|
|
93
|
+
const instr = getIntBE(buf, i);
|
|
94
|
+
const pc = -(this.pos + i - off);
|
|
95
|
+
setIntBE(buf, i, 0x48000001 | ((instr + pc) & 0x03fffffc));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
i -= off;
|
|
99
|
+
this.pos += i;
|
|
100
|
+
return i;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const BRANCH_TABLE = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0];
|
|
104
|
+
class IA64 {
|
|
105
|
+
pos;
|
|
106
|
+
constructor(pos) {
|
|
107
|
+
this.pos = pos;
|
|
108
|
+
}
|
|
109
|
+
code(buf, off, len) {
|
|
110
|
+
const end = off + len - 16;
|
|
111
|
+
let i;
|
|
112
|
+
for (i = off; i <= end; i += 16) {
|
|
113
|
+
const mask = BRANCH_TABLE[buf[i] & 0x1f];
|
|
114
|
+
for (let slot = 0, bitPos = 5; slot < 3; ++slot, bitPos += 41) {
|
|
115
|
+
if (((mask >>> slot) & 1) === 0)
|
|
116
|
+
continue;
|
|
117
|
+
const bytePos = bitPos >>> 3;
|
|
118
|
+
const bitRes = BigInt(bitPos & 7);
|
|
119
|
+
let instr = 0n;
|
|
120
|
+
for (let j = 0; j < 6; ++j)
|
|
121
|
+
instr |= BigInt(buf[i + bytePos + j]) << BigInt(8 * j);
|
|
122
|
+
let instrNorm = instr >> bitRes;
|
|
123
|
+
if (((instrNorm >> 37n) & 0x0fn) !== 0x05n || ((instrNorm >> 9n) & 0x07n) !== 0n)
|
|
124
|
+
continue;
|
|
125
|
+
let src = Number((instrNorm >> 13n) & 0x0fffffn);
|
|
126
|
+
src |= Number((instrNorm >> 36n) & 1n) << 20;
|
|
127
|
+
src <<= 4;
|
|
128
|
+
let dest = (src - (this.pos + i - off)) | 0;
|
|
129
|
+
dest >>>= 4;
|
|
130
|
+
instrNorm &= ~(0x8fffffn << 13n);
|
|
131
|
+
instrNorm |= BigInt(dest & 0x0fffff) << 13n;
|
|
132
|
+
instrNorm |= BigInt(dest & 0x100000) << BigInt(36 - 20);
|
|
133
|
+
instr &= (1n << bitRes) - 1n;
|
|
134
|
+
instr |= instrNorm << bitRes;
|
|
135
|
+
for (let j = 0; j < 6; ++j)
|
|
136
|
+
buf[i + bytePos + j] = Number((instr >> BigInt(8 * j)) & 0xffn);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
i -= off;
|
|
140
|
+
this.pos += i;
|
|
141
|
+
return i;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
class ARM {
|
|
145
|
+
pos;
|
|
146
|
+
constructor(startPos) {
|
|
147
|
+
this.pos = startPos + 8;
|
|
148
|
+
}
|
|
149
|
+
code(buf, off, len) {
|
|
150
|
+
const end = off + len - 4;
|
|
151
|
+
let i;
|
|
152
|
+
for (i = off; i <= end; i += 4) {
|
|
153
|
+
if (buf[i + 3] === 0xeb) {
|
|
154
|
+
const src = ((buf[i + 2] << 16) | (buf[i + 1] << 8) | buf[i]) << 2;
|
|
155
|
+
const dest = ((src - (this.pos + i - off)) | 0) >>> 2;
|
|
156
|
+
buf[i + 2] = dest >>> 16;
|
|
157
|
+
buf[i + 1] = dest >>> 8;
|
|
158
|
+
buf[i] = dest;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
i -= off;
|
|
162
|
+
this.pos += i;
|
|
163
|
+
return i;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
class ARMThumb {
|
|
167
|
+
pos;
|
|
168
|
+
constructor(startPos) {
|
|
169
|
+
this.pos = startPos + 4;
|
|
170
|
+
}
|
|
171
|
+
code(buf, off, len) {
|
|
172
|
+
const end = off + len - 4;
|
|
173
|
+
let i;
|
|
174
|
+
for (i = off; i <= end; i += 2) {
|
|
175
|
+
if ((buf[i + 1] & 0xf8) === 0xf0 && (buf[i + 3] & 0xf8) === 0xf8) {
|
|
176
|
+
const src = (((buf[i + 1] & 0x07) << 19) | (buf[i] << 11) | ((buf[i + 3] & 0x07) << 8) | buf[i + 2]) << 1;
|
|
177
|
+
const dest = ((src - (this.pos + i - off)) | 0) >>> 1;
|
|
178
|
+
buf[i + 1] = 0xf0 | ((dest >>> 19) & 0x07);
|
|
179
|
+
buf[i] = dest >>> 11;
|
|
180
|
+
buf[i + 3] = 0xf8 | ((dest >>> 8) & 0x07);
|
|
181
|
+
buf[i + 2] = dest;
|
|
182
|
+
i += 2;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
i -= off;
|
|
186
|
+
this.pos += i;
|
|
187
|
+
return i;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
class SPARC {
|
|
191
|
+
pos;
|
|
192
|
+
constructor(pos) {
|
|
193
|
+
this.pos = pos;
|
|
194
|
+
}
|
|
195
|
+
code(buf, off, len) {
|
|
196
|
+
const end = off + len - 4;
|
|
197
|
+
let i;
|
|
198
|
+
for (i = off; i <= end; i += 4) {
|
|
199
|
+
if ((buf[i] === 0x40 && (buf[i + 1] & 0xc0) === 0x00) || (buf[i] === 0x7f && (buf[i + 1] & 0xc0) === 0xc0)) {
|
|
200
|
+
const src = getIntBE(buf, i);
|
|
201
|
+
const pc = -((this.pos + i - off) >>> 2);
|
|
202
|
+
let dest = (src + pc) | 0;
|
|
203
|
+
dest = (dest << 9) >> 9;
|
|
204
|
+
dest = 0x40000000 | (dest & 0x3fffffff);
|
|
205
|
+
setIntBE(buf, i, dest);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
i -= off;
|
|
209
|
+
this.pos += i;
|
|
210
|
+
return i;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
class ARM64 {
|
|
214
|
+
pos;
|
|
215
|
+
constructor(pos) {
|
|
216
|
+
this.pos = pos;
|
|
217
|
+
}
|
|
218
|
+
code(buf, off, len) {
|
|
219
|
+
const end = off + len - 4;
|
|
220
|
+
let i;
|
|
221
|
+
for (i = off; i <= end; i += 4) {
|
|
222
|
+
// Only the highest byte is needed to identify the BL and ADRP instructions.
|
|
223
|
+
const top = buf[i + 3];
|
|
224
|
+
if ((top & 0xfc) === 0x94) {
|
|
225
|
+
// BL: the full 26-bit immediate.
|
|
226
|
+
const instr = getIntLE(buf, i);
|
|
227
|
+
const pc = -((this.pos + i - off) >>> 2);
|
|
228
|
+
setIntLE(buf, i, 0x94000000 | ((instr + pc) & 0x03ffffff));
|
|
229
|
+
}
|
|
230
|
+
else if ((top & 0x9f) === 0x90) {
|
|
231
|
+
// ADRP: only values in the range +/-512 MiB are converted.
|
|
232
|
+
let instr = getIntLE(buf, i);
|
|
233
|
+
const src = ((instr >>> 29) & 3) | ((instr >>> 3) & 0x001ffffc);
|
|
234
|
+
if (((src + 0x00020000) & 0x001c0000) !== 0)
|
|
235
|
+
continue;
|
|
236
|
+
const pc = -((this.pos + i - off) >>> 12);
|
|
237
|
+
const dest = (src + pc) | 0;
|
|
238
|
+
instr &= 0x9000001f;
|
|
239
|
+
instr |= (dest & 3) << 29;
|
|
240
|
+
instr |= (dest & 0x0003fffc) << 3;
|
|
241
|
+
instr |= -(dest & 0x00020000) & 0x00e00000;
|
|
242
|
+
setIntLE(buf, i, instr);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
i -= off;
|
|
246
|
+
this.pos += i;
|
|
247
|
+
return i;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
class RISCV {
|
|
251
|
+
pos;
|
|
252
|
+
constructor(pos) {
|
|
253
|
+
this.pos = pos;
|
|
254
|
+
}
|
|
255
|
+
code(buf, off, len) {
|
|
256
|
+
const end = off + len - 8;
|
|
257
|
+
let i;
|
|
258
|
+
for (i = off; i <= end; i += 2) {
|
|
259
|
+
let inst = buf[i];
|
|
260
|
+
if (inst === 0xef) {
|
|
261
|
+
// JAL, only with rd = x1 (ra) or x5 (t0).
|
|
262
|
+
const b1 = buf[i + 1];
|
|
263
|
+
if ((b1 & 0x0d) !== 0)
|
|
264
|
+
continue;
|
|
265
|
+
const b2 = buf[i + 2];
|
|
266
|
+
const b3 = buf[i + 3];
|
|
267
|
+
const pc = this.pos + i - off;
|
|
268
|
+
let addr = ((b1 & 0xf0) << 13) | (b2 << 9) | (b3 << 1);
|
|
269
|
+
addr = (addr - pc) | 0;
|
|
270
|
+
buf[i + 1] = (b1 & 0x0f) | ((addr >>> 8) & 0xf0);
|
|
271
|
+
buf[i + 2] = ((addr >>> 16) & 0x0f) | ((addr >>> 7) & 0x10) | ((addr << 4) & 0xe0);
|
|
272
|
+
buf[i + 3] = ((addr >>> 4) & 0x7f) | ((addr >>> 13) & 0x80);
|
|
273
|
+
i += 4 - 2;
|
|
274
|
+
}
|
|
275
|
+
else if ((inst & 0x7f) === 0x17) {
|
|
276
|
+
// AUIPC
|
|
277
|
+
let inst2;
|
|
278
|
+
inst |= buf[i + 1] << 8;
|
|
279
|
+
inst |= buf[i + 2] << 16;
|
|
280
|
+
inst |= buf[i + 3] << 24;
|
|
281
|
+
if ((inst & 0xe80) !== 0) {
|
|
282
|
+
// rd is neither x0 nor x2: a "fake" pair the encoder left alone, decoded the simple way.
|
|
283
|
+
inst2 = getIntLE(buf, i + 4);
|
|
284
|
+
if ((((inst << 8) ^ inst2) & 0xf8003) !== 3) {
|
|
285
|
+
i += 6 - 2;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const addr = (inst & 0xfffff000) + (inst2 >>> 20);
|
|
289
|
+
inst = 0x17 | (2 << 7) | (inst2 << 12);
|
|
290
|
+
inst2 = addr;
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
// rd is x0 or x2: the special format the encoder writes.
|
|
294
|
+
const inst2Rs1 = inst >>> 27;
|
|
295
|
+
if (((inst - 0x3100) & 0x3f80) >= (inst2Rs1 & 0x1d)) {
|
|
296
|
+
i += 4 - 2;
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
let addr = getIntBE(buf, i + 4);
|
|
300
|
+
addr = (addr - (this.pos + i - off)) | 0;
|
|
301
|
+
inst2 = (inst >>> 12) | (addr << 20);
|
|
302
|
+
inst = 0x17 | (inst2Rs1 << 7) | ((addr + 0x800) & 0xfffff000);
|
|
303
|
+
}
|
|
304
|
+
setIntLE(buf, i, inst);
|
|
305
|
+
setIntLE(buf, i + 4, inst2);
|
|
306
|
+
i += 8 - 2;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
i -= off;
|
|
310
|
+
this.pos += i;
|
|
311
|
+
return i;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function makeSimple(kind, start) {
|
|
315
|
+
switch (kind) {
|
|
316
|
+
case 'x86':
|
|
317
|
+
return new X86(start);
|
|
318
|
+
case 'powerpc':
|
|
319
|
+
return new PowerPC(start);
|
|
320
|
+
case 'ia64':
|
|
321
|
+
return new IA64(start);
|
|
322
|
+
case 'arm':
|
|
323
|
+
return new ARM(start);
|
|
324
|
+
case 'armthumb':
|
|
325
|
+
return new ARMThumb(start);
|
|
326
|
+
case 'sparc':
|
|
327
|
+
return new SPARC(start);
|
|
328
|
+
case 'arm64':
|
|
329
|
+
return new ARM64(start);
|
|
330
|
+
default:
|
|
331
|
+
return new RISCV(start);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/** Runs a branch converter over data that arrives in pieces, as XZ for Java's SimpleInputStream does. */
|
|
335
|
+
class SimpleFilterStream {
|
|
336
|
+
held = new Uint8Array(0);
|
|
337
|
+
filter;
|
|
338
|
+
constructor(kind, start) {
|
|
339
|
+
this.filter = makeSimple(kind, start);
|
|
340
|
+
}
|
|
341
|
+
push(chunk) {
|
|
342
|
+
let buf;
|
|
343
|
+
if (this.held.length === 0)
|
|
344
|
+
buf = chunk;
|
|
345
|
+
else {
|
|
346
|
+
buf = new Uint8Array(this.held.length + chunk.length);
|
|
347
|
+
buf.set(this.held);
|
|
348
|
+
buf.set(chunk, this.held.length);
|
|
349
|
+
}
|
|
350
|
+
const done = this.filter.code(buf, 0, buf.length);
|
|
351
|
+
this.held = buf.slice(done);
|
|
352
|
+
return buf.subarray(0, done);
|
|
353
|
+
}
|
|
354
|
+
end() {
|
|
355
|
+
const rest = this.held;
|
|
356
|
+
this.held = new Uint8Array(0);
|
|
357
|
+
return rest;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
exports.SimpleFilterStream = SimpleFilterStream;
|
|
361
|
+
/** The delta filter's decoder: each byte is added to the one `distance` bytes before it. */
|
|
362
|
+
class DeltaStream {
|
|
363
|
+
distance;
|
|
364
|
+
history;
|
|
365
|
+
pos = 0;
|
|
366
|
+
constructor(distance) {
|
|
367
|
+
this.distance = distance;
|
|
368
|
+
this.history = new Uint8Array(256);
|
|
369
|
+
}
|
|
370
|
+
push(chunk) {
|
|
371
|
+
const h = this.history;
|
|
372
|
+
const d = this.distance;
|
|
373
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
374
|
+
const b = (chunk[i] + h[(this.pos - d) & 0xff]) & 0xff;
|
|
375
|
+
chunk[i] = b;
|
|
376
|
+
h[this.pos & 0xff] = b;
|
|
377
|
+
this.pos++;
|
|
378
|
+
}
|
|
379
|
+
return chunk;
|
|
380
|
+
}
|
|
381
|
+
end() {
|
|
382
|
+
return new Uint8Array(0);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
exports.DeltaStream = DeltaStream;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ArchiveActionOverride, type ArchiveFinding, type ArchiveFindingAction, ArchiveCategory as C, ArchiveDetail as D } from './types';
|
|
2
|
+
interface Spec {
|
|
3
|
+
action: ArchiveFindingAction;
|
|
4
|
+
/**
|
|
5
|
+
* May contain <key> placeholders filled from data, and <first|second> choices, which take the first alternative
|
|
6
|
+
* whose {key} values are all set and not empty, or that names none. A filled value has control and format
|
|
7
|
+
* characters replaced by "?", and one in a choice, such as an entry name, is cut to 60 characters.
|
|
8
|
+
*/
|
|
9
|
+
description: string;
|
|
10
|
+
weight: number;
|
|
11
|
+
}
|
|
12
|
+
/** The built-in spec for a kind of finding, or undefined for a kind archive-defuse does not make, such as one from another package. */
|
|
13
|
+
export declare function findingSpec(category: string, detail: string): Spec | undefined;
|
|
14
|
+
export declare function allFindingSpecs(): Array<{
|
|
15
|
+
category: C;
|
|
16
|
+
detail: D;
|
|
17
|
+
} & Spec>;
|
|
18
|
+
export declare class FindingFactory {
|
|
19
|
+
private readonly overrides;
|
|
20
|
+
constructor(overrides?: ArchiveActionOverride[]);
|
|
21
|
+
actionFor(category: C, detail: D): ArchiveFindingAction;
|
|
22
|
+
/** True when findings of this kind remove what they report. */
|
|
23
|
+
strips(category: C, detail: D): boolean;
|
|
24
|
+
make(category: C, detail: D, location?: string, data?: Record<string, string | number>): ArchiveFinding;
|
|
25
|
+
}
|
|
26
|
+
export {};
|