Files
Claude-Code-Workflow/test-infinite-loop.mjs
catlog22 964292ebdb feat: Add comprehensive tests for contentPattern and glob pattern matching
- Implemented final verification tests for contentPattern to validate behavior with empty strings, dangerous patterns, and normal patterns.
- Created glob pattern matching tests to verify regex conversion and matching functionality.
- Developed infinite loop risk tests using Worker threads to isolate potential blocking operations.
- Introduced optimized contentPattern tests to validate improvements in the findMatches function.
- Added verification tests to assess the effectiveness of contentPattern optimizations.
- Conducted safety tests for contentPattern to identify edge cases and potential vulnerabilities.
- Implemented unrestricted loop tests to analyze infinite loop risks without match limits.
- Developed tests for zero-width pattern detection logic to ensure proper handling of dangerous regex patterns.
2026-02-09 11:13:01 +08:00

174 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* contentPattern 无限循环风险测试
* 使用 Worker 隔离环境,防止主线程卡死
*/
import { Worker } from 'worker_threads';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// 测试函数代码
const workerCode = `
function findMatches(content, pattern) {
try {
const regex = new RegExp(pattern, 'gm');
const matches = [];
let match;
let iterations = 0;
const MAX_ITERATIONS = 1000;
while ((match = regex.exec(content)) !== null && matches.length < 10) {
iterations++;
if (iterations > MAX_ITERATIONS) {
return { error: 'Exceeded max iterations - possible infinite loop', iterations };
}
const lineStart = content.lastIndexOf('\\n', match.index) + 1;
const lineEnd = content.indexOf('\\n', match.index);
const line = content.substring(lineStart, lineEnd === -1 ? undefined : lineEnd).trim();
matches.push(line.substring(0, 200));
}
return { matches, iterations };
} catch (error) {
return { error: error.message };
}
};
self.on('message', ({ content, pattern }) => {
const result = findMatches(content, pattern);
self.postMessage(result);
});
`;
async function testInfiniteLoop(content, pattern, testName, timeout = 2000) {
console.log(`\n测试: ${testName}`);
console.log(`模式: "${pattern}"`);
// 创建临时 worker
const blob = new Blob([workerCode], { type: 'application/javascript' });
const workerUrl = URL.createObjectURL(blob);
try {
const worker = new Worker(workerUrl);
const result = await new Promise((resolve) => {
const timer = setTimeout(() => {
worker.terminate();
resolve({ error: 'TIMEOUT - Infinite loop detected!', timeout: true });
}, timeout);
worker.once('message', (data) => {
clearTimeout(timer);
worker.terminate();
resolve(data);
});
worker.once('error', (error) => {
clearTimeout(timer);
worker.terminate();
resolve({ error: error.message });
});
worker.postMessage({ content, pattern });
});
URL.revokeObjectURL(workerUrl);
if (result.error) {
if (result.timeout) {
console.log(`❌ 超时 - 检测到无限循环!`);
return { hasInfiniteLoop: true };
} else {
console.log(`⚠️ 错误: ${result.error}`);
return { hasInfiniteLoop: false, error: result.error };
}
} else {
console.log(`✅ 结果: ${result.matches?.length || 0} 个匹配, ${result.iterations} 次迭代`);
return { hasInfiniteLoop: false, iterations: result.iterations };
}
} catch (error) {
console.log(`❌ 异常: ${error.message}`);
return { hasInfiniteLoop: false, error: error.message };
}
}
async function main() {
console.log('=== contentPattern 无限循环风险测试 ===\n');
console.log('⚠️ 危险测试将在 Worker 中运行2秒超时\n');
const tests = [
{
name: '正常模式',
content: 'Line 1\nLine 2\nLine 3',
pattern: 'Line',
expected: '正常'
},
{
name: '空字符串模式(危险)',
content: 'Line 1\nLine 2\nLine 3',
pattern: '',
expected: '无限循环'
},
{
name: '零宽匹配(危险)',
content: 'abc\ndef\nghi',
pattern: 'x*', // 匹配 0 个或多个 x
expected: '无限循环'
},
{
name: '或运算符空匹配(危险)',
content: 'some text',
pattern: 'a|', // 匹配 'a' 或空
expected: '无限循环'
},
{
name: 'ReDoS 攻击(危险)',
content: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab',
pattern: '(a+)+b',
expected: '超时'
},
{
name: '正常匹配',
content: 'TODO fix this\nTODO fix that',
pattern: 'TODO',
expected: '正常'
}
];
const results = [];
for (const test of tests) {
const result = await testInfiniteLoop(test.content, test.pattern, test.name, 2000);
results.push({ ...test, result });
}
console.log(`\n${'='.repeat(60)}`);
console.log('\n测试结果汇总:\n');
const infiniteLoopCount = results.filter(r => r.result.hasInfiniteLoop).length;
const timeoutCount = results.filter(r => r.result.error?.includes('TIMEOUT')).length;
results.forEach((r, i) => {
const status = r.result.hasInfiniteLoop ? '❌ 无限循环' :
r.result.error?.includes('TIMEOUT') ? '⏱️ 超时' :
r.result.error ? '⚠️ 错误' : '✅ 正常';
console.log(`${i + 1}. ${r.name.padEnd(30)} ${status}`);
if (r.result.iterations) {
console.log(` 迭代次数: ${r.result.iterations}`);
}
});
console.log(`\n总结:`);
console.log(`- 无限循环风险: ${infiniteLoopCount}`);
console.log(`- 超时风险: ${timeoutCount}`);
console.log(`- 正常工作: ${results.length - infiniteLoopCount - timeoutCount}`);
if (infiniteLoopCount > 0 || timeoutCount > 0) {
console.log(`\n⚠️ contentPattern 存在严重的无限循环和 ReDoS 风险!`);
}
}
main().catch(console.error);