mirror of
https://github.com/morluto/rea.git
synced 2026-11-10 16:57:19 +00:00
feat(analysis): make resource budgets recoverable across CLI and MCP (#9706)
* refactor(analysis): centralize resource budgets and recovery facts * feat(analysis): expose ASAR and Ghidra runtime admission controls * feat(artifacts): expose reader admission and preserve limited recognition * feat(javascript): expose recoverable semantic precision budgets * feat(web): add recoverable source-map budgets and compact retained views * feat(web): make historical capture decoding budgets recoverable * fix(desktop): enforce selected view policies across capture and export * feat(runtime): make Frida and LLDB retention budgets selectable * feat(native): expose diagnostic budgets and preserve exhaustion causes * feat(managed): expose recoverable snapshot and representation budgets * feat(metadata): make Go and Rust inspection budgets recoverable * feat(wasm): expose representation and producer admissions * feat(evm): expose per-call worker resource budgets * feat(android): make resource and string-pool omissions recoverable * feat(producers): expose command and recorded-capture budgets * docs(analysis): record recovery contracts and integrated validation * fix(docs): link calibration oracle from published verification pages * fix(docs): restore desktop task anchors and receipt links * test(analysis): align fixtures with selectable budget contracts * fix(analysis): remove source-location projector dependency cycle * test(analysis): refresh budget recovery and verifier regressions * test(analysis): preserve format and publication recovery expectations * test(windows): align conformance with owned runtime admission * fix(desktop): preserve selected alias kinds in exported state * test(analysis): align provider fixtures with recoverable budgets * test(desktop): validate emitted alias metadata structurally * fix(ghidra): classify bounded Windows endpoint refusals * test(cli): assert selectable artifact admission recovery * fix(cli): preserve capture provenance in environment builds
This commit is contained in:
1 parent
55b6d2ca20
commit
cb4e5cfbff
515 files changed
+21066
-3637
No files matched your search
@@ -1,52 +1,3 @@
|
||||
export const inspectionLimits = {
|
||||
referenceOffset: 0,
|
||||
referenceLimit: 100,
|
||||
resourceOffset: 0,
|
||||
resourceLimit: 100,
|
||||
attributeOffset: 0,
|
||||
attributeLimit: 100,
|
||||
maxMetadataBytes: 1024 * 1024,
|
||||
maxTableRows: 1_000,
|
||||
maxHeapItemBytes: 1024 * 1024,
|
||||
};
|
||||
|
||||
export const memberLimits = {
|
||||
typeOffset: 0,
|
||||
typeLimit: 100,
|
||||
methodOffset: 0,
|
||||
methodLimit: 100,
|
||||
fieldOffset: 0,
|
||||
fieldLimit: 100,
|
||||
memberRefOffset: 0,
|
||||
memberRefLimit: 100,
|
||||
edgeOffset: 0,
|
||||
edgeLimit: 100,
|
||||
instructionAnchorLimit: 100,
|
||||
maxMetadataBytes: 1024 * 1024,
|
||||
maxTableRows: 1_000,
|
||||
maxHeapItemBytes: 1024 * 1024,
|
||||
maxMethodBodyBytes: 1024 * 1024,
|
||||
maxMethodInstructions: 1_000,
|
||||
};
|
||||
|
||||
export const nativeBoundaryLimits = {
|
||||
moduleRefOffset: 0,
|
||||
moduleRefLimit: 100,
|
||||
importOffset: 0,
|
||||
importLimit: 100,
|
||||
implementationOffset: 0,
|
||||
implementationLimit: 100,
|
||||
maxMetadataBytes: 1024 * 1024,
|
||||
maxTableRows: 1_000,
|
||||
maxHeapItemBytes: 1024 * 1024,
|
||||
};
|
||||
|
||||
export const comparisonLimits = {
|
||||
max_method_matches: 100,
|
||||
max_field_matches: 100,
|
||||
max_candidates: 20,
|
||||
};
|
||||
|
||||
export const defaultIlBody = Buffer.from([
|
||||
0x32, 0x02, 0x7b, 0x01, 0x00, 0x00, 0x04, 0x28, 0x01, 0x00, 0x00, 0x0a, 0x2a,
|
||||
]);
|
||||
@@ -19,13 +19,7 @@ import {
|
||||
buildNativePeFixture,
|
||||
} from "../../fixtures/managed/pe.mjs";
|
||||
import { createManagedConformanceSupport } from "./support.mjs";
|
||||
import {
|
||||
comparisonLimits,
|
||||
defaultIlBody,
|
||||
inspectionLimits,
|
||||
memberLimits,
|
||||
nativeBoundaryLimits,
|
||||
} from "./config.mjs";
|
||||
import { defaultIlBody } from "./config.mjs";
|
||||
import { createManagedCompletionReport } from "./completion-report.mjs";
|
||||
import {
|
||||
completeVerifierRun,
|
||||
@@ -45,8 +39,6 @@ const {
|
||||
sha256,
|
||||
} = createManagedConformanceSupport({
|
||||
workspace,
|
||||
inspectionLimits,
|
||||
memberLimits,
|
||||
defaultIlBody,
|
||||
});
|
||||
|
||||
@@ -58,7 +50,6 @@ try {
|
||||
const modernArtifact = inspectManagedArtifactBytes(
|
||||
modern.bytes,
|
||||
modern.target,
|
||||
inspectionLimits,
|
||||
);
|
||||
assert.equal(modernArtifact.classification.status, "managed");
|
||||
assert.equal(modernArtifact.classification.runtime_family, "modern-dotnet");
|
||||
@@ -83,7 +74,6 @@ try {
|
||||
const frameworkArtifact = inspectManagedArtifactBytes(
|
||||
framework.bytes,
|
||||
framework.target,
|
||||
inspectionLimits,
|
||||
);
|
||||
assert.equal(
|
||||
frameworkArtifact.classification.runtime_family,
|
||||
@@ -93,7 +83,6 @@ try {
|
||||
const frameworkBoundaries = inspectManagedNativeBoundariesBytes(
|
||||
framework.bytes,
|
||||
framework.target,
|
||||
nativeBoundaryLimits,
|
||||
);
|
||||
assert.equal(frameworkBoundaries.pinvoke_imports.length, 1);
|
||||
assert.equal(
|
||||
@@ -108,14 +97,13 @@ try {
|
||||
const frameworkMembers = inspectManagedMembersBytes(
|
||||
framework.bytes,
|
||||
framework.target,
|
||||
memberLimits,
|
||||
);
|
||||
const frameworkArtifactEvidence = createEvidence(
|
||||
framework.target,
|
||||
MANAGED_STATIC_PROVIDER,
|
||||
{
|
||||
operation: "inspect_managed_artifact",
|
||||
parameters: inspectionLimits,
|
||||
parameters: {},
|
||||
result: frameworkArtifact,
|
||||
rawResult: null,
|
||||
limitations: frameworkArtifact.limitations,
|
||||
@@ -127,7 +115,7 @@ try {
|
||||
MANAGED_STATIC_PROVIDER,
|
||||
{
|
||||
operation: "inspect_managed_members",
|
||||
parameters: memberLimits,
|
||||
parameters: {},
|
||||
result: frameworkMembers,
|
||||
rawResult: null,
|
||||
limitations: frameworkMembers.limitations,
|
||||
@@ -139,7 +127,7 @@ try {
|
||||
MANAGED_STATIC_PROVIDER,
|
||||
{
|
||||
operation: "inspect_managed_native_boundaries",
|
||||
parameters: nativeBoundaryLimits,
|
||||
parameters: {},
|
||||
result: frameworkBoundaries,
|
||||
rawResult: null,
|
||||
limitations: frameworkBoundaries.limitations,
|
||||
@@ -221,7 +209,6 @@ try {
|
||||
const r2rArtifact = inspectManagedArtifactBytes(
|
||||
readyToRun.bytes,
|
||||
readyToRun.target,
|
||||
inspectionLimits,
|
||||
);
|
||||
assert.equal(r2rArtifact.pe.architecture, "x86_64");
|
||||
assert.equal(
|
||||
@@ -231,7 +218,6 @@ try {
|
||||
const r2rBoundaries = inspectManagedNativeBoundariesBytes(
|
||||
readyToRun.bytes,
|
||||
readyToRun.target,
|
||||
nativeBoundaryLimits,
|
||||
);
|
||||
assert.equal(r2rBoundaries.summary.ready_to_run, true);
|
||||
assert.equal(r2rBoundaries.native_implementations[0]?.code_type, "native");
|
||||
@@ -248,7 +234,6 @@ try {
|
||||
const obfuscatedMembers = inspectManagedMembersBytes(
|
||||
obfuscated.bytes,
|
||||
obfuscated.target,
|
||||
memberLimits,
|
||||
);
|
||||
assert.equal(obfuscatedMembers.types[0]?.full_name, "Fixture.ꙮType");
|
||||
assert.equal(obfuscatedMembers.methods[0]?.name, "λ⛧");
|
||||
@@ -309,11 +294,6 @@ try {
|
||||
const comparison = await compareManagedMemberPaths({
|
||||
leftPath: left.path,
|
||||
rightPath: right.path,
|
||||
memberLimits: {
|
||||
maxFileBytes: 1024 * 1024,
|
||||
...memberLimits,
|
||||
},
|
||||
comparisonLimits,
|
||||
});
|
||||
assert.equal(comparison.ok, true);
|
||||
const comparisonResult = comparison.value.normalized_result;
|
||||
@@ -341,11 +321,6 @@ try {
|
||||
const partialBodyComparison = await compareManagedMemberPaths({
|
||||
leftPath: unavailableBodyLeft.path,
|
||||
rightPath: unavailableBodyRight.path,
|
||||
memberLimits: {
|
||||
maxFileBytes: 1024 * 1024,
|
||||
...memberLimits,
|
||||
},
|
||||
comparisonLimits,
|
||||
});
|
||||
assert.equal(partialBodyComparison.ok, true);
|
||||
const partialBodyMethod =
|
||||
@@ -363,7 +338,6 @@ try {
|
||||
const nativeResult = inspectManagedArtifactBytes(
|
||||
nativeOnly.bytes,
|
||||
nativeOnly.target,
|
||||
inspectionLimits,
|
||||
);
|
||||
assert.equal(nativeResult.classification.status, "not-managed");
|
||||
|
||||
@@ -373,7 +347,6 @@ try {
|
||||
const malformedResult = inspectManagedArtifactBytes(
|
||||
malformed.bytes,
|
||||
malformed.target,
|
||||
inspectionLimits,
|
||||
);
|
||||
assert.equal(malformedResult.classification.status, "malformed");
|
||||
|
||||
|
||||
@@ -14,13 +14,7 @@ import {
|
||||
parseManagedAppManifest,
|
||||
} from "./manifest-parser.mjs";
|
||||
|
||||
export const createManagedManifestVerifier = (context) => ({
|
||||
verifyManagedAppManifest: (rawManifest, manifestPath) =>
|
||||
verifyManagedAppManifest(context, rawManifest, manifestPath),
|
||||
});
|
||||
|
||||
async function verifyManagedAppManifest(context, rawManifest, manifestPath) {
|
||||
const { appManifestInspectionLimits } = context;
|
||||
export async function verifyManagedAppManifest(rawManifest, manifestPath) {
|
||||
const manifest = parseManagedAppManifest(rawManifest);
|
||||
const targetPath = isAbsolute(manifest.target.path)
|
||||
? manifest.target.path
|
||||
@@ -36,25 +30,15 @@ async function verifyManagedAppManifest(context, rawManifest, manifestPath) {
|
||||
`target sha256 mismatch: expected ${manifest.target.sha256}, observed ${target.sha256}`,
|
||||
);
|
||||
const bytes = await readFile(targetPath);
|
||||
const artifact = inspectManagedArtifactBytes(
|
||||
bytes,
|
||||
target,
|
||||
appManifestInspectionLimits,
|
||||
);
|
||||
const artifact = inspectManagedArtifactBytes(bytes, target);
|
||||
verifyManifestTarget(manifest, artifact);
|
||||
const methodVerification = verifyManifestMethods(
|
||||
context,
|
||||
manifest,
|
||||
bytes,
|
||||
target,
|
||||
);
|
||||
const methodVerification = verifyManifestMethods(manifest, bytes, target);
|
||||
const { methods, inspectedMethods } = methodVerification;
|
||||
let assertions = 1 + methodVerification.assertions;
|
||||
const applicationGraph =
|
||||
manifest.application_graph === undefined
|
||||
? undefined
|
||||
: verifyManagedAppManifestApplicationGraph({
|
||||
context,
|
||||
graphManifest: manifest.application_graph,
|
||||
bytes,
|
||||
target,
|
||||
@@ -109,17 +93,12 @@ function verifyManifestTarget(manifest, artifact) {
|
||||
);
|
||||
}
|
||||
|
||||
function verifyManifestMethods(context, manifest, bytes, target) {
|
||||
function verifyManifestMethods(manifest, bytes, target) {
|
||||
const methods = [];
|
||||
let assertions = 0;
|
||||
const inspectedMethods = new Map();
|
||||
for (const expectedMethod of manifest.methods) {
|
||||
const method = inspectManagedMethodByToken(
|
||||
context,
|
||||
bytes,
|
||||
target,
|
||||
expectedMethod,
|
||||
);
|
||||
const method = inspectManagedMethodByToken(bytes, target, expectedMethod);
|
||||
ensure(
|
||||
method.signature.raw_sha256 === expectedMethod.signature_sha256,
|
||||
`method ${expectedMethod.token} signature sha256 mismatch: expected ${expectedMethod.signature_sha256}, observed ${method.signature.raw_sha256}`,
|
||||
@@ -154,7 +133,6 @@ function verifyManifestMethods(context, manifest, bytes, target) {
|
||||
}
|
||||
|
||||
function verifyManagedAppManifestApplicationGraph({
|
||||
context,
|
||||
graphManifest,
|
||||
bytes,
|
||||
target,
|
||||
@@ -164,7 +142,6 @@ function verifyManagedAppManifestApplicationGraph({
|
||||
}) {
|
||||
const graphByToken = new Map();
|
||||
const projectionState = {
|
||||
context,
|
||||
graphByToken,
|
||||
inspectedMethods,
|
||||
bytes,
|
||||
@@ -238,8 +215,6 @@ function verifyManagedAppManifestApplicationGraph({
|
||||
}
|
||||
|
||||
const projectManifestMethod = (state, token) => {
|
||||
const { appManifestInspectionLimits, appManifestMemberLimits } =
|
||||
state.context;
|
||||
const existing = state.graphByToken.get(token);
|
||||
if (existing !== undefined) return existing;
|
||||
const method = state.inspectedMethods.get(token);
|
||||
@@ -248,7 +223,6 @@ const projectManifestMethod = (state, token) => {
|
||||
`application graph method ${token} must also be declared in manifest.methods`,
|
||||
);
|
||||
const members = inspectManagedMethodPageByToken(
|
||||
state.context,
|
||||
state.bytes,
|
||||
state.target,
|
||||
token,
|
||||
@@ -258,7 +232,7 @@ const projectManifestMethod = (state, token) => {
|
||||
MANAGED_STATIC_PROVIDER,
|
||||
{
|
||||
operation: "inspect_managed_artifact",
|
||||
parameters: appManifestInspectionLimits,
|
||||
parameters: {},
|
||||
result: state.artifact,
|
||||
rawResult: null,
|
||||
limitations: state.artifact.limitations,
|
||||
@@ -268,7 +242,7 @@ const projectManifestMethod = (state, token) => {
|
||||
const memberEvidence = createEvidence(state.target, MANAGED_STATIC_PROVIDER, {
|
||||
operation: "inspect_managed_members",
|
||||
parameters: {
|
||||
...appManifestMemberLimits,
|
||||
methodLimit: 1,
|
||||
methodOffset: methodTokenRow(token) - 1,
|
||||
},
|
||||
result: members,
|
||||
@@ -298,9 +272,8 @@ const projectManifestMethod = (state, token) => {
|
||||
return projection;
|
||||
};
|
||||
|
||||
function inspectManagedMethodByToken(context, bytes, target, expectedMethod) {
|
||||
function inspectManagedMethodByToken(bytes, target, expectedMethod) {
|
||||
const members = inspectManagedMethodPageByToken(
|
||||
context,
|
||||
bytes,
|
||||
target,
|
||||
expectedMethod.token,
|
||||
@@ -319,11 +292,10 @@ function inspectManagedMethodByToken(context, bytes, target, expectedMethod) {
|
||||
return method;
|
||||
}
|
||||
|
||||
function inspectManagedMethodPageByToken(context, bytes, target, token) {
|
||||
const { appManifestMemberLimits } = context;
|
||||
function inspectManagedMethodPageByToken(bytes, target, token) {
|
||||
const row = methodTokenRow(token);
|
||||
return inspectManagedMembersBytes(bytes, target, {
|
||||
...appManifestMemberLimits,
|
||||
methodLimit: 1,
|
||||
methodOffset: row - 1,
|
||||
});
|
||||
}
|
||||
@@ -10,13 +10,12 @@ import { inspectManagedMembersBytes } from "../../../dist/dotnet/ManagedMemberIn
|
||||
import { importManagedReconstructionEvidence } from "../../../dist/application/managed/ManagedReconstructionService.js";
|
||||
import { createEvidence } from "../../../dist/domain/evidence.js";
|
||||
import { MANAGED_STATIC_PROVIDER } from "../../../dist/domain/investigationProviders.js";
|
||||
import { createManagedManifestVerifier } from "./manifest.mjs";
|
||||
import { verifyManagedAppManifest } from "./manifest.mjs";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
export const createManagedConformanceOracleSupport = (context) => {
|
||||
const verifier = createManagedManifestVerifier(context);
|
||||
const support = { ...context, ...verifier };
|
||||
const support = { ...context, verifyManagedAppManifest };
|
||||
return {
|
||||
runManagedAppManifestSelfTest: () => runManagedAppManifestSelfTest(support),
|
||||
runOptionalManagedAppManifest: () => runOptionalManagedAppManifest(support),
|
||||
@@ -29,16 +28,8 @@ async function runManagedAppManifestSelfTest(context) {
|
||||
methodName: "PinnedSemanticSlice",
|
||||
ilBody: context.defaultIlBody,
|
||||
});
|
||||
const artifact = inspectManagedArtifactBytes(
|
||||
sample.bytes,
|
||||
sample.target,
|
||||
context.inspectionLimits,
|
||||
);
|
||||
const members = inspectManagedMembersBytes(
|
||||
sample.bytes,
|
||||
sample.target,
|
||||
context.memberLimits,
|
||||
);
|
||||
const artifact = inspectManagedArtifactBytes(sample.bytes, sample.target);
|
||||
const members = inspectManagedMembersBytes(sample.bytes, sample.target);
|
||||
const method = members.methods[0];
|
||||
assert.ok(method);
|
||||
const summary = await context.verifyManagedAppManifest(
|
||||
@@ -132,16 +123,8 @@ async function runOptionalIlspyOracle(context) {
|
||||
const sample = await context.fixture("ilspy-oracle.exe", {
|
||||
methodName: "PinnedSemanticSlice",
|
||||
});
|
||||
const artifact = inspectManagedArtifactBytes(
|
||||
sample.bytes,
|
||||
sample.target,
|
||||
context.inspectionLimits,
|
||||
);
|
||||
const members = inspectManagedMembersBytes(
|
||||
sample.bytes,
|
||||
sample.target,
|
||||
context.memberLimits,
|
||||
);
|
||||
const artifact = inspectManagedArtifactBytes(sample.bytes, sample.target);
|
||||
const members = inspectManagedMembersBytes(sample.bytes, sample.target);
|
||||
const method = members.methods[0];
|
||||
ensureIlspy(method !== undefined, "source-owned fixture has no method");
|
||||
const listOutput = await runIlspy(
|
||||
@@ -167,7 +150,6 @@ async function runOptionalIlspyOracle(context) {
|
||||
"ilspycmd C# output exceeded the managed reconstruction import bound",
|
||||
);
|
||||
const reconstructionImport = importIlspyReconstruction({
|
||||
context,
|
||||
sample,
|
||||
method,
|
||||
members,
|
||||
@@ -210,7 +192,6 @@ async function runOptionalIlspyOracle(context) {
|
||||
}
|
||||
|
||||
function importIlspyReconstruction({
|
||||
context,
|
||||
sample,
|
||||
method,
|
||||
members,
|
||||
@@ -223,7 +204,7 @@ function importIlspyReconstruction({
|
||||
MANAGED_STATIC_PROVIDER,
|
||||
{
|
||||
operation: "inspect_managed_members",
|
||||
parameters: context.memberLimits,
|
||||
parameters: {},
|
||||
result: members,
|
||||
rawResult: null,
|
||||
limitations: members.limitations,
|
||||
|
||||
@@ -17,32 +17,11 @@ export const createManagedConformanceSupport = (context) => {
|
||||
const fixture = (name, options) =>
|
||||
fixtureBytes(name, buildManagedPeFixture(options));
|
||||
const sha256 = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
||||
const appManifestInspectionLimits = {
|
||||
...context.inspectionLimits,
|
||||
maxMetadataBytes: 64 * 1024 * 1024,
|
||||
maxTableRows: 250_000,
|
||||
maxHeapItemBytes: 16 * 1024 * 1024,
|
||||
};
|
||||
const appManifestMemberLimits = {
|
||||
...context.memberLimits,
|
||||
typeLimit: 1,
|
||||
methodLimit: 1,
|
||||
fieldLimit: 1,
|
||||
memberRefLimit: 1,
|
||||
edgeLimit: 1,
|
||||
maxMetadataBytes: 64 * 1024 * 1024,
|
||||
maxTableRows: 250_000,
|
||||
maxHeapItemBytes: 16 * 1024 * 1024,
|
||||
maxMethodBodyBytes: 4 * 1024 * 1024,
|
||||
maxMethodInstructions: 20_000,
|
||||
};
|
||||
const base = {
|
||||
...context,
|
||||
fixture,
|
||||
fixtureBytes,
|
||||
sha256,
|
||||
appManifestInspectionLimits,
|
||||
appManifestMemberLimits,
|
||||
};
|
||||
return { ...base, ...createManagedConformanceOracleSupport(base) };
|
||||
};
|
||||
Reference in new issue
Block a user