Files
reverse-engineering-anything/tests/boundary/cli/cliIntegerArguments.test.ts
T
S1MonandS1Mon bcc6775dc1 fix(cli): reject non-decimal Android overload index tokens (#7493)
Android overload selection declared a plain number, so the CLI argument
parser coerced the raw token with Number before the schema ran. An empty
token therefore arrived as 0, and hexadecimal, exponent, signed, and
float spellings arrived as their numeric value, leaving both commands to
proceed to artifact admission on a selector the caller never wrote as a
decimal integer.

Reuse the existing decimal token parser that the other integer CLI
options already use. Omitted and explicit decimal zero keep their current
meanings, and the published schema for overloadIndex is unchanged.

Validation: npm run compile, the cli-boundary vitest project for
tests/boundary/cli/cliIntegerArguments.test.ts (56 passed), npm run
typecheck, npm run lint, npm run lint:typed, npm run format:check, npm
run metadata:check, npm run verify:architecture-guards, and npm run
knip:production. The new cases fail against the base source and pass with
the change.

Fixes #7430.

Co-authored-by: S1Mon <251732998+fgfsgsgvo@users.noreply.github.com>
2026-10-27 23:25:32 +08:00

174 lines
4.2 KiB
TypeScript

import { describe, expect } from "vitest";
import { cliTest, type CliResult } from "../../support/cli/cliFixture.js";
const SESSION_ID = "27d3e3f1-f1e5-49ae-91ec-95af1f343a5a";
const NON_INTEGER_TEXT = [
"",
" ",
"\t",
"1\n",
"0x1",
"0b1",
"1e0",
"+1",
"1.0",
"9007199254740992",
];
const NON_INTEGER_OPTION_TEXT = [...NON_INTEGER_TEXT, "-0"];
const expectCliValidationError = (result: CliResult, field: string): void => {
expect(result.exitCode).toBe(1);
expect(JSON.parse(result.stdout)).toMatchObject({
code: "VALIDATION_ERROR",
fieldErrors: expect.arrayContaining([
expect.objectContaining({ path: expect.stringContaining(field) }),
]),
});
};
describe("CLI integer arguments", () => {
cliTest.for(NON_INTEGER_TEXT)(
"rejects %j as a Cutter expected generation",
async (value, { cli }) => {
const result = await cli.run({
arguments: ["cutter-command", SESSION_ID, value, "pdi", "--json"],
});
expectCliValidationError(result, "expectedGeneration");
},
);
cliTest.for(NON_INTEGER_TEXT)(
"rejects %j as a web module script index",
async (value, { cli }) => {
const result = await cli.run({
arguments: [
"trace-web-module-imports",
"/nonexistent/manifest.json",
value,
"--json",
],
});
expectCliValidationError(result, "scriptIndex");
},
);
cliTest.for(NON_INTEGER_OPTION_TEXT)(
"rejects %j in a repeated web capture record selector",
async (value, { cli }) => {
const result = await cli.run({
arguments: [
"inspect-web-network-capture",
"/nonexistent/capture.qlog",
"qlog",
"--record",
"0",
"--record",
value,
"--json",
],
});
expectCliValidationError(result, "record");
},
);
cliTest.for(NON_INTEGER_OPTION_TEXT)(
"rejects %j as an Android method overload index",
async (value, { cli }) => {
const result = await cli.run({
arguments: [
"inspect-android-method",
"/nonexistent/missing.apk",
"com.example.Main",
"run",
`--overload-index=${value}`,
"--json",
],
});
expectCliValidationError(result, "overloadIndex");
},
);
cliTest.for(NON_INTEGER_OPTION_TEXT)(
"rejects %j as an Android reference overload index",
async (value, { cli }) => {
const result = await cli.run({
arguments: [
"trace-android-references",
"/nonexistent/missing.apk",
"com.example.Main",
`--overload-index=${value}`,
"--json",
],
});
expectCliValidationError(result, "overloadIndex");
},
);
cliTest(
"keeps an explicit decimal zero as an Android method overload index",
async ({ cli }) => {
const result = await cli.run({
arguments: [
"inspect-android-method",
"/nonexistent/missing.apk",
"com.example.Main",
"run",
"--overload-index=0",
"--json",
],
});
expect(result.exitCode).toBe(1);
expect(JSON.parse(result.stdout)).toMatchObject({
code: "target_unavailable",
});
},
);
cliTest(
"keeps an explicit decimal zero as an Android reference overload index",
async ({ cli }) => {
const result = await cli.run({
arguments: [
"trace-android-references",
"/nonexistent/missing.apk",
"com.example.Main",
"--overload-index=0",
"--json",
],
});
expect(result.exitCode).toBe(1);
expect(JSON.parse(result.stdout)).toMatchObject({
code: "target_unavailable",
});
},
);
cliTest(
"keeps the one-based source line lower bound at the CLI boundary",
async ({ cli }) => {
const result = await cli.run({
arguments: [
"trace-web-source-location",
"/nonexistent/manifest.json",
"0",
"/nonexistent/app.js.map",
"https://example.test/app.js.map",
"0",
"0",
"--json",
],
});
expectCliValidationError(result, "line");
},
);
});