@futpib/parser 1.0.2 → 1.0.4

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 (311) hide show
  1. package/.github/copilot-instructions.md +149 -0
  2. package/.github/workflows/copilot-setup-steps.yml +18 -0
  3. package/.github/workflows/main.yml +29 -8
  4. package/.yarn/releases/yarn-4.9.4.cjs +942 -0
  5. package/.yarnrc.yml +1 -1
  6. package/build/allSettledStream.js +1 -1
  7. package/build/allSettledStream.test.js +2 -2
  8. package/build/androidPackageParser.d.ts +1 -1
  9. package/build/androidPackageParser.js +5 -3
  10. package/build/androidPackageParser.test.js +7 -7
  11. package/build/androidPackageUnparser.d.ts +2 -2
  12. package/build/androidPackageUnparser.js +18 -14
  13. package/build/androidPackageUnparser.test.js +7 -7
  14. package/build/arbitrarilySlicedAsyncInterator.js +2 -1
  15. package/build/arbitraryDalvikBytecode.d.ts +4 -0
  16. package/build/arbitraryDalvikBytecode.js +640 -0
  17. package/build/arbitraryDalvikExecutable.d.ts +3 -0
  18. package/build/arbitraryDalvikExecutable.js +282 -0
  19. package/build/arbitraryDosDateTime.js +1 -0
  20. package/build/arbitraryZipStream.js +1 -1
  21. package/build/arrayParser.js +2 -2
  22. package/build/arrayUnparser.d.ts +1 -1
  23. package/build/backsmali.d.ts +3 -1
  24. package/build/backsmali.js +31 -3
  25. package/build/bash.d.ts +84 -0
  26. package/build/bash.js +1 -0
  27. package/build/bashParser.d.ts +6 -0
  28. package/build/bashParser.js +294 -0
  29. package/build/bashParser.test.d.ts +1 -0
  30. package/build/bashParser.test.js +181 -0
  31. package/build/customInvariant.d.ts +2 -1
  32. package/build/customInvariant.js +4 -6
  33. package/build/dalvikBytecodeParser/formatParsers.d.ts +76 -2
  34. package/build/dalvikBytecodeParser/formatParsers.js +146 -11
  35. package/build/dalvikBytecodeParser/formatSizes.d.ts +34 -0
  36. package/build/dalvikBytecodeParser/formatSizes.js +34 -0
  37. package/build/dalvikBytecodeParser/operationFormats.d.ts +225 -0
  38. package/build/dalvikBytecodeParser/operationFormats.js +225 -0
  39. package/build/dalvikBytecodeParser.d.ts +1105 -5
  40. package/build/dalvikBytecodeParser.js +658 -205
  41. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +152 -0
  42. package/build/dalvikBytecodeUnparser/formatUnparsers.js +225 -0
  43. package/build/dalvikBytecodeUnparser.d.ts +3 -0
  44. package/build/dalvikBytecodeUnparser.js +642 -0
  45. package/build/dalvikBytecodeUnparser.test.d.ts +1 -0
  46. package/build/dalvikBytecodeUnparser.test.js +25 -0
  47. package/build/dalvikExecutable.d.ts +65 -8
  48. package/build/dalvikExecutable.js +36 -0
  49. package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +1 -1
  50. package/build/dalvikExecutableParser/stringSyntaxParser.js +17 -17
  51. package/build/dalvikExecutableParser/typeParsers.d.ts +2 -1
  52. package/build/dalvikExecutableParser/typeParsers.js +16 -11
  53. package/build/dalvikExecutableParser/typedNumbers.d.ts +85 -69
  54. package/build/dalvikExecutableParser/typedNumbers.js +0 -1
  55. package/build/dalvikExecutableParser.d.ts +2 -2
  56. package/build/dalvikExecutableParser.js +655 -337
  57. package/build/dalvikExecutableParser.test.js +24 -22
  58. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +223 -246
  59. package/build/dalvikExecutableUnparser/annotationUnparsers.d.ts +14 -0
  60. package/build/dalvikExecutableUnparser/annotationUnparsers.js +97 -0
  61. package/build/dalvikExecutableUnparser/poolBuilders.d.ts +49 -0
  62. package/build/dalvikExecutableUnparser/poolBuilders.js +140 -0
  63. package/build/dalvikExecutableUnparser/poolScanners.d.ts +4 -0
  64. package/build/dalvikExecutableUnparser/poolScanners.js +220 -0
  65. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +25 -0
  66. package/build/dalvikExecutableUnparser/sectionUnparsers.js +581 -0
  67. package/build/dalvikExecutableUnparser/utils.d.ts +10 -0
  68. package/build/dalvikExecutableUnparser/utils.js +108 -0
  69. package/build/dalvikExecutableUnparser.d.ts +4 -0
  70. package/build/dalvikExecutableUnparser.js +406 -0
  71. package/build/dalvikExecutableUnparser.test.d.ts +1 -0
  72. package/build/dalvikExecutableUnparser.test.js +31 -0
  73. package/build/debugLogInputParser.js +1 -1
  74. package/build/disjunctionParser.d.ts +2 -2
  75. package/build/disjunctionParser.js +2 -2
  76. package/build/elementTerminatedArrayParser.d.ts +2 -2
  77. package/build/elementTerminatedArrayParser.js +1 -1
  78. package/build/elementTerminatedArrayParser.test.js +5 -5
  79. package/build/elementTerminatedSequenceArrayParser.d.ts +2 -2
  80. package/build/elementTerminatedSequenceArrayParser.js +1 -1
  81. package/build/elementTerminatedSequenceArrayParser.test.js +2 -2
  82. package/build/elementTerminatedSequenceParser.d.ts +2 -2
  83. package/build/elementTerminatedSequenceParser.js +1 -1
  84. package/build/elementTerminatedSequenceParser.test.js +2 -2
  85. package/build/endOfInputParser.d.ts +1 -1
  86. package/build/exactElementSwitchParser.d.ts +3 -0
  87. package/build/exactElementSwitchParser.js +22 -0
  88. package/build/fetchCid.js +2 -6
  89. package/build/fetchCid.test.d.ts +1 -0
  90. package/build/fetchCid.test.js +16 -0
  91. package/build/fixedLengthSequenceParser.test.js +2 -2
  92. package/build/hasExecutable.js +2 -2
  93. package/build/highResolutionTimer.js +1 -1
  94. package/build/index.d.ts +24 -2
  95. package/build/index.js +22 -1
  96. package/build/inputReader.d.ts +1 -1
  97. package/build/inputReader.test.js +33 -45
  98. package/build/javaKeyStoreParser.test.js +6 -6
  99. package/build/jsonParser.js +8 -8
  100. package/build/lazyMessageError.d.ts +48 -0
  101. package/build/lazyMessageError.js +53 -0
  102. package/build/lazyMessageError.test.d.ts +1 -0
  103. package/build/lazyMessageError.test.js +15 -0
  104. package/build/leb128Parser.d.ts +1 -1
  105. package/build/leb128Parser.js +10 -10
  106. package/build/leb128Parser.test.js +7 -7
  107. package/build/negativeLookaheadParser.js +2 -2
  108. package/build/negativeLookaheadParser.test.js +4 -4
  109. package/build/noStackCaptureOverheadError.d.ts +4 -0
  110. package/build/noStackCaptureOverheadError.js +9 -0
  111. package/build/noStackCaptureOverheadError.test.d.ts +1 -0
  112. package/build/noStackCaptureOverheadError.test.js +15 -0
  113. package/build/nonEmptyArrayParser.js +2 -2
  114. package/build/nonEmptyArrayParser.test.js +2 -1
  115. package/build/optionalParser.js +2 -2
  116. package/build/parser.d.ts +2 -1
  117. package/build/parser.js +23 -8
  118. package/build/parser.test.js +78 -29
  119. package/build/parserConsumedSequenceParser.d.ts +1 -1
  120. package/build/parserConsumedSequenceParser.js +2 -2
  121. package/build/parserContext.d.ts +8 -6
  122. package/build/parserContext.js +60 -33
  123. package/build/parserContext.test.js +7 -3
  124. package/build/parserError.d.ts +603 -44
  125. package/build/parserError.js +98 -53
  126. package/build/parserImplementationInvariant.d.ts +1 -1
  127. package/build/parserImplementationInvariant.js +2 -2
  128. package/build/parserInputCompanion.js +2 -2
  129. package/build/promiseCompose.js +1 -2
  130. package/build/regexpParser.d.ts +2 -0
  131. package/build/regexpParser.js +71 -0
  132. package/build/regexpParser.test.d.ts +1 -0
  133. package/build/regexpParser.test.js +83 -0
  134. package/build/regularExpression.d.ts +63 -0
  135. package/build/regularExpression.js +1 -0
  136. package/build/regularExpressionParser.d.ts +3 -0
  137. package/build/regularExpressionParser.js +580 -0
  138. package/build/regularExpressionParser.test.d.ts +1 -0
  139. package/build/regularExpressionParser.test.js +89 -0
  140. package/build/separatedArrayParser.js +2 -2
  141. package/build/separatedNonEmptyArrayParser.d.ts +2 -0
  142. package/build/separatedNonEmptyArrayParser.js +40 -0
  143. package/build/separatedNonEmptyArrayParser.test.d.ts +1 -0
  144. package/build/separatedNonEmptyArrayParser.test.js +66 -0
  145. package/build/sequenceBuffer.js +1 -1
  146. package/build/sequenceTerminatedSequenceParser.d.ts +2 -2
  147. package/build/sequenceTerminatedSequenceParser.js +3 -3
  148. package/build/sequenceTerminatedSequenceParser.test.js +1 -1
  149. package/build/sequenceUnparser.d.ts +1 -1
  150. package/build/skipToParser.d.ts +1 -1
  151. package/build/skipToParser.js +2 -2
  152. package/build/sliceBoundedParser.test.js +4 -9
  153. package/build/smali.d.ts +1 -1
  154. package/build/smali.js +6 -2
  155. package/build/smaliParser.d.ts +62 -6
  156. package/build/smaliParser.js +1721 -296
  157. package/build/smaliParser.test.js +338 -43
  158. package/build/stringFromAsyncIterable.d.ts +1 -0
  159. package/build/stringFromAsyncIterable.js +7 -0
  160. package/build/terminatedArrayParser.js +4 -4
  161. package/build/terminatedArrayParser.test.js +7 -7
  162. package/build/toAsyncIterator.js +4 -4
  163. package/build/unionParser.d.ts +1 -1
  164. package/build/unionParser.js +2 -2
  165. package/build/unionParser.test.js +3 -3
  166. package/build/unparser.d.ts +3 -3
  167. package/build/unparser.js +6 -4
  168. package/build/unparser.test.js +7 -19
  169. package/build/unparserContext.d.ts +2 -2
  170. package/build/unparserContext.js +2 -3
  171. package/build/unparserError.d.ts +2 -1
  172. package/build/unparserError.js +2 -1
  173. package/build/unparserImplementationInvariant.d.ts +1 -1
  174. package/build/unparserOutputCompanion.d.ts +1 -1
  175. package/build/unparserOutputCompanion.js +1 -1
  176. package/build/zipParser.js +1 -1
  177. package/build/zipUnparser.d.ts +3 -3
  178. package/build/zipUnparser.js +9 -19
  179. package/build/zipUnparser.test.js +1 -1
  180. package/package.json +20 -26
  181. package/src/allSettledStream.test.ts +2 -2
  182. package/src/allSettledStream.ts +3 -3
  183. package/src/androidPackageParser.test.ts +17 -19
  184. package/src/androidPackageParser.ts +129 -171
  185. package/src/androidPackageUnparser.test.ts +19 -21
  186. package/src/androidPackageUnparser.ts +23 -17
  187. package/src/arbitrarilySlicedAsyncInterable.ts +1 -1
  188. package/src/arbitrarilySlicedAsyncInterator.ts +4 -4
  189. package/src/arbitraryDalvikBytecode.ts +992 -0
  190. package/src/arbitraryDalvikExecutable.ts +434 -0
  191. package/src/arbitraryDosDateTime.ts +1 -0
  192. package/src/arbitraryZipStream.ts +1 -1
  193. package/src/arrayParser.ts +2 -2
  194. package/src/arrayUnparser.ts +2 -2
  195. package/src/backsmali.ts +48 -4
  196. package/src/bash.ts +120 -0
  197. package/src/bashParser.test.ts +332 -0
  198. package/src/bashParser.ts +461 -0
  199. package/src/bsonParser.test.ts +12 -14
  200. package/src/customInvariant.ts +8 -12
  201. package/src/dalvikBytecodeParser/formatParsers.ts +376 -17
  202. package/src/dalvikBytecodeParser/formatSizes.ts +35 -0
  203. package/src/dalvikBytecodeParser/operationFormats.ts +226 -0
  204. package/src/dalvikBytecodeParser.ts +1042 -243
  205. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +442 -0
  206. package/src/dalvikBytecodeUnparser.test.ts +44 -0
  207. package/src/dalvikBytecodeUnparser.ts +758 -0
  208. package/src/dalvikExecutable.ts +110 -48
  209. package/src/dalvikExecutableParser/stringSyntaxParser.ts +33 -33
  210. package/src/dalvikExecutableParser/typeParsers.ts +23 -14
  211. package/src/dalvikExecutableParser/typedNumbers.ts +19 -19
  212. package/src/dalvikExecutableParser.test.ts +60 -60
  213. package/src/dalvikExecutableParser.test.ts.md +6 -6
  214. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  215. package/src/dalvikExecutableParser.ts +911 -434
  216. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +256 -239
  217. package/src/dalvikExecutableUnparser/annotationUnparsers.ts +135 -0
  218. package/src/dalvikExecutableUnparser/poolBuilders.ts +189 -0
  219. package/src/dalvikExecutableUnparser/poolScanners.ts +297 -0
  220. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +683 -0
  221. package/src/dalvikExecutableUnparser/utils.ts +149 -0
  222. package/src/dalvikExecutableUnparser.test.ts +57 -0
  223. package/src/dalvikExecutableUnparser.ts +581 -0
  224. package/src/debugLogInputParser.ts +1 -1
  225. package/src/disjunctionParser.ts +5 -5
  226. package/src/elementTerminatedArrayParser.test.ts +8 -8
  227. package/src/elementTerminatedArrayParser.ts +2 -2
  228. package/src/elementTerminatedSequenceArrayParser.test.ts +4 -6
  229. package/src/elementTerminatedSequenceArrayParser.ts +2 -2
  230. package/src/elementTerminatedSequenceParser.test.ts +4 -6
  231. package/src/elementTerminatedSequenceParser.ts +2 -2
  232. package/src/endOfInputParser.ts +1 -1
  233. package/src/exactElementSwitchParser.ts +41 -0
  234. package/src/fetchCid.test.ts +20 -0
  235. package/src/fetchCid.ts +3 -7
  236. package/src/fixedLengthSequenceParser.test.ts +10 -12
  237. package/src/hasExecutable.ts +2 -2
  238. package/src/highResolutionTimer.ts +1 -1
  239. package/src/index.ts +113 -2
  240. package/src/inputReader.test.ts +39 -52
  241. package/src/inputReader.ts +2 -4
  242. package/src/inputReaderState.ts +1 -1
  243. package/src/inspect.ts +1 -1
  244. package/src/javaKeyStoreParser.test.ts +12 -14
  245. package/src/javaKeyStoreParser.ts +2 -6
  246. package/src/jsonParser.test.ts +2 -4
  247. package/src/jsonParser.ts +34 -38
  248. package/src/lazyMessageError.test.ts +21 -0
  249. package/src/lazyMessageError.ts +88 -0
  250. package/src/leb128Parser.test.ts +25 -23
  251. package/src/leb128Parser.ts +19 -19
  252. package/src/negativeLookaheadParser.test.ts +7 -11
  253. package/src/negativeLookaheadParser.ts +2 -2
  254. package/src/noStackCaptureOverheadError.test.ts +17 -0
  255. package/src/noStackCaptureOverheadError.ts +12 -0
  256. package/src/nonEmptyArrayParser.test.ts +3 -2
  257. package/src/nonEmptyArrayParser.ts +2 -2
  258. package/src/optionalParser.ts +2 -2
  259. package/src/parser.test.ts +96 -43
  260. package/src/parser.test.ts.md +13 -6
  261. package/src/parser.test.ts.snap +0 -0
  262. package/src/parser.ts +35 -12
  263. package/src/parserAccessorParser.ts +1 -1
  264. package/src/parserConsumedSequenceParser.ts +3 -3
  265. package/src/parserContext.test.ts +7 -3
  266. package/src/parserContext.ts +82 -48
  267. package/src/parserError.ts +143 -63
  268. package/src/parserImplementationInvariant.ts +3 -3
  269. package/src/parserInputCompanion.ts +2 -2
  270. package/src/promiseCompose.ts +2 -2
  271. package/src/regexpParser.test.ts +186 -0
  272. package/src/regexpParser.ts +94 -0
  273. package/src/regularExpression.ts +24 -0
  274. package/src/regularExpressionParser.test.ts +102 -0
  275. package/src/regularExpressionParser.ts +921 -0
  276. package/src/separatedArrayParser.ts +3 -3
  277. package/src/separatedNonEmptyArrayParser.test.ts +117 -0
  278. package/src/separatedNonEmptyArrayParser.ts +61 -0
  279. package/src/sequenceBuffer.test.ts +9 -9
  280. package/src/sequenceBuffer.ts +4 -4
  281. package/src/sequenceTerminatedSequenceParser.test.ts +3 -5
  282. package/src/sequenceTerminatedSequenceParser.ts +4 -4
  283. package/src/sequenceUnparser.ts +2 -2
  284. package/src/skipToParser.ts +2 -2
  285. package/src/sliceBoundedParser.test.ts +4 -12
  286. package/src/sliceBoundedParser.ts +2 -2
  287. package/src/smali.ts +8 -3
  288. package/src/smaliParser.test.ts +377 -66
  289. package/src/smaliParser.test.ts.md +1635 -48
  290. package/src/smaliParser.test.ts.snap +0 -0
  291. package/src/smaliParser.ts +2751 -569
  292. package/src/stringFromAsyncIterable.ts +9 -0
  293. package/src/terminatedArrayParser.test.ts +11 -11
  294. package/src/terminatedArrayParser.ts +5 -7
  295. package/src/toAsyncIterator.ts +8 -8
  296. package/src/uint8Array.ts +2 -3
  297. package/src/unionParser.test.ts +22 -23
  298. package/src/unionParser.ts +6 -8
  299. package/src/unparser.test.ts +18 -34
  300. package/src/unparser.ts +13 -9
  301. package/src/unparserContext.ts +9 -13
  302. package/src/unparserError.ts +2 -1
  303. package/src/unparserImplementationInvariant.ts +1 -1
  304. package/src/unparserOutputCompanion.ts +1 -1
  305. package/src/zip.ts +2 -6
  306. package/src/zipParser.ts +10 -18
  307. package/src/zipUnparser.test.ts +1 -1
  308. package/src/zipUnparser.ts +52 -64
  309. package/tsconfig.json +7 -1
  310. package/xo.config.ts +15 -0
  311. package/.yarn/releases/yarn-4.5.3.cjs +0 -934
@@ -0,0 +1,992 @@
1
+ import * as fc from 'fast-check';
2
+ import {
3
+ type DalvikBytecode,
4
+ type DalvikBytecodeOperation,
5
+ } from './dalvikBytecodeParser.js';
6
+ import {
7
+ type IndexIntoStringIds,
8
+ type IndexIntoTypeIds,
9
+ type IndexIntoMethodIds,
10
+ type IndexIntoFieldIds,
11
+ type IndexIntoPrototypeIds,
12
+ isoIndexIntoStringIds,
13
+ isoIndexIntoTypeIds,
14
+ isoIndexIntoMethodIds,
15
+ isoIndexIntoFieldIds,
16
+ isoIndexIntoPrototypeIds,
17
+ } from './dalvikExecutableParser/typedNumbers.js';
18
+
19
+ // Arbitrary generators for typed indexes
20
+ const arbitraryIndexIntoStringIds: fc.Arbitrary<IndexIntoStringIds> = fc
21
+ .nat({ max: 65535 })
22
+ .map(n => isoIndexIntoStringIds.wrap(n));
23
+
24
+ const arbitraryIndexIntoTypeIds: fc.Arbitrary<IndexIntoTypeIds> = fc
25
+ .nat({ max: 65535 })
26
+ .map(n => isoIndexIntoTypeIds.wrap(n));
27
+
28
+ const arbitraryIndexIntoMethodIds: fc.Arbitrary<IndexIntoMethodIds> = fc
29
+ .nat({ max: 65535 })
30
+ .map(n => isoIndexIntoMethodIds.wrap(n));
31
+
32
+ const arbitraryIndexIntoFieldIds: fc.Arbitrary<IndexIntoFieldIds> = fc
33
+ .nat({ max: 65535 })
34
+ .map(n => isoIndexIntoFieldIds.wrap(n));
35
+
36
+ const arbitraryIndexIntoPrototypeIds: fc.Arbitrary<IndexIntoPrototypeIds> = fc
37
+ .nat({ max: 65535 })
38
+ .map(n => isoIndexIntoPrototypeIds.wrap(n));
39
+
40
+ // Arbitrary register number (4-bit or 8-bit or 16-bit depending on format)
41
+ const arbitraryRegister4 = fc.nat({ max: 15 });
42
+ const arbitraryRegister8 = fc.nat({ max: 255 });
43
+ const arbitraryRegister16 = fc.nat({ max: 65535 });
44
+
45
+ // Arbitrary values for const operations
46
+ const arbitraryNibbleValue = fc.integer({ min: -8, max: 7 }); // 4-bit signed
47
+ const arbitraryByteValue = fc.integer({ min: -128, max: 127 }); // 8-bit signed
48
+ const arbitraryShortValue = fc.integer({ min: -32768, max: 32767 }); // 16-bit signed
49
+ const arbitraryIntValue = fc.integer({ min: -2147483648, max: 2147483647 }); // 32-bit signed
50
+ const arbitraryLongValue = fc.bigInt({ min: -9223372036854775808n, max: 9223372036854775807n }); // 64-bit signed
51
+
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 });
56
+
57
+ // No-operation
58
+ const arbitraryNop = fc.constant<DalvikBytecodeOperation>({
59
+ operation: 'nop',
60
+ });
61
+
62
+ // Move operations (Format 12x)
63
+ const arbitraryMove = fc.record({
64
+ operation: fc.constant('move' as const),
65
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
66
+ });
67
+
68
+ const arbitraryMoveWide = fc.record({
69
+ operation: fc.constant('move-wide' as const),
70
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
71
+ });
72
+
73
+ const arbitraryMoveObject = fc.record({
74
+ operation: fc.constant('move-object' as const),
75
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
76
+ });
77
+
78
+ // Move operations (Format 22x - from16)
79
+ const arbitraryMoveFrom16 = fc.record({
80
+ operation: fc.constant('move/from16' as const),
81
+ registers: fc.tuple(arbitraryRegister8, arbitraryRegister16),
82
+ });
83
+
84
+ const arbitraryMoveWideFrom16 = fc.record({
85
+ operation: fc.constant('move-wide/from16' as const),
86
+ registers: fc.tuple(arbitraryRegister8, arbitraryRegister16),
87
+ });
88
+
89
+ const arbitraryMoveObjectFrom16 = fc.record({
90
+ operation: fc.constant('move-object/from16' as const),
91
+ registers: fc.tuple(arbitraryRegister8, arbitraryRegister16),
92
+ });
93
+
94
+ // Move operations (Format 32x - /16)
95
+ const arbitraryMoveWide16 = fc.record({
96
+ operation: fc.constant('move-wide/16' as const),
97
+ registers: fc.tuple(arbitraryRegister16, arbitraryRegister16),
98
+ });
99
+
100
+ // Move-result operations (Format 11x)
101
+ const arbitraryMoveResult = fc.record({
102
+ operation: fc.constant('move-result' as const),
103
+ registers: fc.tuple(arbitraryRegister8),
104
+ });
105
+
106
+ const arbitraryMoveResultWide = fc.record({
107
+ operation: fc.constant('move-result-wide' as const),
108
+ registers: fc.tuple(arbitraryRegister8),
109
+ });
110
+
111
+ const arbitraryMoveResultObject = fc.record({
112
+ operation: fc.constant('move-result-object' as const),
113
+ registers: fc.tuple(arbitraryRegister8),
114
+ });
115
+
116
+ const arbitraryMoveException = fc.record({
117
+ operation: fc.constant('move-exception' as const),
118
+ registers: fc.tuple(arbitraryRegister8),
119
+ });
120
+
121
+ // Return operations
122
+ const arbitraryReturnVoid = fc.constant<DalvikBytecodeOperation>({
123
+ operation: 'return-void',
124
+ });
125
+
126
+ const arbitraryReturn = fc.record({
127
+ operation: fc.constant('return' as const),
128
+ registers: fc.tuple(arbitraryRegister8),
129
+ });
130
+
131
+ const arbitraryReturnWide = fc.record({
132
+ operation: fc.constant('return-wide' as const),
133
+ registers: fc.tuple(arbitraryRegister8),
134
+ });
135
+
136
+ const arbitraryReturnObject = fc.record({
137
+ operation: fc.constant('return-object' as const),
138
+ registers: fc.tuple(arbitraryRegister8),
139
+ });
140
+
141
+ // Const operations
142
+ const arbitraryConst4 = fc.record({
143
+ operation: fc.constant('const/4' as const),
144
+ registers: fc.tuple(arbitraryRegister4),
145
+ value: arbitraryNibbleValue,
146
+ });
147
+
148
+ const arbitraryConst16 = fc.record({
149
+ operation: fc.constant('const/16' as const),
150
+ registers: fc.tuple(arbitraryRegister8),
151
+ value: arbitraryShortValue,
152
+ });
153
+
154
+ const arbitraryConst = fc.record({
155
+ operation: fc.constant('const' as const),
156
+ registers: fc.tuple(arbitraryRegister8),
157
+ value: arbitraryIntValue,
158
+ });
159
+
160
+ const arbitraryConstHigh16 = fc.record({
161
+ operation: fc.constant('const/high16' as const),
162
+ registers: fc.tuple(arbitraryRegister8),
163
+ // Parser shifts left by 16, so value is stored pre-shifted
164
+ value: arbitraryShortValue.map(v => v << 16),
165
+ });
166
+
167
+ const arbitraryConstWide16 = fc.record({
168
+ operation: fc.constant('const-wide/16' as const),
169
+ registers: fc.tuple(arbitraryRegister8),
170
+ // Parser stores value as-is (no shift for const-wide/16)
171
+ value: fc.integer({ min: -32768, max: 32767 }).map(v => BigInt(v)),
172
+ });
173
+
174
+ const arbitraryConstWide32 = fc.record({
175
+ operation: fc.constant('const-wide/32' as const),
176
+ registers: fc.tuple(arbitraryRegister8),
177
+ // Parser stores value as-is (no shift for const-wide/32)
178
+ value: fc.integer({ min: -2147483648, max: 2147483647 }).map(v => BigInt(v)),
179
+ });
180
+
181
+ const arbitraryConstWide = fc.record({
182
+ operation: fc.constant('const-wide' as const),
183
+ registers: fc.tuple(arbitraryRegister8),
184
+ value: arbitraryLongValue,
185
+ });
186
+
187
+ const arbitraryConstWideHigh16 = fc.record({
188
+ operation: fc.constant('const-wide/high16' as const),
189
+ registers: fc.tuple(arbitraryRegister8),
190
+ // Parser shifts value left by 48 bits, so generate pre-shifted values
191
+ value: fc.integer({ min: -32768, max: 32767 }).map(v => BigInt(v) << 48n),
192
+ });
193
+
194
+ const arbitraryConstString = fc.record({
195
+ operation: fc.constant('const-string' as const),
196
+ registers: fc.tuple(arbitraryRegister8),
197
+ stringIndex: arbitraryIndexIntoStringIds,
198
+ });
199
+
200
+ const arbitraryConstStringJumbo = fc.record({
201
+ operation: fc.constant('const-string/jumbo' as const),
202
+ registers: fc.tuple(arbitraryRegister8),
203
+ stringIndex: arbitraryIndexIntoStringIds,
204
+ });
205
+
206
+ const arbitraryConstClass = fc.record({
207
+ operation: fc.constant('const-class' as const),
208
+ registers: fc.tuple(arbitraryRegister8),
209
+ typeIndex: arbitraryIndexIntoTypeIds,
210
+ });
211
+
212
+ const arbitraryConstMethodHandle = fc.record({
213
+ operation: fc.constant('const-method-handle' as const),
214
+ registers: fc.tuple(arbitraryRegister8),
215
+ methodIndex: arbitraryIndexIntoMethodIds,
216
+ });
217
+
218
+ // Monitor operations
219
+ const arbitraryMonitorEnter = fc.record({
220
+ operation: fc.constant('monitor-enter' as const),
221
+ registers: fc.tuple(arbitraryRegister8),
222
+ });
223
+
224
+ const arbitraryMonitorExit = fc.record({
225
+ operation: fc.constant('monitor-exit' as const),
226
+ registers: fc.tuple(arbitraryRegister8),
227
+ });
228
+
229
+ // Type operations
230
+ const arbitraryCheckCast = fc.record({
231
+ operation: fc.constant('check-cast' as const),
232
+ registers: fc.tuple(arbitraryRegister8),
233
+ typeIndex: arbitraryIndexIntoTypeIds,
234
+ });
235
+
236
+ const arbitraryInstanceOf = fc.record({
237
+ operation: fc.constant('instance-of' as const),
238
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
239
+ typeIndex: arbitraryIndexIntoTypeIds,
240
+ });
241
+
242
+ const arbitraryNewInstance = fc.record({
243
+ operation: fc.constant('new-instance' as const),
244
+ registers: fc.tuple(arbitraryRegister8),
245
+ typeIndex: arbitraryIndexIntoTypeIds,
246
+ });
247
+
248
+ const arbitraryNewArray = fc.record({
249
+ operation: fc.constant('new-array' as const),
250
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
251
+ typeIndex: arbitraryIndexIntoTypeIds,
252
+ });
253
+
254
+ // Array operations
255
+ const arbitraryArrayLength = fc.record({
256
+ operation: fc.constant('array-length' as const),
257
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
258
+ });
259
+
260
+ const arbitraryThrow = fc.record({
261
+ operation: fc.constant('throw' as const),
262
+ registers: fc.tuple(arbitraryRegister8),
263
+ });
264
+
265
+ // Goto operations
266
+ const arbitraryGoto = fc.record({
267
+ operation: fc.constant('goto' as const),
268
+ branchOffset: arbitraryBranchOffset8,
269
+ });
270
+
271
+ const arbitraryGoto16 = fc.record({
272
+ operation: fc.constant('goto/16' as const),
273
+ branchOffset: arbitraryBranchOffset16,
274
+ });
275
+
276
+ const arbitraryGoto32 = fc.record({
277
+ operation: fc.constant('goto/32' as const),
278
+ branchOffset: arbitraryBranchOffset32,
279
+ });
280
+
281
+ // Switch operations
282
+ const arbitraryPackedSwitch = fc.record({
283
+ operation: fc.constant('packed-switch' as const),
284
+ registers: fc.tuple(arbitraryRegister8),
285
+ branchOffset: arbitraryBranchOffset32,
286
+ });
287
+
288
+ const arbitrarySparseSwitch = fc.record({
289
+ operation: fc.constant('sparse-switch' as const),
290
+ registers: fc.tuple(arbitraryRegister8),
291
+ branchOffset: arbitraryBranchOffset32,
292
+ });
293
+
294
+ const arbitraryFillArrayData = fc.record({
295
+ operation: fc.constant('fill-array-data' as const),
296
+ registers: fc.tuple(arbitraryRegister8),
297
+ branchOffset: arbitraryBranchOffset32,
298
+ });
299
+
300
+ // Payload operations
301
+ const arbitraryPackedSwitchPayload = fc
302
+ .nat({ max: 20 })
303
+ .chain(size =>
304
+ fc.record({
305
+ operation: fc.constant('packed-switch-payload' as const),
306
+ value: arbitraryIntValue,
307
+ branchOffsets: fc.array(arbitraryBranchOffset32, { minLength: size, maxLength: size }),
308
+ })
309
+ );
310
+
311
+ const arbitrarySparseSwitchPayload = fc
312
+ .nat({ max: 20 })
313
+ .chain(size =>
314
+ fc.record({
315
+ operation: fc.constant('sparse-switch-payload' as const),
316
+ keys: fc.array(arbitraryIntValue, { minLength: size, maxLength: size }),
317
+ branchOffsets: fc.array(arbitraryBranchOffset32, { minLength: size, maxLength: size }),
318
+ })
319
+ );
320
+
321
+ const arbitraryFillArrayDataPayload = fc
322
+ .record({
323
+ elementWidth: fc.constantFrom(1, 2, 4, 8),
324
+ size: fc.nat({ max: 100 }),
325
+ })
326
+ .chain(({ elementWidth, size }) =>
327
+ fc.record({
328
+ operation: fc.constant('fill-array-data-payload' as const),
329
+ elementWidth: fc.constant(elementWidth),
330
+ // Data array contains bytes, so length must be size * elementWidth
331
+ data: fc.array(fc.nat({ max: 255 }), { minLength: size * elementWidth, maxLength: size * elementWidth }),
332
+ })
333
+ );
334
+
335
+ // If-test operations (Format 22t)
336
+ // Commutative operations (if-eq, if-ne) generate sorted registers to match parser behavior
337
+ const arbitraryIfEqual = fc.record({
338
+ operation: fc.constant('if-eq' as const),
339
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4).map(([a, b]) => [a, b].sort((x, y) => x - y)),
340
+ branchOffset: arbitraryBranchOffset16,
341
+ });
342
+
343
+ const arbitraryIfNotEqual = fc.record({
344
+ operation: fc.constant('if-ne' as const),
345
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4).map(([a, b]) => [a, b].sort((x, y) => x - y)),
346
+ branchOffset: arbitraryBranchOffset16,
347
+ });
348
+
349
+ const arbitraryIfLessThan = fc.record({
350
+ operation: fc.constant('if-lt' as const),
351
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
352
+ branchOffset: arbitraryBranchOffset16,
353
+ });
354
+
355
+ const arbitraryIfGreaterThanOrEqualTo = fc.record({
356
+ operation: fc.constant('if-ge' as const),
357
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
358
+ branchOffset: arbitraryBranchOffset16,
359
+ });
360
+
361
+ const arbitraryIfGreaterThan = fc.record({
362
+ operation: fc.constant('if-gt' as const),
363
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
364
+ branchOffset: arbitraryBranchOffset16,
365
+ });
366
+
367
+ const arbitraryIfLessThanOrEqualTo = fc.record({
368
+ operation: fc.constant('if-le' as const),
369
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
370
+ branchOffset: arbitraryBranchOffset16,
371
+ });
372
+
373
+ // If-test-zero operations (Format 21t)
374
+ const arbitraryIfEqualZero = fc.record({
375
+ operation: fc.constant('if-eqz' as const),
376
+ registers: fc.tuple(arbitraryRegister8),
377
+ branchOffset: arbitraryBranchOffset16,
378
+ });
379
+
380
+ const arbitraryIfNotEqualZero = fc.record({
381
+ operation: fc.constant('if-nez' as const),
382
+ registers: fc.tuple(arbitraryRegister8),
383
+ branchOffset: arbitraryBranchOffset16,
384
+ });
385
+
386
+ const arbitraryIfLessThanZero = fc.record({
387
+ operation: fc.constant('if-ltz' as const),
388
+ registers: fc.tuple(arbitraryRegister8),
389
+ branchOffset: arbitraryBranchOffset16,
390
+ });
391
+
392
+ const arbitraryIfGreaterThanOrEqualToZero = fc.record({
393
+ operation: fc.constant('if-gez' as const),
394
+ registers: fc.tuple(arbitraryRegister8),
395
+ branchOffset: arbitraryBranchOffset16,
396
+ });
397
+
398
+ const arbitraryIfGreaterThanZero = fc.record({
399
+ operation: fc.constant('if-gtz' as const),
400
+ registers: fc.tuple(arbitraryRegister8),
401
+ branchOffset: arbitraryBranchOffset16,
402
+ });
403
+
404
+ const arbitraryIfLessThanOrEqualToZero = fc.record({
405
+ operation: fc.constant('if-lez' as const),
406
+ registers: fc.tuple(arbitraryRegister8),
407
+ branchOffset: arbitraryBranchOffset16,
408
+ });
409
+
410
+ // Array element operations (Format 23x)
411
+ const createArbitraryArrayElementOperation = (operation: string) =>
412
+ fc.record({
413
+ operation: fc.constant(operation as any),
414
+ registers: fc.tuple(arbitraryRegister8, arbitraryRegister8, arbitraryRegister8),
415
+ });
416
+
417
+ const arbitraryArrayElementGet = createArbitraryArrayElementOperation('aget');
418
+ const arbitraryArrayElementGetWide = createArbitraryArrayElementOperation('aget-wide');
419
+ const arbitraryArrayElementGetObject = createArbitraryArrayElementOperation('aget-object');
420
+ const arbitraryArrayElementGetBoolean = createArbitraryArrayElementOperation('aget-boolean');
421
+ const arbitraryArrayElementGetByte = createArbitraryArrayElementOperation('aget-byte');
422
+ const arbitraryArrayElementGetChar = createArbitraryArrayElementOperation('aget-char');
423
+ const arbitraryArrayElementGetShort = createArbitraryArrayElementOperation('aget-short');
424
+ const arbitraryArrayElementPut = createArbitraryArrayElementOperation('aput');
425
+ const arbitraryArrayElementPutWide = createArbitraryArrayElementOperation('aput-wide');
426
+ const arbitraryArrayElementPutObject = createArbitraryArrayElementOperation('aput-object');
427
+ const arbitraryArrayElementPutBoolean = createArbitraryArrayElementOperation('aput-boolean');
428
+ const arbitraryArrayElementPutByte = createArbitraryArrayElementOperation('aput-byte');
429
+ const arbitraryArrayElementPutChar = createArbitraryArrayElementOperation('aput-char');
430
+ const arbitraryArrayElementPutShort = createArbitraryArrayElementOperation('aput-short');
431
+
432
+ // Instance field operations (Format 22c)
433
+ const createArbitraryInstanceFieldOperation = (operation: string) =>
434
+ fc.record({
435
+ operation: fc.constant(operation as any),
436
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
437
+ fieldIndex: arbitraryIndexIntoFieldIds,
438
+ });
439
+
440
+ const arbitraryInstanceFieldGet = createArbitraryInstanceFieldOperation('iget');
441
+ const arbitraryInstanceFieldGetWide = createArbitraryInstanceFieldOperation('iget-wide');
442
+ const arbitraryInstanceFieldGetObject = createArbitraryInstanceFieldOperation('iget-object');
443
+ const arbitraryInstanceFieldGetBoolean = createArbitraryInstanceFieldOperation('iget-boolean');
444
+ const arbitraryInstanceFieldGetByte = createArbitraryInstanceFieldOperation('iget-byte');
445
+ const arbitraryInstanceFieldGetChar = createArbitraryInstanceFieldOperation('iget-char');
446
+ const arbitraryInstanceFieldGetShort = createArbitraryInstanceFieldOperation('iget-short');
447
+ const arbitraryInstanceFieldPut = createArbitraryInstanceFieldOperation('iput');
448
+ const arbitraryInstanceFieldPutWide = createArbitraryInstanceFieldOperation('iput-wide');
449
+ const arbitraryInstanceFieldPutObject = createArbitraryInstanceFieldOperation('iput-object');
450
+ const arbitraryInstanceFieldPutBoolean = createArbitraryInstanceFieldOperation('iput-boolean');
451
+ const arbitraryInstanceFieldPutByte = createArbitraryInstanceFieldOperation('iput-byte');
452
+ const arbitraryInstanceFieldPutChar = createArbitraryInstanceFieldOperation('iput-char');
453
+ const arbitraryInstanceFieldPutShort = createArbitraryInstanceFieldOperation('iput-short');
454
+
455
+ // Static field operations (Format 21c)
456
+ const createArbitraryStaticFieldOperation = (operation: string) =>
457
+ fc.record({
458
+ operation: fc.constant(operation as any),
459
+ registers: fc.tuple(arbitraryRegister8),
460
+ fieldIndex: arbitraryIndexIntoFieldIds,
461
+ });
462
+
463
+ const arbitraryStaticFieldGet = createArbitraryStaticFieldOperation('sget');
464
+ const arbitraryStaticFieldGetWide = createArbitraryStaticFieldOperation('sget-wide');
465
+ const arbitraryStaticFieldGetObject = createArbitraryStaticFieldOperation('sget-object');
466
+ const arbitraryStaticFieldGetBoolean = createArbitraryStaticFieldOperation('sget-boolean');
467
+ const arbitraryStaticFieldGetByte = createArbitraryStaticFieldOperation('sget-byte');
468
+ const arbitraryStaticFieldGetChar = createArbitraryStaticFieldOperation('sget-char');
469
+ const arbitraryStaticFieldGetShort = createArbitraryStaticFieldOperation('sget-short');
470
+ const arbitraryStaticFieldPut = createArbitraryStaticFieldOperation('sput');
471
+ const arbitraryStaticFieldPutWide = createArbitraryStaticFieldOperation('sput-wide');
472
+ const arbitraryStaticFieldPutObject = createArbitraryStaticFieldOperation('sput-object');
473
+ const arbitraryStaticFieldPutBoolean = createArbitraryStaticFieldOperation('sput-boolean');
474
+ const arbitraryStaticFieldPutByte = createArbitraryStaticFieldOperation('sput-byte');
475
+ const arbitraryStaticFieldPutChar = createArbitraryStaticFieldOperation('sput-char');
476
+ const arbitraryStaticFieldPutShort = createArbitraryStaticFieldOperation('sput-short');
477
+
478
+ // Invoke operations (Format 35c)
479
+ const createArbitraryInvokeOperation = (operation: string) =>
480
+ fc
481
+ .nat({ max: 5 })
482
+ .chain(registerCount =>
483
+ fc.record({
484
+ operation: fc.constant(operation as any),
485
+ registers: fc.array(arbitraryRegister4, {
486
+ minLength: registerCount,
487
+ maxLength: registerCount,
488
+ }),
489
+ methodIndex: arbitraryIndexIntoMethodIds,
490
+ })
491
+ );
492
+
493
+ const arbitraryInvokeVirtual = createArbitraryInvokeOperation('invoke-virtual');
494
+ const arbitraryInvokeSuper = createArbitraryInvokeOperation('invoke-super');
495
+ const arbitraryInvokeDirect = createArbitraryInvokeOperation('invoke-direct');
496
+ const arbitraryInvokeStatic = createArbitraryInvokeOperation('invoke-static');
497
+ const arbitraryInvokeInterface = createArbitraryInvokeOperation('invoke-interface');
498
+
499
+ // Invoke-range operations (Format 3rc)
500
+ const createArbitraryInvokeRangeOperation = (operation: string) =>
501
+ fc
502
+ .nat({ max: 255 })
503
+ .chain(registerCount =>
504
+ fc.record({
505
+ operation: fc.constant(operation as any),
506
+ registers: fc
507
+ .nat({ max: 65535 - registerCount })
508
+ .map(startRegister =>
509
+ Array.from({ length: registerCount }, (_, i) => startRegister + i)
510
+ ),
511
+ methodIndex: arbitraryIndexIntoMethodIds,
512
+ })
513
+ );
514
+
515
+ const arbitraryInvokeVirtualRange = createArbitraryInvokeRangeOperation('invoke-virtual/range');
516
+ const arbitraryInvokeSuperRange = createArbitraryInvokeRangeOperation('invoke-super/range');
517
+ const arbitraryInvokeDirectRange = createArbitraryInvokeRangeOperation('invoke-direct/range');
518
+ const arbitraryInvokeStaticRange = createArbitraryInvokeRangeOperation('invoke-static/range');
519
+ const arbitraryInvokeInterfaceRange = createArbitraryInvokeRangeOperation(
520
+ 'invoke-interface/range'
521
+ );
522
+
523
+ // Invoke-polymorphic operations
524
+ const arbitraryInvokePolymorphic = fc
525
+ .nat({ max: 5 })
526
+ .chain(registerCount =>
527
+ fc.record({
528
+ operation: fc.constant('invoke-polymorphic' as const),
529
+ registers: fc.array(arbitraryRegister4, {
530
+ minLength: registerCount,
531
+ maxLength: registerCount,
532
+ }),
533
+ methodIndex: arbitraryIndexIntoMethodIds,
534
+ protoIndex: arbitraryIndexIntoPrototypeIds,
535
+ })
536
+ );
537
+
538
+ const arbitraryInvokePolymorphicRange = fc
539
+ .nat({ max: 255 })
540
+ .chain(registerCount =>
541
+ fc.record({
542
+ operation: fc.constant('invoke-polymorphic/range' as const),
543
+ registers: fc
544
+ .nat({ max: 65535 - registerCount })
545
+ .map(startRegister =>
546
+ Array.from({ length: registerCount }, (_, i) => startRegister + i)
547
+ ),
548
+ methodIndex: arbitraryIndexIntoMethodIds,
549
+ protoIndex: arbitraryIndexIntoPrototypeIds,
550
+ })
551
+ );
552
+
553
+ // Filled-new-array operations
554
+ const arbitraryFilledNewArray = fc
555
+ .nat({ max: 5 })
556
+ .chain(registerCount =>
557
+ fc.record({
558
+ operation: fc.constant('filled-new-array' as const),
559
+ registers: fc.array(arbitraryRegister4, {
560
+ minLength: registerCount,
561
+ maxLength: registerCount,
562
+ }),
563
+ typeIndex: arbitraryIndexIntoTypeIds,
564
+ })
565
+ );
566
+
567
+ const arbitraryFilledNewArrayRange = fc
568
+ .nat({ max: 255 })
569
+ .chain(registerCount =>
570
+ fc.record({
571
+ operation: fc.constant('filled-new-array/range' as const),
572
+ registers: fc
573
+ .nat({ max: 65535 - registerCount })
574
+ .map(startRegister =>
575
+ Array.from({ length: registerCount }, (_, i) => startRegister + i)
576
+ ),
577
+ typeIndex: arbitraryIndexIntoTypeIds,
578
+ })
579
+ );
580
+
581
+ // Binary operations (Format 23x)
582
+ const createArbitraryBinaryOperation = (operation: string) =>
583
+ fc.record({
584
+ operation: fc.constant(operation as any),
585
+ registers: fc.tuple(arbitraryRegister8, arbitraryRegister8, arbitraryRegister8),
586
+ });
587
+
588
+ // Int operations
589
+ const arbitraryAddInt = createArbitraryBinaryOperation('add-int');
590
+ const arbitrarySubInt = createArbitraryBinaryOperation('sub-int');
591
+ const arbitraryMulInt = createArbitraryBinaryOperation('mul-int');
592
+ const arbitraryDivInt = createArbitraryBinaryOperation('div-int');
593
+ const arbitraryRemInt = createArbitraryBinaryOperation('rem-int');
594
+ const arbitraryAndInt = createArbitraryBinaryOperation('and-int');
595
+ const arbitraryOrInt = createArbitraryBinaryOperation('or-int');
596
+ const arbitraryXorInt = createArbitraryBinaryOperation('xor-int');
597
+ const arbitraryShlInt = createArbitraryBinaryOperation('shl-int');
598
+ const arbitraryShrInt = createArbitraryBinaryOperation('shr-int');
599
+ const arbitraryUshrInt = createArbitraryBinaryOperation('ushr-int');
600
+
601
+ // Long operations
602
+ const arbitraryAddLong = createArbitraryBinaryOperation('add-long');
603
+ const arbitrarySubLong = createArbitraryBinaryOperation('sub-long');
604
+ const arbitraryMulLong = createArbitraryBinaryOperation('mul-long');
605
+ const arbitraryDivLong = createArbitraryBinaryOperation('div-long');
606
+ const arbitraryRemLong = createArbitraryBinaryOperation('rem-long');
607
+ const arbitraryAndLong = createArbitraryBinaryOperation('and-long');
608
+ const arbitraryOrLong = createArbitraryBinaryOperation('or-long');
609
+ const arbitraryXorLong = createArbitraryBinaryOperation('xor-long');
610
+ const arbitraryShlLong = createArbitraryBinaryOperation('shl-long');
611
+ const arbitraryShrLong = createArbitraryBinaryOperation('shr-long');
612
+ const arbitraryUshrLong = createArbitraryBinaryOperation('ushr-long');
613
+
614
+ // Float operations
615
+ const arbitraryAddFloat = createArbitraryBinaryOperation('add-float');
616
+ const arbitrarySubFloat = createArbitraryBinaryOperation('sub-float');
617
+ const arbitraryMulFloat = createArbitraryBinaryOperation('mul-float');
618
+ const arbitraryDivFloat = createArbitraryBinaryOperation('div-float');
619
+
620
+ // Double operations
621
+ const arbitraryAddDouble = createArbitraryBinaryOperation('add-double');
622
+ const arbitrarySubDouble = createArbitraryBinaryOperation('sub-double');
623
+ const arbitraryMulDouble = createArbitraryBinaryOperation('mul-double');
624
+ const arbitraryDivDouble = createArbitraryBinaryOperation('div-double');
625
+ const arbitraryRemDouble = createArbitraryBinaryOperation('rem-double');
626
+
627
+ // Compare operations
628
+ const arbitraryCmpLong = createArbitraryBinaryOperation('cmp-long');
629
+ const arbitraryCmplFloat = createArbitraryBinaryOperation('cmpl-float');
630
+ const arbitraryCmpgFloat = createArbitraryBinaryOperation('cmpg-float');
631
+ const arbitraryCmplDouble = createArbitraryBinaryOperation('cmpl-double');
632
+ const arbitraryCmpgDouble = createArbitraryBinaryOperation('cmpg-double');
633
+
634
+ // Binary operations in-place (Format 12x)
635
+ const createArbitraryBinaryOperationInPlace = (operation: string) =>
636
+ fc.record({
637
+ operation: fc.constant(operation as any),
638
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
639
+ });
640
+
641
+ const arbitraryAddIntInPlace = createArbitraryBinaryOperationInPlace('add-int/2addr');
642
+ const arbitrarySubIntInPlace = createArbitraryBinaryOperationInPlace('sub-int/2addr');
643
+ const arbitraryMulIntInPlace = createArbitraryBinaryOperationInPlace('mul-int/2addr');
644
+ const arbitraryDivIntInPlace = createArbitraryBinaryOperationInPlace('div-int/2addr');
645
+ const arbitraryRemIntInPlace = createArbitraryBinaryOperationInPlace('rem-int/2addr');
646
+ const arbitraryAndIntInPlace = createArbitraryBinaryOperationInPlace('and-int/2addr');
647
+ const arbitraryOrIntInPlace = createArbitraryBinaryOperationInPlace('or-int/2addr');
648
+ const arbitraryXorIntInPlace = createArbitraryBinaryOperationInPlace('xor-int/2addr');
649
+ const arbitraryShlIntInPlace = createArbitraryBinaryOperationInPlace('shl-int/2addr');
650
+ const arbitraryShrIntInPlace = createArbitraryBinaryOperationInPlace('shr-int/2addr');
651
+ const arbitraryUshrIntInPlace = createArbitraryBinaryOperationInPlace('ushr-int/2addr');
652
+ const arbitraryAddLongInPlace = createArbitraryBinaryOperationInPlace('add-long/2addr');
653
+ const arbitrarySubLongInPlace = createArbitraryBinaryOperationInPlace('sub-long/2addr');
654
+ const arbitraryMulLongInPlace = createArbitraryBinaryOperationInPlace('mul-long/2addr');
655
+ const arbitraryDivLongInPlace = createArbitraryBinaryOperationInPlace('div-long/2addr');
656
+ const arbitraryRemLongInPlace = createArbitraryBinaryOperationInPlace('rem-long/2addr');
657
+ const arbitraryAndLongInPlace = createArbitraryBinaryOperationInPlace('and-long/2addr');
658
+ const arbitraryOrLongInPlace = createArbitraryBinaryOperationInPlace('or-long/2addr');
659
+ const arbitraryXorLongInPlace = createArbitraryBinaryOperationInPlace('xor-long/2addr');
660
+ const arbitraryShlLongInPlace = createArbitraryBinaryOperationInPlace('shl-long/2addr');
661
+ const arbitraryShrLongInPlace = createArbitraryBinaryOperationInPlace('shr-long/2addr');
662
+ const arbitraryUshrLongInPlace = createArbitraryBinaryOperationInPlace('ushr-long/2addr');
663
+ const arbitraryAddFloatInPlace = createArbitraryBinaryOperationInPlace('add-float/2addr');
664
+ const arbitrarySubFloatInPlace = createArbitraryBinaryOperationInPlace('sub-float/2addr');
665
+ const arbitraryMulFloatInPlace = createArbitraryBinaryOperationInPlace('mul-float/2addr');
666
+ const arbitraryDivFloatInPlace = createArbitraryBinaryOperationInPlace('div-float/2addr');
667
+ const arbitraryRemFloatInPlace = createArbitraryBinaryOperationInPlace('rem-float/2addr');
668
+ const arbitraryAddDoubleInPlace = createArbitraryBinaryOperationInPlace('add-double/2addr');
669
+ const arbitrarySubDoubleInPlace = createArbitraryBinaryOperationInPlace('sub-double/2addr');
670
+ const arbitraryMulDoubleInPlace = createArbitraryBinaryOperationInPlace('mul-double/2addr');
671
+ const arbitraryDivDoubleInPlace = createArbitraryBinaryOperationInPlace('div-double/2addr');
672
+ const arbitraryRemDoubleInPlace = createArbitraryBinaryOperationInPlace('rem-double/2addr');
673
+
674
+ // Binary operations with literal8 (Format 22b)
675
+ const createArbitraryBinaryOperationLiteral8 = (operation: string) =>
676
+ fc.record({
677
+ operation: fc.constant(operation as any),
678
+ registers: fc.tuple(arbitraryRegister8, arbitraryRegister8),
679
+ value: arbitraryByteValue,
680
+ });
681
+
682
+ const arbitraryAddIntLiteral8 = createArbitraryBinaryOperationLiteral8('add-int/lit8');
683
+ const arbitraryReverseSubtractIntLiteral8 = createArbitraryBinaryOperationLiteral8(
684
+ 'rsub-int/lit8'
685
+ );
686
+ const arbitraryMultiplyIntLiteral8 = createArbitraryBinaryOperationLiteral8('mul-int/lit8');
687
+ const arbitraryDivideIntLiteral8 = createArbitraryBinaryOperationLiteral8('div-int/lit8');
688
+ const arbitraryRemainderIntLiteral8 = createArbitraryBinaryOperationLiteral8('rem-int/lit8');
689
+ const arbitraryAndIntLiteral8 = createArbitraryBinaryOperationLiteral8('and-int/lit8');
690
+ const arbitraryOrIntLiteral8 = createArbitraryBinaryOperationLiteral8('or-int/lit8');
691
+ const arbitraryXorIntLiteral8 = createArbitraryBinaryOperationLiteral8('xor-int/lit8');
692
+ const arbitraryShlIntLiteral8 = createArbitraryBinaryOperationLiteral8('shl-int/lit8');
693
+ const arbitraryShrIntLiteral8 = createArbitraryBinaryOperationLiteral8('shr-int/lit8');
694
+ const arbitraryUshrIntLiteral8 = createArbitraryBinaryOperationLiteral8('ushr-int/lit8');
695
+
696
+ // Binary operations with literal16 (Format 22s)
697
+ const createArbitraryBinaryOperationLiteral16 = (operation: string) =>
698
+ fc.record({
699
+ operation: fc.constant(operation as any),
700
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
701
+ value: arbitraryShortValue,
702
+ });
703
+
704
+ const arbitraryAddIntLiteral16 = createArbitraryBinaryOperationLiteral16('add-int/lit16');
705
+ const arbitraryReverseSubtractIntLiteral16 = createArbitraryBinaryOperationLiteral16('rsub-int');
706
+ const arbitraryMultiplyIntLiteral16 = createArbitraryBinaryOperationLiteral16('mul-int/lit16');
707
+ const arbitraryDivideIntLiteral16 = createArbitraryBinaryOperationLiteral16('div-int/lit16');
708
+ const arbitraryRemainderIntLiteral16 = createArbitraryBinaryOperationLiteral16('rem-int/lit16');
709
+ const arbitraryAndIntLiteral16 = createArbitraryBinaryOperationLiteral16('and-int/lit16');
710
+ const arbitraryOrIntLiteral16 = createArbitraryBinaryOperationLiteral16('or-int/lit16');
711
+ const arbitraryXorIntLiteral16 = createArbitraryBinaryOperationLiteral16('xor-int/lit16');
712
+
713
+ // Unary operations (Format 12x)
714
+ const createArbitraryUnaryOperation = (operation: string) =>
715
+ fc.record({
716
+ operation: fc.constant(operation as any),
717
+ registers: fc.tuple(arbitraryRegister4, arbitraryRegister4),
718
+ });
719
+
720
+ const arbitraryNegateInt = createArbitraryUnaryOperation('neg-int');
721
+ const arbitraryNotInt = createArbitraryUnaryOperation('not-int');
722
+ const arbitraryNegateLong = createArbitraryUnaryOperation('neg-long');
723
+ const arbitraryNotLong = createArbitraryUnaryOperation('not-long');
724
+ const arbitraryNegateFloat = createArbitraryUnaryOperation('neg-float');
725
+ const arbitraryNegateDouble = createArbitraryUnaryOperation('neg-double');
726
+ const arbitraryIntToLong = createArbitraryUnaryOperation('int-to-long');
727
+ const arbitraryIntToFloat = createArbitraryUnaryOperation('int-to-float');
728
+ const arbitraryIntToDouble = createArbitraryUnaryOperation('int-to-double');
729
+ const arbitraryLongToInt = createArbitraryUnaryOperation('long-to-int');
730
+ const arbitraryLongToFloat = createArbitraryUnaryOperation('long-to-float');
731
+ const arbitraryLongToDouble = createArbitraryUnaryOperation('long-to-double');
732
+ const arbitraryFloatToInt = createArbitraryUnaryOperation('float-to-int');
733
+ const arbitraryFloatToLong = createArbitraryUnaryOperation('float-to-long');
734
+ const arbitraryFloatToDouble = createArbitraryUnaryOperation('float-to-double');
735
+ const arbitraryDoubleToInt = createArbitraryUnaryOperation('double-to-int');
736
+ const arbitraryDoubleToLong = createArbitraryUnaryOperation('double-to-long');
737
+ const arbitraryDoubleToFloat = createArbitraryUnaryOperation('double-to-float');
738
+ const arbitraryIntToByte = createArbitraryUnaryOperation('int-to-byte');
739
+ const arbitraryIntToChar = createArbitraryUnaryOperation('int-to-char');
740
+ const arbitraryIntToShort = createArbitraryUnaryOperation('int-to-short');
741
+
742
+ // Combine all operations
743
+ export const arbitraryDalvikBytecodeOperation: fc.Arbitrary<DalvikBytecodeOperation> = fc.oneof(
744
+ arbitraryNop,
745
+ // Move operations
746
+ arbitraryMove,
747
+ arbitraryMoveWide,
748
+ arbitraryMoveObject,
749
+ arbitraryMoveFrom16,
750
+ arbitraryMoveWideFrom16,
751
+ arbitraryMoveObjectFrom16,
752
+ arbitraryMoveWide16,
753
+ arbitraryMoveResult,
754
+ arbitraryMoveResultWide,
755
+ arbitraryMoveResultObject,
756
+ arbitraryMoveException,
757
+ // Return operations
758
+ arbitraryReturnVoid,
759
+ arbitraryReturn,
760
+ arbitraryReturnWide,
761
+ arbitraryReturnObject,
762
+ // Const operations
763
+ arbitraryConst4,
764
+ arbitraryConst16,
765
+ arbitraryConst,
766
+ arbitraryConstHigh16,
767
+ arbitraryConstWide16,
768
+ arbitraryConstWide32,
769
+ arbitraryConstWide,
770
+ arbitraryConstWideHigh16,
771
+ arbitraryConstString,
772
+ arbitraryConstStringJumbo,
773
+ arbitraryConstClass,
774
+ arbitraryConstMethodHandle,
775
+ // Monitor operations
776
+ arbitraryMonitorEnter,
777
+ arbitraryMonitorExit,
778
+ // Type operations
779
+ arbitraryCheckCast,
780
+ arbitraryInstanceOf,
781
+ arbitraryNewInstance,
782
+ arbitraryNewArray,
783
+ // Array operations
784
+ arbitraryArrayLength,
785
+ arbitraryThrow,
786
+ // Goto operations
787
+ arbitraryGoto,
788
+ arbitraryGoto16,
789
+ arbitraryGoto32,
790
+ // Switch operations
791
+ arbitraryPackedSwitch,
792
+ arbitrarySparseSwitch,
793
+ arbitraryFillArrayData,
794
+ // Payload operations
795
+ arbitraryPackedSwitchPayload,
796
+ arbitrarySparseSwitchPayload,
797
+ arbitraryFillArrayDataPayload,
798
+ // If-test operations
799
+ arbitraryIfEqual,
800
+ arbitraryIfNotEqual,
801
+ arbitraryIfLessThan,
802
+ arbitraryIfGreaterThanOrEqualTo,
803
+ arbitraryIfGreaterThan,
804
+ arbitraryIfLessThanOrEqualTo,
805
+ // If-test-zero operations
806
+ arbitraryIfEqualZero,
807
+ arbitraryIfNotEqualZero,
808
+ arbitraryIfLessThanZero,
809
+ arbitraryIfGreaterThanOrEqualToZero,
810
+ arbitraryIfGreaterThanZero,
811
+ arbitraryIfLessThanOrEqualToZero,
812
+ // Array element operations
813
+ arbitraryArrayElementGet,
814
+ arbitraryArrayElementGetWide,
815
+ arbitraryArrayElementGetObject,
816
+ arbitraryArrayElementGetBoolean,
817
+ arbitraryArrayElementGetByte,
818
+ arbitraryArrayElementGetChar,
819
+ arbitraryArrayElementGetShort,
820
+ arbitraryArrayElementPut,
821
+ arbitraryArrayElementPutWide,
822
+ arbitraryArrayElementPutObject,
823
+ arbitraryArrayElementPutBoolean,
824
+ arbitraryArrayElementPutByte,
825
+ arbitraryArrayElementPutChar,
826
+ arbitraryArrayElementPutShort,
827
+ // Instance field operations
828
+ arbitraryInstanceFieldGet,
829
+ arbitraryInstanceFieldGetWide,
830
+ arbitraryInstanceFieldGetObject,
831
+ arbitraryInstanceFieldGetBoolean,
832
+ arbitraryInstanceFieldGetByte,
833
+ arbitraryInstanceFieldGetChar,
834
+ arbitraryInstanceFieldGetShort,
835
+ arbitraryInstanceFieldPut,
836
+ arbitraryInstanceFieldPutWide,
837
+ arbitraryInstanceFieldPutObject,
838
+ arbitraryInstanceFieldPutBoolean,
839
+ arbitraryInstanceFieldPutByte,
840
+ arbitraryInstanceFieldPutChar,
841
+ arbitraryInstanceFieldPutShort,
842
+ // Static field operations
843
+ arbitraryStaticFieldGet,
844
+ arbitraryStaticFieldGetWide,
845
+ arbitraryStaticFieldGetObject,
846
+ arbitraryStaticFieldGetBoolean,
847
+ arbitraryStaticFieldGetByte,
848
+ arbitraryStaticFieldGetChar,
849
+ arbitraryStaticFieldGetShort,
850
+ arbitraryStaticFieldPut,
851
+ arbitraryStaticFieldPutWide,
852
+ arbitraryStaticFieldPutObject,
853
+ arbitraryStaticFieldPutBoolean,
854
+ arbitraryStaticFieldPutByte,
855
+ arbitraryStaticFieldPutChar,
856
+ arbitraryStaticFieldPutShort,
857
+ // Invoke operations
858
+ arbitraryInvokeVirtual,
859
+ arbitraryInvokeSuper,
860
+ arbitraryInvokeDirect,
861
+ arbitraryInvokeStatic,
862
+ arbitraryInvokeInterface,
863
+ arbitraryInvokeVirtualRange,
864
+ arbitraryInvokeSuperRange,
865
+ arbitraryInvokeDirectRange,
866
+ arbitraryInvokeStaticRange,
867
+ arbitraryInvokeInterfaceRange,
868
+ arbitraryInvokePolymorphic,
869
+ arbitraryInvokePolymorphicRange,
870
+ // Filled-new-array operations
871
+ arbitraryFilledNewArray,
872
+ arbitraryFilledNewArrayRange,
873
+ // Binary operations
874
+ arbitraryAddInt,
875
+ arbitrarySubInt,
876
+ arbitraryMulInt,
877
+ arbitraryDivInt,
878
+ arbitraryRemInt,
879
+ arbitraryAndInt,
880
+ arbitraryOrInt,
881
+ arbitraryXorInt,
882
+ arbitraryShlInt,
883
+ arbitraryShrInt,
884
+ arbitraryUshrInt,
885
+ arbitraryAddLong,
886
+ arbitrarySubLong,
887
+ arbitraryMulLong,
888
+ arbitraryDivLong,
889
+ arbitraryRemLong,
890
+ arbitraryAndLong,
891
+ arbitraryOrLong,
892
+ arbitraryXorLong,
893
+ arbitraryShlLong,
894
+ arbitraryShrLong,
895
+ arbitraryUshrLong,
896
+ arbitraryAddFloat,
897
+ arbitrarySubFloat,
898
+ arbitraryMulFloat,
899
+ arbitraryDivFloat,
900
+ arbitraryAddDouble,
901
+ arbitrarySubDouble,
902
+ arbitraryMulDouble,
903
+ arbitraryDivDouble,
904
+ arbitraryRemDouble,
905
+ arbitraryCmpLong,
906
+ arbitraryCmplFloat,
907
+ arbitraryCmpgFloat,
908
+ arbitraryCmplDouble,
909
+ arbitraryCmpgDouble,
910
+ // Binary operations in-place
911
+ arbitraryAddIntInPlace,
912
+ arbitrarySubIntInPlace,
913
+ arbitraryMulIntInPlace,
914
+ arbitraryDivIntInPlace,
915
+ arbitraryRemIntInPlace,
916
+ arbitraryAndIntInPlace,
917
+ arbitraryOrIntInPlace,
918
+ arbitraryXorIntInPlace,
919
+ arbitraryShlIntInPlace,
920
+ arbitraryShrIntInPlace,
921
+ arbitraryUshrIntInPlace,
922
+ arbitraryAddLongInPlace,
923
+ arbitrarySubLongInPlace,
924
+ arbitraryMulLongInPlace,
925
+ arbitraryDivLongInPlace,
926
+ arbitraryRemLongInPlace,
927
+ arbitraryAndLongInPlace,
928
+ arbitraryOrLongInPlace,
929
+ arbitraryXorLongInPlace,
930
+ arbitraryShlLongInPlace,
931
+ arbitraryShrLongInPlace,
932
+ arbitraryUshrLongInPlace,
933
+ arbitraryAddFloatInPlace,
934
+ arbitrarySubFloatInPlace,
935
+ arbitraryMulFloatInPlace,
936
+ arbitraryDivFloatInPlace,
937
+ arbitraryRemFloatInPlace,
938
+ arbitraryAddDoubleInPlace,
939
+ arbitrarySubDoubleInPlace,
940
+ arbitraryMulDoubleInPlace,
941
+ arbitraryDivDoubleInPlace,
942
+ arbitraryRemDoubleInPlace,
943
+ // Binary operations with literal8
944
+ arbitraryAddIntLiteral8,
945
+ arbitraryReverseSubtractIntLiteral8,
946
+ arbitraryMultiplyIntLiteral8,
947
+ arbitraryDivideIntLiteral8,
948
+ arbitraryRemainderIntLiteral8,
949
+ arbitraryAndIntLiteral8,
950
+ arbitraryOrIntLiteral8,
951
+ arbitraryXorIntLiteral8,
952
+ arbitraryShlIntLiteral8,
953
+ arbitraryShrIntLiteral8,
954
+ arbitraryUshrIntLiteral8,
955
+ // Binary operations with literal16
956
+ arbitraryAddIntLiteral16,
957
+ arbitraryReverseSubtractIntLiteral16,
958
+ arbitraryMultiplyIntLiteral16,
959
+ arbitraryDivideIntLiteral16,
960
+ arbitraryRemainderIntLiteral16,
961
+ arbitraryAndIntLiteral16,
962
+ arbitraryOrIntLiteral16,
963
+ arbitraryXorIntLiteral16,
964
+ // Unary operations
965
+ arbitraryNegateInt,
966
+ arbitraryNotInt,
967
+ arbitraryNegateLong,
968
+ arbitraryNotLong,
969
+ arbitraryNegateFloat,
970
+ arbitraryNegateDouble,
971
+ arbitraryIntToLong,
972
+ arbitraryIntToFloat,
973
+ arbitraryIntToDouble,
974
+ arbitraryLongToInt,
975
+ arbitraryLongToFloat,
976
+ arbitraryLongToDouble,
977
+ arbitraryFloatToInt,
978
+ arbitraryFloatToLong,
979
+ arbitraryFloatToDouble,
980
+ arbitraryDoubleToInt,
981
+ arbitraryDoubleToLong,
982
+ arbitraryDoubleToFloat,
983
+ arbitraryIntToByte,
984
+ arbitraryIntToChar,
985
+ arbitraryIntToShort
986
+ );
987
+
988
+ // Arbitrary for complete Dalvik bytecode (array of operations)
989
+ export const arbitraryDalvikBytecode: fc.Arbitrary<DalvikBytecode> = fc.array(
990
+ arbitraryDalvikBytecodeOperation,
991
+ { minLength: 0, maxLength: 100 }
992
+ );