mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:20:43 +00:00
perf(infra): fast path posix containment checks
This commit is contained in:
@@ -6,6 +6,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
|
- Infra/path-guards: add a fast path for canonical absolute POSIX containment checks, avoiding repeated `path.resolve` and `path.relative` work in hot filesystem walkers. Refs #75895, #75575, and #68782. Thanks @Enderfga.
|
||||||
- Tools: add a platform-level tool descriptor planner for descriptor-first visibility, generic availability checks, and executor references. Thanks @shakkernerd.
|
- Tools: add a platform-level tool descriptor planner for descriptor-first visibility, generic availability checks, and executor references. Thanks @shakkernerd.
|
||||||
- Docs/Codex: clarify that ChatGPT/Codex subscription setups should use `openai/gpt-*` with `agentRuntime.id: "codex"` for native Codex runtime, while `openai-codex/*` remains the PI OAuth route. Thanks @pashpashpash.
|
- Docs/Codex: clarify that ChatGPT/Codex subscription setups should use `openai/gpt-*` with `agentRuntime.id: "codex"` for native Codex runtime, while `openai-codex/*` remains the PI OAuth route. Thanks @pashpashpash.
|
||||||
- Plugins/source checkout: load bundled plugins from the `extensions/*` pnpm workspace tree in source checkouts, so plugin-local dependencies and edits are used directly while packaged installs keep using the built runtime tree. Thanks @vincentkoc.
|
- Plugins/source checkout: load bundled plugins from the `extensions/*` pnpm workspace tree in source checkouts, so plugin-local dependencies and edits are used directly while packaged installs keep using the built runtime tree. Thanks @vincentkoc.
|
||||||
|
|||||||
@@ -74,6 +74,15 @@ describe("isPathInside", () => {
|
|||||||
["/workspace/root", "/workspace/root/nested/file.txt", true],
|
["/workspace/root", "/workspace/root/nested/file.txt", true],
|
||||||
["/workspace/root", "/workspace/root/..file.txt", true],
|
["/workspace/root", "/workspace/root/..file.txt", true],
|
||||||
["/workspace/root", "/workspace/root/../escape.txt", false],
|
["/workspace/root", "/workspace/root/../escape.txt", false],
|
||||||
|
["/workspace/root", "/workspace/rootless/file.txt", false],
|
||||||
|
["/workspace/root", "/workspace/root/a/b/c/d/e/file.txt", true],
|
||||||
|
["/workspace/root", "/workspace/root/a/..", true],
|
||||||
|
["/workspace/root", "/workspace/root/a/../..", false],
|
||||||
|
["/workspace/root", "/workspace/root/a/b/../../../escape", false],
|
||||||
|
["/", "/anything/at/all", true],
|
||||||
|
["/", "/", true],
|
||||||
|
["foo", "foo/bar", true],
|
||||||
|
["foo", "../escape", false],
|
||||||
])("checks posix containment %s -> %s", (basePath, targetPath, expected) => {
|
])("checks posix containment %s -> %s", (basePath, targetPath, expected) => {
|
||||||
expect(isPathInside(basePath, targetPath)).toBe(expected);
|
expect(isPathInside(basePath, targetPath)).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
|||||||
const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
|
const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
|
||||||
const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
|
const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
|
||||||
const PARENT_SEGMENT_PREFIX = /^\.\.(?:[\\/]|$)/u;
|
const PARENT_SEGMENT_PREFIX = /^\.\.(?:[\\/]|$)/u;
|
||||||
|
const POSIX_SEPARATOR_CHAR_CODE = 0x2f;
|
||||||
|
|
||||||
export function normalizeWindowsPathForComparison(input: string): string {
|
export function normalizeWindowsPathForComparison(input: string): string {
|
||||||
let normalized = path.win32.normalize(input);
|
let normalized = path.win32.normalize(input);
|
||||||
@@ -44,6 +45,18 @@ export function isPathInside(root: string, target: string): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
root.length > 0 &&
|
||||||
|
root.charCodeAt(0) === POSIX_SEPARATOR_CHAR_CODE &&
|
||||||
|
target.length >= root.length &&
|
||||||
|
target.charCodeAt(0) === POSIX_SEPARATOR_CHAR_CODE &&
|
||||||
|
!target.includes("/..") &&
|
||||||
|
(target === root ||
|
||||||
|
(target.startsWith(root) && target.charCodeAt(root.length) === POSIX_SEPARATOR_CHAR_CODE))
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const resolvedRoot = path.resolve(root);
|
const resolvedRoot = path.resolve(root);
|
||||||
const resolvedTarget = path.resolve(target);
|
const resolvedTarget = path.resolve(target);
|
||||||
const relative = path.relative(resolvedRoot, resolvedTarget);
|
const relative = path.relative(resolvedRoot, resolvedTarget);
|
||||||
|
|||||||
Reference in New Issue
Block a user