mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:20:43 +00:00
refactor: share shell wrapper traversal
This commit is contained in:
@@ -57,46 +57,75 @@ export type ShellWrapperCommand = {
|
||||
command: string | null;
|
||||
};
|
||||
|
||||
function resolveShellWrapperSpecAndArgvInternal(
|
||||
argv: string[],
|
||||
depth: number,
|
||||
): { argv: string[]; wrapper: ShellWrapperSpec; payload: string } | null {
|
||||
if (!isWithinDispatchClassificationDepth(depth)) {
|
||||
type ShellWrapperCandidate<TState> = {
|
||||
argv: string[];
|
||||
token0: string;
|
||||
state: TState;
|
||||
};
|
||||
|
||||
function resolveShellWrapperCandidate<TState>(params: {
|
||||
argv: string[];
|
||||
depth: number;
|
||||
state: TState;
|
||||
onDispatchUnwrap?: (state: TState, wrappedArgv: string[]) => TState;
|
||||
}): ShellWrapperCandidate<TState> | null {
|
||||
if (!isWithinDispatchClassificationDepth(params.depth)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const token0 = argv[0]?.trim();
|
||||
const token0 = params.argv[0]?.trim();
|
||||
if (!token0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const dispatchUnwrap = unwrapKnownDispatchWrapperInvocation(argv);
|
||||
const dispatchUnwrap = unwrapKnownDispatchWrapperInvocation(params.argv);
|
||||
if (dispatchUnwrap.kind === "blocked") {
|
||||
return null;
|
||||
}
|
||||
if (dispatchUnwrap.kind === "unwrapped") {
|
||||
return resolveShellWrapperSpecAndArgvInternal(dispatchUnwrap.argv, depth + 1);
|
||||
return resolveShellWrapperCandidate({
|
||||
...params,
|
||||
argv: dispatchUnwrap.argv,
|
||||
depth: params.depth + 1,
|
||||
state: params.onDispatchUnwrap?.(params.state, params.argv) ?? params.state,
|
||||
});
|
||||
}
|
||||
|
||||
const shellMultiplexerUnwrap = unwrapKnownShellMultiplexerInvocation(argv);
|
||||
const shellMultiplexerUnwrap = unwrapKnownShellMultiplexerInvocation(params.argv);
|
||||
if (shellMultiplexerUnwrap.kind === "blocked") {
|
||||
return null;
|
||||
}
|
||||
if (shellMultiplexerUnwrap.kind === "unwrapped") {
|
||||
return resolveShellWrapperSpecAndArgvInternal(shellMultiplexerUnwrap.argv, depth + 1);
|
||||
return resolveShellWrapperCandidate({
|
||||
...params,
|
||||
argv: shellMultiplexerUnwrap.argv,
|
||||
depth: params.depth + 1,
|
||||
});
|
||||
}
|
||||
|
||||
const wrapper = findShellWrapperSpec(normalizeExecutableToken(token0));
|
||||
return { argv: params.argv, token0, state: params.state };
|
||||
}
|
||||
|
||||
function resolveShellWrapperSpecAndArgvInternal(
|
||||
argv: string[],
|
||||
depth: number,
|
||||
): { argv: string[]; wrapper: ShellWrapperSpec; payload: string } | null {
|
||||
const candidate = resolveShellWrapperCandidate({ argv, depth, state: null });
|
||||
if (!candidate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const wrapper = findShellWrapperSpec(normalizeExecutableToken(candidate.token0));
|
||||
if (!wrapper) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const payload = extractShellWrapperPayload(argv, wrapper);
|
||||
const payload = extractShellWrapperPayload(candidate.argv, wrapper);
|
||||
if (!payload) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { argv, wrapper, payload };
|
||||
return { argv: candidate.argv, wrapper, payload };
|
||||
}
|
||||
|
||||
function isWithinDispatchClassificationDepth(depth: number): boolean {
|
||||
@@ -108,31 +137,8 @@ export function isShellWrapperExecutable(token: string): boolean {
|
||||
}
|
||||
|
||||
function isShellWrapperInvocationInternal(argv: string[], depth: number): boolean {
|
||||
if (!isWithinDispatchClassificationDepth(depth)) {
|
||||
return false;
|
||||
}
|
||||
const token0 = argv[0]?.trim();
|
||||
if (!token0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dispatchUnwrap = unwrapKnownDispatchWrapperInvocation(argv);
|
||||
if (dispatchUnwrap.kind === "blocked") {
|
||||
return false;
|
||||
}
|
||||
if (dispatchUnwrap.kind === "unwrapped") {
|
||||
return isShellWrapperInvocationInternal(dispatchUnwrap.argv, depth + 1);
|
||||
}
|
||||
|
||||
const shellMultiplexerUnwrap = unwrapKnownShellMultiplexerInvocation(argv);
|
||||
if (shellMultiplexerUnwrap.kind === "blocked") {
|
||||
return false;
|
||||
}
|
||||
if (shellMultiplexerUnwrap.kind === "unwrapped") {
|
||||
return isShellWrapperInvocationInternal(shellMultiplexerUnwrap.argv, depth + 1);
|
||||
}
|
||||
|
||||
return isShellWrapperExecutable(token0);
|
||||
const candidate = resolveShellWrapperCandidate({ argv, depth, state: null });
|
||||
return candidate ? isShellWrapperExecutable(candidate.token0) : false;
|
||||
}
|
||||
|
||||
export function isShellWrapperInvocation(argv: string[]): boolean {
|
||||
@@ -235,49 +241,25 @@ function hasEnvManipulationBeforeShellWrapperInternal(
|
||||
depth: number,
|
||||
envManipulationSeen: boolean,
|
||||
): boolean {
|
||||
if (!isWithinDispatchClassificationDepth(depth)) {
|
||||
const candidate = resolveShellWrapperCandidate({
|
||||
argv,
|
||||
depth,
|
||||
state: envManipulationSeen,
|
||||
onDispatchUnwrap: (state, wrappedArgv) => state || hasDispatchEnvManipulation(wrappedArgv),
|
||||
});
|
||||
if (!candidate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const token0 = argv[0]?.trim();
|
||||
if (!token0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dispatchUnwrap = unwrapKnownDispatchWrapperInvocation(argv);
|
||||
if (dispatchUnwrap.kind === "blocked") {
|
||||
return false;
|
||||
}
|
||||
if (dispatchUnwrap.kind === "unwrapped") {
|
||||
const nextEnvManipulationSeen = envManipulationSeen || hasDispatchEnvManipulation(argv);
|
||||
return hasEnvManipulationBeforeShellWrapperInternal(
|
||||
dispatchUnwrap.argv,
|
||||
depth + 1,
|
||||
nextEnvManipulationSeen,
|
||||
);
|
||||
}
|
||||
|
||||
const shellMultiplexerUnwrap = unwrapKnownShellMultiplexerInvocation(argv);
|
||||
if (shellMultiplexerUnwrap.kind === "blocked") {
|
||||
return false;
|
||||
}
|
||||
if (shellMultiplexerUnwrap.kind === "unwrapped") {
|
||||
return hasEnvManipulationBeforeShellWrapperInternal(
|
||||
shellMultiplexerUnwrap.argv,
|
||||
depth + 1,
|
||||
envManipulationSeen,
|
||||
);
|
||||
}
|
||||
|
||||
const wrapper = findShellWrapperSpec(normalizeExecutableToken(token0));
|
||||
const wrapper = findShellWrapperSpec(normalizeExecutableToken(candidate.token0));
|
||||
if (!wrapper) {
|
||||
return false;
|
||||
}
|
||||
const payload = extractShellWrapperPayload(argv, wrapper);
|
||||
const payload = extractShellWrapperPayload(candidate.argv, wrapper);
|
||||
if (!payload) {
|
||||
return false;
|
||||
}
|
||||
return envManipulationSeen;
|
||||
return candidate.state;
|
||||
}
|
||||
|
||||
export function hasEnvManipulationBeforeShellWrapper(argv: string[]): boolean {
|
||||
|
||||
Reference in New Issue
Block a user