mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-14 02:15:36 +00:00
Merge pull request #1434 from kaitranntt/codex/fix-unbounded-recursion-in-receipt-generation
fix(persist): bound Codex translator receipt scan
This commit is contained in:
3 files changed
+104
-15
No files matched your search
@@ -1,5 +1,8 @@
|
||||
export const CODEX_TRANSLATOR_URL_MARKER = '/api/provider/codex';
|
||||
|
||||
const MAX_CODEX_TRANSLATOR_SCAN_DEPTH = 100;
|
||||
const MAX_CODEX_TRANSLATOR_SCAN_NODES = 10000;
|
||||
|
||||
function formatSettingsPathSegment(basePath: string, segment: string | number): string {
|
||||
if (typeof segment === 'number') {
|
||||
return `${basePath}[${segment}]`;
|
||||
@@ -13,23 +16,62 @@ function formatSettingsPathSegment(basePath: string, segment: string | number):
|
||||
}
|
||||
|
||||
export function findCodexTranslatorUrlPaths(value: unknown, path = ''): string[] {
|
||||
if (typeof value === 'string') {
|
||||
return value.includes(CODEX_TRANSLATOR_URL_MARKER) ? [path || '(root)'] : [];
|
||||
const matches: string[] = [];
|
||||
const stack: Array<{ value: unknown; path: string; depth: number }> = [{ value, path, depth: 0 }];
|
||||
const seen = new WeakSet<object>();
|
||||
let visitedNodes = 0;
|
||||
|
||||
while (stack.length > 0 && visitedNodes < MAX_CODEX_TRANSLATOR_SCAN_NODES) {
|
||||
const item = stack.pop();
|
||||
if (!item) {
|
||||
break;
|
||||
}
|
||||
|
||||
visitedNodes += 1;
|
||||
|
||||
if (typeof item.value === 'string') {
|
||||
if (item.value.includes(CODEX_TRANSLATOR_URL_MARKER)) {
|
||||
matches.push(item.path || '(root)');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof item.value !== 'object' || item.value === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seen.has(item.value)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(item.value);
|
||||
|
||||
if (item.depth >= MAX_CODEX_TRANSLATOR_SCAN_DEPTH) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(item.value)) {
|
||||
for (let index = item.value.length - 1; index >= 0; index -= 1) {
|
||||
stack.push({
|
||||
value: item.value[index],
|
||||
path: formatSettingsPathSegment(item.path, index),
|
||||
depth: item.depth + 1,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const entries = Object.entries(item.value);
|
||||
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
||||
const [key, child] = entries[index];
|
||||
stack.push({
|
||||
value: child,
|
||||
path: formatSettingsPathSegment(item.path, key),
|
||||
depth: item.depth + 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.flatMap((item, index) =>
|
||||
findCodexTranslatorUrlPaths(item, formatSettingsPathSegment(path, index))
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
return Object.entries(value).flatMap(([key, item]) =>
|
||||
findCodexTranslatorUrlPaths(item, formatSettingsPathSegment(path, key))
|
||||
);
|
||||
}
|
||||
|
||||
return [];
|
||||
return matches;
|
||||
}
|
||||
|
||||
export function formatSettingsPathList(paths: string[]): string {
|
||||
|
||||
Reference in new issue
Block a user