@futpib/parser 1.0.3 → 1.0.6

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.
Files changed (262) hide show
  1. package/.claude/settings.local.json +24 -0
  2. package/.github/workflows/main.yml +1 -0
  3. package/build/androidPackageParser.js +30 -32
  4. package/build/arbitraryDalvikBytecode.d.ts +3 -3
  5. package/build/arbitraryDalvikBytecode.js +33 -27
  6. package/build/arbitraryDalvikExecutable.js +55 -17
  7. package/build/arbitraryJava.d.ts +31 -0
  8. package/build/arbitraryJava.js +532 -0
  9. package/build/arbitraryJavaScript.d.ts +3 -0
  10. package/build/arbitraryJavaScript.js +263 -0
  11. package/build/arbitraryJavascript.d.ts +3 -0
  12. package/build/arbitraryJavascript.js +263 -0
  13. package/build/arbitraryZig.d.ts +3 -0
  14. package/build/arbitraryZig.js +240 -0
  15. package/build/arbitraryZipStream.d.ts +1 -1
  16. package/build/arrayParser.js +72 -13
  17. package/build/backsmali.d.ts +4 -3
  18. package/build/backsmali.js +26 -6
  19. package/build/bash.d.ts +89 -0
  20. package/build/bash.js +1 -0
  21. package/build/bashParser.d.ts +6 -0
  22. package/build/bashParser.js +335 -0
  23. package/build/bashParser.test.d.ts +1 -0
  24. package/build/bashParser.test.js +343 -0
  25. package/build/bashParserEdgeCases.test.d.ts +1 -0
  26. package/build/bashParserEdgeCases.test.js +117 -0
  27. package/build/dalvikBytecodeParser/addressConversion.d.ts +110 -0
  28. package/build/dalvikBytecodeParser/addressConversion.js +334 -0
  29. package/build/dalvikBytecodeParser/formatParsers.d.ts +7 -6
  30. package/build/dalvikBytecodeParser/formatParsers.js +13 -14
  31. package/build/dalvikBytecodeParser.d.ts +60 -31
  32. package/build/dalvikBytecodeParser.js +92 -35
  33. package/build/dalvikBytecodeParser.test-d.d.ts +1 -0
  34. package/build/dalvikBytecodeParser.test-d.js +268 -0
  35. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +9 -8
  36. package/build/dalvikBytecodeUnparser/formatUnparsers.js +13 -12
  37. package/build/dalvikBytecodeUnparser.d.ts +2 -2
  38. package/build/dalvikBytecodeUnparser.js +23 -23
  39. package/build/dalvikBytecodeUnparser.test.js +7 -7
  40. package/build/dalvikExecutable.d.ts +3 -3
  41. package/build/dalvikExecutable.test-d.d.ts +1 -0
  42. package/build/dalvikExecutable.test-d.js +59 -0
  43. package/build/dalvikExecutableParser/typedNumbers.d.ts +18 -0
  44. package/build/dalvikExecutableParser/typedNumbers.js +3 -0
  45. package/build/dalvikExecutableParser.d.ts +2 -1
  46. package/build/dalvikExecutableParser.js +96 -77
  47. package/build/dalvikExecutableParser.test.js +24 -3
  48. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +3 -0
  49. package/build/dalvikExecutableUnparser/poolScanners.d.ts +2 -2
  50. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +3 -3
  51. package/build/dalvikExecutableUnparser/sectionUnparsers.js +26 -11
  52. package/build/dalvikExecutableUnparser.d.ts +2 -2
  53. package/build/dalvikExecutableUnparser.test.js +2 -1
  54. package/build/disjunctionParser.d.ts +5 -3
  55. package/build/disjunctionParser.js +79 -17
  56. package/build/disjunctionParser.test-d.d.ts +1 -0
  57. package/build/disjunctionParser.test-d.js +72 -0
  58. package/build/elementSwitchParser.d.ts +4 -0
  59. package/build/{exactElementSwitchParser.js → elementSwitchParser.js} +3 -4
  60. package/build/elementSwitchParser.test-d.d.ts +1 -0
  61. package/build/elementSwitchParser.test-d.js +44 -0
  62. package/build/exactSequenceParser.d.ts +4 -2
  63. package/build/exactSequenceParser.test-d.d.ts +1 -0
  64. package/build/exactSequenceParser.test-d.js +36 -0
  65. package/build/fetchCid.js +2 -66
  66. package/build/index.d.ts +25 -2
  67. package/build/index.js +23 -1
  68. package/build/index.test.js +16 -1
  69. package/build/inputReader.d.ts +10 -0
  70. package/build/inputReader.js +36 -0
  71. package/build/java.d.ts +502 -0
  72. package/build/java.js +2 -0
  73. package/build/javaKeyStoreParser.js +14 -17
  74. package/build/javaParser.d.ts +51 -0
  75. package/build/javaParser.js +1538 -0
  76. package/build/javaParser.test.d.ts +1 -0
  77. package/build/javaParser.test.js +1287 -0
  78. package/build/javaScript.d.ts +35 -0
  79. package/build/javaScript.js +1 -0
  80. package/build/javaScriptParser.d.ts +9 -0
  81. package/build/javaScriptParser.js +34 -0
  82. package/build/javaScriptUnparser.d.ts +3 -0
  83. package/build/javaScriptUnparser.js +4 -0
  84. package/build/javaScriptUnparser.test.d.ts +1 -0
  85. package/build/javaScriptUnparser.test.js +24 -0
  86. package/build/javaUnparser.d.ts +2 -0
  87. package/build/javaUnparser.js +519 -0
  88. package/build/javaUnparser.test.d.ts +1 -0
  89. package/build/javaUnparser.test.js +24 -0
  90. package/build/javascript.d.ts +35 -0
  91. package/build/javascript.js +1 -0
  92. package/build/javascriptParser.d.ts +9 -0
  93. package/build/javascriptParser.js +34 -0
  94. package/build/javascriptUnparser.d.ts +3 -0
  95. package/build/javascriptUnparser.js +4 -0
  96. package/build/javascriptUnparser.test.d.ts +1 -0
  97. package/build/javascriptUnparser.test.js +24 -0
  98. package/build/jsonParser.js +2 -12
  99. package/build/lazyMessageError.d.ts +3 -0
  100. package/build/lookaheadParser.js +60 -3
  101. package/build/negativeLookaheadParser.js +70 -11
  102. package/build/nonEmptyArrayParser.js +72 -13
  103. package/build/objectParser.d.ts +12 -0
  104. package/build/objectParser.js +31 -0
  105. package/build/objectParser.test-d.d.ts +1 -0
  106. package/build/objectParser.test-d.js +112 -0
  107. package/build/objectParser.test.d.ts +1 -0
  108. package/build/objectParser.test.js +55 -0
  109. package/build/optionalParser.js +69 -10
  110. package/build/parser.d.ts +4 -0
  111. package/build/parser.js +3 -1
  112. package/build/parser.test.js +114 -1
  113. package/build/parserConsumedSequenceParser.js +66 -7
  114. package/build/parserContext.d.ts +6 -0
  115. package/build/parserContext.js +20 -11
  116. package/build/parserError.d.ts +119 -27
  117. package/build/parserError.js +16 -8
  118. package/build/regexpParser.d.ts +2 -0
  119. package/build/regexpParser.js +101 -0
  120. package/build/regexpParser.test.d.ts +1 -0
  121. package/build/regexpParser.test.js +114 -0
  122. package/build/regularExpression.d.ts +63 -0
  123. package/build/regularExpression.js +1 -0
  124. package/build/regularExpressionParser.d.ts +3 -0
  125. package/build/regularExpressionParser.js +600 -0
  126. package/build/regularExpressionParser.test.d.ts +1 -0
  127. package/build/regularExpressionParser.test.js +89 -0
  128. package/build/separatedArrayParser.js +73 -14
  129. package/build/separatedNonEmptyArrayParser.js +73 -14
  130. package/build/sliceBoundedParser.js +62 -5
  131. package/build/smaliParser.d.ts +7 -7
  132. package/build/smaliParser.js +185 -268
  133. package/build/smaliParser.test.js +58 -0
  134. package/build/stringEscapes.d.ts +5 -0
  135. package/build/stringEscapes.js +244 -0
  136. package/build/symbolicExpression.d.ts +29 -0
  137. package/build/symbolicExpression.js +1 -0
  138. package/build/symbolicExpressionParser.d.ts +4 -0
  139. package/build/symbolicExpressionParser.js +123 -0
  140. package/build/symbolicExpressionParser.test.d.ts +1 -0
  141. package/build/symbolicExpressionParser.test.js +289 -0
  142. package/build/terminatedArrayParser.js +113 -38
  143. package/build/terminatedArrayParser.test.js +4 -2
  144. package/build/tupleParser.d.ts +7 -15
  145. package/build/tupleParser.js +1 -0
  146. package/build/unionParser.d.ts +5 -3
  147. package/build/unionParser.js +7 -2
  148. package/build/unionParser.test-d.d.ts +1 -0
  149. package/build/unionParser.test-d.js +72 -0
  150. package/build/unionParser.test.js +10 -11
  151. package/build/zig.d.ts +280 -0
  152. package/build/zig.js +2 -0
  153. package/build/zigParser.d.ts +3 -0
  154. package/build/zigParser.js +1119 -0
  155. package/build/zigParser.test.d.ts +1 -0
  156. package/build/zigParser.test.js +1590 -0
  157. package/build/zigUnparser.d.ts +2 -0
  158. package/build/zigUnparser.js +460 -0
  159. package/build/zigUnparser.test.d.ts +1 -0
  160. package/build/zigUnparser.test.js +24 -0
  161. package/build/zipParser.js +19 -32
  162. package/build/zipUnparser.js +19 -7
  163. package/build/zipUnparser.test.js +1 -1
  164. package/node_modules-@types/s-expression/index.d.ts +5 -0
  165. package/package.json +25 -6
  166. package/src/androidPackageParser.ts +33 -60
  167. package/src/arbitraryDalvikBytecode.ts +39 -31
  168. package/src/arbitraryDalvikExecutable.ts +65 -20
  169. package/src/arbitraryJava.ts +804 -0
  170. package/src/arbitraryJavaScript.ts +410 -0
  171. package/src/arbitraryZig.ts +380 -0
  172. package/src/arrayParser.ts +1 -3
  173. package/src/backsmali.ts +35 -4
  174. package/src/bash.ts +127 -0
  175. package/src/bashParser.test.ts +590 -0
  176. package/src/bashParser.ts +498 -0
  177. package/src/dalvikBytecodeParser/addressConversion.ts +496 -0
  178. package/src/dalvikBytecodeParser/formatParsers.ts +19 -29
  179. package/src/dalvikBytecodeParser.test-d.ts +310 -0
  180. package/src/dalvikBytecodeParser.ts +194 -69
  181. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +27 -26
  182. package/src/dalvikBytecodeUnparser.test.ts +7 -7
  183. package/src/dalvikBytecodeUnparser.ts +31 -30
  184. package/src/dalvikExecutable.test-d.ts +132 -0
  185. package/src/dalvikExecutable.ts +3 -3
  186. package/src/dalvikExecutableParser/typedNumbers.ts +11 -0
  187. package/src/dalvikExecutableParser.test.ts +37 -3
  188. package/src/dalvikExecutableParser.test.ts.md +163 -2
  189. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  190. package/src/dalvikExecutableParser.ts +121 -139
  191. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +4 -0
  192. package/src/dalvikExecutableUnparser/poolScanners.ts +6 -6
  193. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +38 -14
  194. package/src/dalvikExecutableUnparser.test.ts +3 -2
  195. package/src/dalvikExecutableUnparser.ts +4 -4
  196. package/src/disjunctionParser.test-d.ts +105 -0
  197. package/src/disjunctionParser.ts +18 -15
  198. package/src/elementSwitchParser.test-d.ts +74 -0
  199. package/src/elementSwitchParser.ts +51 -0
  200. package/src/exactSequenceParser.test-d.ts +43 -0
  201. package/src/exactSequenceParser.ts +13 -8
  202. package/src/fetchCid.ts +2 -76
  203. package/src/index.test.ts +22 -1
  204. package/src/index.ts +119 -2
  205. package/src/inputReader.ts +53 -0
  206. package/src/java.ts +708 -0
  207. package/src/javaKeyStoreParser.ts +18 -32
  208. package/src/javaParser.test.ts +1592 -0
  209. package/src/javaParser.ts +2640 -0
  210. package/src/javaScript.ts +36 -0
  211. package/src/javaScriptParser.ts +57 -0
  212. package/src/javaScriptUnparser.test.ts +37 -0
  213. package/src/javaScriptUnparser.ts +7 -0
  214. package/src/javaUnparser.test.ts +37 -0
  215. package/src/javaUnparser.ts +640 -0
  216. package/src/jsonParser.ts +6 -27
  217. package/src/lookaheadParser.ts +2 -6
  218. package/src/negativeLookaheadParser.ts +1 -3
  219. package/src/nonEmptyArrayParser.ts +1 -3
  220. package/src/objectParser.test-d.ts +152 -0
  221. package/src/objectParser.test.ts +71 -0
  222. package/src/objectParser.ts +69 -0
  223. package/src/optionalParser.ts +1 -3
  224. package/src/parser.test.ts +151 -4
  225. package/src/parser.ts +11 -1
  226. package/src/parserConsumedSequenceParser.ts +2 -4
  227. package/src/parserContext.ts +26 -11
  228. package/src/parserError.ts +17 -3
  229. package/src/regexpParser.test.ts +264 -0
  230. package/src/regexpParser.ts +126 -0
  231. package/src/regularExpression.ts +24 -0
  232. package/src/regularExpressionParser.test.ts +102 -0
  233. package/src/regularExpressionParser.ts +920 -0
  234. package/src/separatedArrayParser.ts +1 -3
  235. package/src/separatedNonEmptyArrayParser.ts +1 -3
  236. package/src/sliceBoundedParser.test.ts +2 -2
  237. package/src/sliceBoundedParser.ts +15 -19
  238. package/src/smaliParser.test.ts +64 -0
  239. package/src/smaliParser.test.ts.md +12 -12
  240. package/src/smaliParser.test.ts.snap +0 -0
  241. package/src/smaliParser.ts +246 -534
  242. package/src/stringEscapes.ts +253 -0
  243. package/src/symbolicExpression.ts +17 -0
  244. package/src/symbolicExpressionParser.test.ts +466 -0
  245. package/src/symbolicExpressionParser.ts +190 -0
  246. package/src/terminatedArrayParser.test.ts +9 -6
  247. package/src/terminatedArrayParser.ts +25 -29
  248. package/src/tupleParser.ts +21 -18
  249. package/src/unionParser.test-d.ts +105 -0
  250. package/src/unionParser.test.ts +18 -17
  251. package/src/unionParser.ts +28 -16
  252. package/src/zig.ts +411 -0
  253. package/src/zigParser.test.ts +1693 -0
  254. package/src/zigParser.ts +1745 -0
  255. package/src/zigUnparser.test.ts +37 -0
  256. package/src/zigUnparser.ts +615 -0
  257. package/src/zipParser.ts +20 -56
  258. package/src/zipUnparser.test.ts +1 -1
  259. package/src/zipUnparser.ts +22 -7
  260. package/tsconfig.json +2 -2
  261. package/build/exactElementSwitchParser.d.ts +0 -3
  262. package/src/exactElementSwitchParser.ts +0 -41
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@futpib/parser",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "main": "build/index.js",
5
+ "types": "build/index.d.ts",
5
6
  "license": "GPL-3.0-only",
6
7
  "type": "module",
7
8
  "scripts": {
8
9
  "dev": "tsc --watch",
9
10
  "build": "tsc",
11
+ "tsd": "tsd --files 'src/**/*.test-d.ts'",
10
12
  "test": "c8 ava",
11
13
  "prepack": "yarn build"
12
14
  },
@@ -21,13 +23,26 @@
21
23
  "verbose": true,
22
24
  "timeout": "60s"
23
25
  },
26
+ "tsd": {
27
+ "directory": "src",
28
+ "compilerOptions": {
29
+ "lib": [
30
+ "ES2022",
31
+ "DOM",
32
+ "DOM.AsyncIterable"
33
+ ]
34
+ }
35
+ },
24
36
  "devDependencies": {
25
37
  "@ava/typescript": "^6.0.0",
26
38
  "@fast-check/ava": "^2.0.2",
39
+ "@futpib/fetch-cid": "^1.0.2",
40
+ "@gruhn/regex-utils": "^2.7.3",
41
+ "@types/estree": "^1.0.8",
27
42
  "@types/invariant": "^2.2.37",
28
- "@types/node": "^24.4.0",
43
+ "@types/node": "^24.10.1",
29
44
  "ava": "^6.4.1",
30
- "bson": "^6.10.4",
45
+ "bson": "^7.0.0",
31
46
  "c8": "^10.1.3",
32
47
  "coveralls": "^3.1.1",
33
48
  "env-paths": "^3.0.0",
@@ -39,13 +54,17 @@
39
54
  "leb128": "^0.0.5",
40
55
  "mutf-8": "^1.2.2",
41
56
  "p-memoize": "^8.0.0",
57
+ "s-expression": "^3.1.1",
42
58
  "tempy": "^3.1.0",
43
- "type-fest": "^5.0.0",
44
- "typescript": "^5.9.2",
45
- "xo": "^1.2.2"
59
+ "tsd": "^0.33.0",
60
+ "type-fest": "^5.2.0",
61
+ "typescript": "^5.9.3",
62
+ "xo": "^1.2.3"
46
63
  },
47
64
  "packageManager": "yarn@4.9.4",
48
65
  "dependencies": {
66
+ "acorn": "^8.15.0",
67
+ "astring": "^1.9.0",
49
68
  "fp-ts": "^2.16.11",
50
69
  "mem": "^10.0.0",
51
70
  "monocle-ts": "^2.3.13",
@@ -26,6 +26,7 @@ import { createExactSequenceParser } from './exactSequenceParser.js';
26
26
  import { createSliceBoundedParser } from './sliceBoundedParser.js';
27
27
  import { createDisjunctionParser } from './disjunctionParser.js';
28
28
  import { createExactElementParser } from './exactElementParser.js';
29
+ import { createObjectParser } from './objectParser.js';
29
30
  import { createParserConsumedSequenceParser } from './parserConsumedSequenceParser.js';
30
31
  import { createDebugLogInputParser } from './debugLogInputParser.js';
31
32
  import { createDebugLogParser } from './debugLogParser.js';
@@ -86,13 +87,11 @@ type AndroidPackageSigningBlockSignatureV2Pair = {
86
87
  };
87
88
 
88
89
  const createAndroidPackageSigningBlockSignatureV2PairInnerParser = (length: number): Parser<AndroidPackageSigningBlockSignatureV2Pair, Uint8Array> => {
89
- const androidPackageSigningBlockSignatureV2PairInnerParser = promiseCompose(
90
- createTupleParser([
91
- createExactSequenceParser<Uint8Array>(Buffer.from('1a870971', 'hex')),
92
- androidPackageSignatureV2SignersParser,
93
- ]),
94
- ([ _magic, signers = [] ]) => ({ type: 'signatureV2' as const, signers }),
95
- );
90
+ const androidPackageSigningBlockSignatureV2PairInnerParser = createObjectParser({
91
+ type: 'signatureV2' as const,
92
+ _magic: createExactSequenceParser<Uint8Array>(Buffer.from('1a870971', 'hex')),
93
+ signers: androidPackageSignatureV2SignersParser,
94
+ });
96
95
 
97
96
  return setParserName(androidPackageSigningBlockSignatureV2PairInnerParser, 'androidPackageSigningBlockSignatureV2PairInnerParser');
98
97
  };
@@ -102,13 +101,13 @@ type AndroidPackageSigningBlockGenericPair = {
102
101
  pair: AndroidPackageSigningBlockPair;
103
102
  };
104
103
 
105
- const createAndroidPackageSigningBlockGenericPairInnerParser = (length: number): Parser<AndroidPackageSigningBlockGenericPair, Uint8Array> => promiseCompose(
106
- createTupleParser([
107
- uint32LEParser,
108
- createFixedLengthSequenceParser(length - 4),
109
- ]),
110
- ([ id, value ]) => ({ type: 'generic', pair: { id, value } }),
111
- );
104
+ const createAndroidPackageSigningBlockGenericPairInnerParser = (length: number): Parser<AndroidPackageSigningBlockGenericPair, Uint8Array> => createObjectParser({
105
+ type: 'generic' as const,
106
+ pair: createObjectParser({
107
+ id: uint32LEParser,
108
+ value: createFixedLengthSequenceParser<Uint8Array>(length - 4),
109
+ }),
110
+ });
112
111
 
113
112
  type AndroidPackageSigningBlockPairType =
114
113
  | AndroidPackageSigningBlockZeroPaddingPair
@@ -126,7 +125,7 @@ const createAndroidPackageSigningBlockPairInnerParser = (length: number): Parser
126
125
  length,
127
126
  );
128
127
  },
129
- createDisjunctionParser<AndroidPackageSigningBlockPairType, Uint8Array>([
128
+ createDisjunctionParser([
130
129
  createAndroidPackageSigningBlockZeroPaddingPairInnerParser(length),
131
130
  createAndroidPackageSigningBlockSignatureV2PairInnerParser(length),
132
131
  createAndroidPackageSigningBlockGenericPairInnerParser(length),
@@ -189,13 +188,10 @@ export const androidPackageSigningBlockParser: Parser<AndroidPackageSigningBlock
189
188
  },
190
189
  ));
191
190
 
192
- const androidPackageSignatureV2DigestParser = createUint32LengthPrefixedParser<AndroidPackageSignatureV2Digest>(pairLength => promiseCompose(
193
- createTupleParser([
194
- uint32LEParser,
195
- createUint32LengthPrefixedParser(digestLength => createFixedLengthSequenceParser(digestLength)),
196
- ]),
197
- ([ signatureAlgorithmId, digest ]) => ({ signatureAlgorithmId, digest }),
198
- ));
191
+ const androidPackageSignatureV2DigestParser = createUint32LengthPrefixedParser<AndroidPackageSignatureV2Digest>(pairLength => createObjectParser({
192
+ signatureAlgorithmId: uint32LEParser,
193
+ digest: createUint32LengthPrefixedParser(digestLength => createFixedLengthSequenceParser(digestLength)),
194
+ }));
199
195
 
200
196
  const androidPackageSignatureV2DigestsParser = createUint32LengthPrefixedSliceBoundedArrayParser(androidPackageSignatureV2DigestParser);
201
197
 
@@ -209,13 +205,10 @@ const androidPackageSignatureV2CertificatesParser = createUint32LengthPrefixedSl
209
205
 
210
206
  setParserName(androidPackageSignatureV2CertificatesParser, 'androidPackageSignatureV2CertificatesParser');
211
207
 
212
- const androidPackageSignatureV2AdditionalAttributeParser = createUint32LengthPrefixedParser<AndroidPackageSignatureV2AdditionalAttribute>(pairLength => promiseCompose(
213
- createTupleParser([
214
- uint32LEParser,
215
- createFixedLengthSequenceParser(pairLength - 4),
216
- ]),
217
- ([ id, value ]) => ({ id, value }),
218
- ));
208
+ const androidPackageSignatureV2AdditionalAttributeParser = createUint32LengthPrefixedParser<AndroidPackageSignatureV2AdditionalAttribute>(pairLength => createObjectParser({
209
+ id: uint32LEParser,
210
+ value: createFixedLengthSequenceParser<Uint8Array>(pairLength - 4),
211
+ }));
219
212
 
220
213
  setParserName(androidPackageSignatureV2AdditionalAttributeParser, 'androidPackageSignatureV2AdditionalAttributeParser');
221
214
 
@@ -228,7 +221,7 @@ const androidPackageSignatureV2SignedDataParser = createUint32LengthPrefixedSlic
228
221
  androidPackageSignatureV2DigestsParser,
229
222
  androidPackageSignatureV2CertificatesParser,
230
223
  androidPackageSignatureV2AdditionalAttributesParser,
231
- createArrayParser(createExactElementParser(0)),
224
+ createArrayParser(createExactElementParser<Uint8Array>(0)),
232
225
  ]),
233
226
  ([
234
227
  digests,
@@ -245,19 +238,10 @@ const androidPackageSignatureV2SignedDataParser = createUint32LengthPrefixedSlic
245
238
 
246
239
  setParserName(androidPackageSignatureV2SignedDataParser, 'androidPackageSignatureV2SignedDataParser');
247
240
 
248
- const androidPackageSignatureV2SignatureParser = createUint32LengthPrefixedParser(signatureLength => promiseCompose(
249
- createTupleParser([
250
- uint32LEParser,
251
- createUint32LengthPrefixedParser(signatureLength => createFixedLengthSequenceParser(signatureLength)),
252
- ]),
253
- ([
254
- signatureAlgorithmId,
255
- signature,
256
- ]): AndroidPackageSignatureV2Signature => ({
257
- signatureAlgorithmId,
258
- signature,
259
- }),
260
- ));
241
+ const androidPackageSignatureV2SignatureParser = createUint32LengthPrefixedParser(signatureLength => createObjectParser({
242
+ signatureAlgorithmId: uint32LEParser,
243
+ signature: createUint32LengthPrefixedParser(signatureLength => createFixedLengthSequenceParser(signatureLength)),
244
+ }));
261
245
 
262
246
  const androidPackageSignatureV2SignaturesParser = createUint32LengthPrefixedSliceBoundedArrayParser(androidPackageSignatureV2SignatureParser);
263
247
 
@@ -267,22 +251,11 @@ const androidPackageSignatureV2PublicKeyParser = createUint32LengthPrefixedParse
267
251
 
268
252
  setParserName(androidPackageSignatureV2PublicKeyParser, 'androidPackageSignatureV2PublicKeyParser');
269
253
 
270
- const androidPackageSignatureV2SignerParser = createUint32LengthPrefixedSliceBoundedParser(promiseCompose(
271
- createTupleParser([
272
- androidPackageSignatureV2SignedDataParser,
273
- androidPackageSignatureV2SignaturesParser,
274
- androidPackageSignatureV2PublicKeyParser,
275
- ]),
276
- ([
277
- signedData,
278
- signatures = [],
279
- publicKey,
280
- ]): AndroidPackageSignatureV2Signer => ({
281
- signedData,
282
- signatures,
283
- publicKey,
284
- }),
285
- ));
254
+ const androidPackageSignatureV2SignerParser: Parser<AndroidPackageSignatureV2Signer, Uint8Array> = createUint32LengthPrefixedSliceBoundedParser(createObjectParser({
255
+ signedData: androidPackageSignatureV2SignedDataParser,
256
+ signatures: androidPackageSignatureV2SignaturesParser,
257
+ publicKey: androidPackageSignatureV2PublicKeyParser,
258
+ }));
286
259
 
287
260
  setParserName(androidPackageSignatureV2SignerParser, 'androidPackageSignatureV2SignerParser');
288
261
 
@@ -350,7 +323,7 @@ export const androidPackageSignableSectionsParser: Parser<AndroidPackageSignable
350
323
  createOptionalParser(zipArchiveDecryptionHeaderParser),
351
324
  createOptionalParser(zipArchiveExtraDataRecordParser),
352
325
  ])),
353
- createArrayParser(createExactElementParser(0)),
326
+ createArrayParser(createExactElementParser<Uint8Array>(0)),
354
327
  createOptionalParser(createParserConsumedSequenceParser(androidPackageSigningBlockParser)),
355
328
  createParserConsumedSequenceParser(createTupleParser([
356
329
  createArrayParser(zipCentralDirectoryHeaderParser),
@@ -1,7 +1,7 @@
1
1
  import * as fc from 'fast-check';
2
2
  import {
3
- type DalvikBytecode,
4
- type DalvikBytecodeOperation,
3
+ type RawDalvikBytecode,
4
+ type RawDalvikBytecodeOperation,
5
5
  } from './dalvikBytecodeParser.js';
6
6
  import {
7
7
  type IndexIntoStringIds,
@@ -9,11 +9,13 @@ import {
9
9
  type IndexIntoMethodIds,
10
10
  type IndexIntoFieldIds,
11
11
  type IndexIntoPrototypeIds,
12
+ type CodeUnit,
12
13
  isoIndexIntoStringIds,
13
14
  isoIndexIntoTypeIds,
14
15
  isoIndexIntoMethodIds,
15
16
  isoIndexIntoFieldIds,
16
17
  isoIndexIntoPrototypeIds,
18
+ isoCodeUnit,
17
19
  } from './dalvikExecutableParser/typedNumbers.js';
18
20
 
19
21
  // Arbitrary generators for typed indexes
@@ -49,13 +51,19 @@ const arbitraryShortValue = fc.integer({ min: -32768, max: 32767 }); // 16-bit s
49
51
  const arbitraryIntValue = fc.integer({ min: -2147483648, max: 2147483647 }); // 32-bit signed
50
52
  const arbitraryLongValue = fc.bigInt({ min: -9223372036854775808n, max: 9223372036854775807n }); // 64-bit signed
51
53
 
52
- // Arbitrary branch offsets (relative)
53
- const arbitraryBranchOffset8 = fc.integer({ min: -128, max: 127 });
54
- const arbitraryBranchOffset16 = fc.integer({ min: -32768, max: 32767 });
55
- const arbitraryBranchOffset32 = fc.integer({ min: -2147483648, max: 2147483647 });
54
+ // Arbitrary branch offsets (relative) - wrapped as CodeUnit
55
+ const arbitraryBranchOffsetCodeUnit8: fc.Arbitrary<CodeUnit> = fc
56
+ .integer({ min: -128, max: 127 })
57
+ .map(n => isoCodeUnit.wrap(n));
58
+ const arbitraryBranchOffsetCodeUnit16: fc.Arbitrary<CodeUnit> = fc
59
+ .integer({ min: -32768, max: 32767 })
60
+ .map(n => isoCodeUnit.wrap(n));
61
+ const arbitraryBranchOffsetCodeUnit32: fc.Arbitrary<CodeUnit> = fc
62
+ .integer({ min: -2147483648, max: 2147483647 })
63
+ .map(n => isoCodeUnit.wrap(n));
56
64
 
57
65
  // No-operation
58
- const arbitraryNop = fc.constant<DalvikBytecodeOperation>({
66
+ const arbitraryNop = fc.constant<RawDalvikBytecodeOperation>({
59
67
  operation: 'nop',
60
68
  });
61
69
 
@@ -119,7 +127,7 @@ const arbitraryMoveException = fc.record({
119
127
  });
120
128
 
121
129
  // Return operations
122
- const arbitraryReturnVoid = fc.constant<DalvikBytecodeOperation>({
130
+ const arbitraryReturnVoid = fc.constant<RawDalvikBytecodeOperation>({
123
131
  operation: 'return-void',
124
132
  });
125
133
 
@@ -265,36 +273,36 @@ const arbitraryThrow = fc.record({
265
273
  // Goto operations
266
274
  const arbitraryGoto = fc.record({
267
275
  operation: fc.constant('goto' as const),
268
- branchOffset: arbitraryBranchOffset8,
276
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit8,
269
277
  });
270
278
 
271
279
  const arbitraryGoto16 = fc.record({
272
280
  operation: fc.constant('goto/16' as const),
273
- branchOffset: arbitraryBranchOffset16,
281
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
274
282
  });
275
283
 
276
284
  const arbitraryGoto32 = fc.record({
277
285
  operation: fc.constant('goto/32' as const),
278
- branchOffset: arbitraryBranchOffset32,
286
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit32,
279
287
  });
280
288
 
281
289
  // Switch operations
282
290
  const arbitraryPackedSwitch = fc.record({
283
291
  operation: fc.constant('packed-switch' as const),
284
292
  registers: fc.tuple(arbitraryRegister8),
285
- branchOffset: arbitraryBranchOffset32,
293
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit32,
286
294
  });
287
295
 
288
296
  const arbitrarySparseSwitch = fc.record({
289
297
  operation: fc.constant('sparse-switch' as const),
290
298
  registers: fc.tuple(arbitraryRegister8),
291
- branchOffset: arbitraryBranchOffset32,
299
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit32,
292
300
  });
293
301
 
294
302
  const arbitraryFillArrayData = fc.record({
295
303
  operation: fc.constant('fill-array-data' as const),
296
304
  registers: fc.tuple(arbitraryRegister8),
297
- branchOffset: arbitraryBranchOffset32,
305
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit32,
298
306
  });
299
307
 
300
308
  // Payload operations
@@ -304,7 +312,7 @@ const arbitraryPackedSwitchPayload = fc
304
312
  fc.record({
305
313
  operation: fc.constant('packed-switch-payload' as const),
306
314
  value: arbitraryIntValue,
307
- branchOffsets: fc.array(arbitraryBranchOffset32, { minLength: size, maxLength: size }),
315
+ branchOffsetsCodeUnit: fc.array(arbitraryBranchOffsetCodeUnit32, { minLength: size, maxLength: size }),
308
316
  })
309
317
  );
310
318
 
@@ -314,7 +322,7 @@ const arbitrarySparseSwitchPayload = fc
314
322
  fc.record({
315
323
  operation: fc.constant('sparse-switch-payload' as const),
316
324
  keys: fc.array(arbitraryIntValue, { minLength: size, maxLength: size }),
317
- branchOffsets: fc.array(arbitraryBranchOffset32, { minLength: size, maxLength: size }),
325
+ branchOffsetsCodeUnit: fc.array(arbitraryBranchOffsetCodeUnit32, { minLength: size, maxLength: size }),
318
326
  })
319
327
  );
320
328
 
@@ -337,74 +345,74 @@ const arbitraryFillArrayDataPayload = fc
337
345
  const arbitraryIfEqual = fc.record({
338
346
  operation: fc.constant('if-eq' as const),
339
347
  registers: fc.tuple(arbitraryRegister4, arbitraryRegister4).map(([a, b]) => [a, b].sort((x, y) => x - y)),
340
- branchOffset: arbitraryBranchOffset16,
348
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
341
349
  });
342
350
 
343
351
  const arbitraryIfNotEqual = fc.record({
344
352
  operation: fc.constant('if-ne' as const),
345
353
  registers: fc.tuple(arbitraryRegister4, arbitraryRegister4).map(([a, b]) => [a, b].sort((x, y) => x - y)),
346
- branchOffset: arbitraryBranchOffset16,
354
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
347
355
  });
348
356
 
349
357
  const arbitraryIfLessThan = fc.record({
350
358
  operation: fc.constant('if-lt' as const),
351
359
  registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
352
- branchOffset: arbitraryBranchOffset16,
360
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
353
361
  });
354
362
 
355
363
  const arbitraryIfGreaterThanOrEqualTo = fc.record({
356
364
  operation: fc.constant('if-ge' as const),
357
365
  registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
358
- branchOffset: arbitraryBranchOffset16,
366
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
359
367
  });
360
368
 
361
369
  const arbitraryIfGreaterThan = fc.record({
362
370
  operation: fc.constant('if-gt' as const),
363
371
  registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
364
- branchOffset: arbitraryBranchOffset16,
372
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
365
373
  });
366
374
 
367
375
  const arbitraryIfLessThanOrEqualTo = fc.record({
368
376
  operation: fc.constant('if-le' as const),
369
377
  registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
370
- branchOffset: arbitraryBranchOffset16,
378
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
371
379
  });
372
380
 
373
381
  // If-test-zero operations (Format 21t)
374
382
  const arbitraryIfEqualZero = fc.record({
375
383
  operation: fc.constant('if-eqz' as const),
376
384
  registers: fc.tuple(arbitraryRegister8),
377
- branchOffset: arbitraryBranchOffset16,
385
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
378
386
  });
379
387
 
380
388
  const arbitraryIfNotEqualZero = fc.record({
381
389
  operation: fc.constant('if-nez' as const),
382
390
  registers: fc.tuple(arbitraryRegister8),
383
- branchOffset: arbitraryBranchOffset16,
391
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
384
392
  });
385
393
 
386
394
  const arbitraryIfLessThanZero = fc.record({
387
395
  operation: fc.constant('if-ltz' as const),
388
396
  registers: fc.tuple(arbitraryRegister8),
389
- branchOffset: arbitraryBranchOffset16,
397
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
390
398
  });
391
399
 
392
400
  const arbitraryIfGreaterThanOrEqualToZero = fc.record({
393
401
  operation: fc.constant('if-gez' as const),
394
402
  registers: fc.tuple(arbitraryRegister8),
395
- branchOffset: arbitraryBranchOffset16,
403
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
396
404
  });
397
405
 
398
406
  const arbitraryIfGreaterThanZero = fc.record({
399
407
  operation: fc.constant('if-gtz' as const),
400
408
  registers: fc.tuple(arbitraryRegister8),
401
- branchOffset: arbitraryBranchOffset16,
409
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
402
410
  });
403
411
 
404
412
  const arbitraryIfLessThanOrEqualToZero = fc.record({
405
413
  operation: fc.constant('if-lez' as const),
406
414
  registers: fc.tuple(arbitraryRegister8),
407
- branchOffset: arbitraryBranchOffset16,
415
+ branchOffsetCodeUnit: arbitraryBranchOffsetCodeUnit16,
408
416
  });
409
417
 
410
418
  // Array element operations (Format 23x)
@@ -740,7 +748,7 @@ const arbitraryIntToChar = createArbitraryUnaryOperation('int-to-char');
740
748
  const arbitraryIntToShort = createArbitraryUnaryOperation('int-to-short');
741
749
 
742
750
  // Combine all operations
743
- export const arbitraryDalvikBytecodeOperation: fc.Arbitrary<DalvikBytecodeOperation> = fc.oneof(
751
+ export const arbitraryRawDalvikBytecodeOperation: fc.Arbitrary<RawDalvikBytecodeOperation> = fc.oneof(
744
752
  arbitraryNop,
745
753
  // Move operations
746
754
  arbitraryMove,
@@ -986,7 +994,7 @@ export const arbitraryDalvikBytecodeOperation: fc.Arbitrary<DalvikBytecodeOperat
986
994
  );
987
995
 
988
996
  // Arbitrary for complete Dalvik bytecode (array of operations)
989
- export const arbitraryDalvikBytecode: fc.Arbitrary<DalvikBytecode> = fc.array(
990
- arbitraryDalvikBytecodeOperation,
997
+ export const arbitraryRawDalvikBytecode: fc.Arbitrary<RawDalvikBytecode> = fc.array(
998
+ arbitraryRawDalvikBytecodeOperation,
991
999
  { minLength: 0, maxLength: 100 }
992
1000
  );
@@ -288,52 +288,97 @@ const arbitraryDalvikExecutableDebugInfo: fc.Arbitrary<DalvikExecutableDebugInfo
288
288
 
289
289
  // Try-catch handler generators
290
290
  interface DalvikExecutableTry {
291
- startAddress: number;
291
+ startInstructionIndex: number;
292
292
  instructionCount: number;
293
293
  handler: DalvikExecutableEncodedCatchHandler;
294
294
  }
295
295
 
296
296
  interface DalvikExecutableEncodedCatchHandler {
297
297
  handlers: DalvikExecutableEncodedTypeAddressPair[];
298
- catchAllAddress: undefined | number;
298
+ catchAllInstructionIndex: undefined | number;
299
299
  }
300
300
 
301
301
  interface DalvikExecutableEncodedTypeAddressPair {
302
302
  type: string;
303
- address: number;
303
+ handlerInstructionIndex: number;
304
304
  }
305
305
 
306
- const arbitraryDalvikExecutableEncodedTypeAddressPair: fc.Arbitrary<DalvikExecutableEncodedTypeAddressPair> = fc.record({
307
- type: arbitraryDalvikClassName,
308
- address: fc.nat({ max: 65535 }),
309
- });
306
+ // Factory function to create arbitrary try blocks that are valid for given instruction count
307
+ // Since addresses are now instruction indices, they must be within [0, instructionCount]
308
+ function createArbitraryDalvikExecutableTry(instructionCount: number): fc.Arbitrary<DalvikExecutableTry> {
309
+ // If no instructions, we can't have meaningful try blocks
310
+ if (instructionCount === 0) {
311
+ // Return a try block that covers the "after last instruction" position (index 0)
312
+ const arbitraryEmptyHandler: fc.Arbitrary<DalvikExecutableEncodedCatchHandler> = fc.record({
313
+ handlers: fc.constant([]),
314
+ catchAllInstructionIndex: fc.constant(0),
315
+ });
316
+ return fc.record({
317
+ startInstructionIndex: fc.constant(0),
318
+ instructionCount: fc.constant(0),
319
+ handler: arbitraryEmptyHandler,
320
+ });
321
+ }
322
+
323
+ // Addresses must be in range [0, instructionCount] (inclusive, since handler can point to end)
324
+ const maxAddress = instructionCount;
325
+
326
+ const arbitraryDalvikExecutableEncodedTypeAddressPair: fc.Arbitrary<DalvikExecutableEncodedTypeAddressPair> = fc.record({
327
+ type: arbitraryDalvikClassName,
328
+ handlerInstructionIndex: fc.nat({ max: maxAddress }),
329
+ });
310
330
 
311
- const arbitraryDalvikExecutableEncodedCatchHandler: fc.Arbitrary<DalvikExecutableEncodedCatchHandler> = fc.record({
312
- handlers: fc.array(arbitraryDalvikExecutableEncodedTypeAddressPair, { maxLength: 3 }),
313
- catchAllAddress: fc.option(fc.nat({ max: 65535 }), { nil: undefined }),
314
- }).filter(handler => {
315
- // A handler must have at least one typed handler OR a catch-all address
316
- return handler.handlers.length > 0 || handler.catchAllAddress !== undefined;
317
- });
331
+ const arbitraryDalvikExecutableEncodedCatchHandler: fc.Arbitrary<DalvikExecutableEncodedCatchHandler> = fc.record({
332
+ handlers: fc.array(arbitraryDalvikExecutableEncodedTypeAddressPair, { maxLength: 3 }),
333
+ catchAllInstructionIndex: fc.option(fc.nat({ max: maxAddress }), { nil: undefined }),
334
+ }).filter(handler => {
335
+ // A handler must have at least one typed handler OR a catch-all address
336
+ return handler.handlers.length > 0 || handler.catchAllInstructionIndex !== undefined;
337
+ });
318
338
 
319
- const arbitraryDalvikExecutableTry: fc.Arbitrary<DalvikExecutableTry> = fc.record({
320
- startAddress: fc.nat({ max: 65535 }),
321
- instructionCount: fc.nat({ max: 255 }),
322
- handler: arbitraryDalvikExecutableEncodedCatchHandler,
323
- });
339
+ // startInstructionIndex + instructionCount must not exceed instructionCount (the total)
340
+ return fc.tuple(
341
+ fc.nat({ max: instructionCount }),
342
+ fc.nat({ max: instructionCount }),
343
+ ).chain(([start, count]) => {
344
+ // Adjust count so start + count <= instructionCount
345
+ const adjustedCount = Math.min(count, instructionCount - start);
346
+ return fc.record({
347
+ startInstructionIndex: fc.constant(start),
348
+ instructionCount: fc.constant(adjustedCount),
349
+ handler: arbitraryDalvikExecutableEncodedCatchHandler,
350
+ });
351
+ });
352
+ }
353
+
354
+ // Helper function to get instruction count from instructions
355
+ // This handles both array and non-array instruction types
356
+ function getInstructionCount<Instructions>(instructions: Instructions): number {
357
+ if (Array.isArray(instructions)) {
358
+ return instructions.length;
359
+ }
360
+
361
+ return 0; // Non-array instructions default to 0
362
+ }
324
363
 
325
364
  // Generic factory function for DalvikExecutable
326
365
  export const createArbitraryDalvikExecutable = <Instructions>(
327
366
  arbitraryInstructions: fc.Arbitrary<Instructions>,
328
367
  ): fc.Arbitrary<DalvikExecutable<Instructions>> => {
329
368
  // Code generator using provided instructions arbitrary
369
+ // First generate instructions, then generate valid tries based on instruction count
330
370
  const arbitraryDalvikExecutableCode: fc.Arbitrary<DalvikExecutableCode<Instructions>> = fc.record({
331
371
  registersSize: fc.nat({ max: 65535 }),
332
372
  insSize: fc.nat({ max: 255 }),
333
373
  outsSize: fc.nat({ max: 255 }),
334
374
  debugInfo: fc.option(arbitraryDalvikExecutableDebugInfo, { nil: undefined }),
335
375
  instructions: arbitraryInstructions,
336
- tries: fc.array(arbitraryDalvikExecutableTry, { maxLength: 2 }),
376
+ }).chain(partialCode => {
377
+ const instructionCount = getInstructionCount(partialCode.instructions);
378
+ return fc.array(createArbitraryDalvikExecutableTry(instructionCount), { maxLength: 2 }).map(tries => ({
379
+ ...partialCode,
380
+ tries,
381
+ }));
337
382
  });
338
383
 
339
384
  // Method with access and code