我有一个小型 Node.js 应用程序,它尝试使用 synchrony 对 Javascript 源代码数据集进行反混淆。
synchrony.deobfuscateNode(ast)
函数返回一个promise,因此我实现了一个Promise.race
,以便在反混淆花费太长时间的情况下让程序返回:
const { Deobfuscator } = require('./synchrony');
const { timeout } = require('../../../config');
const { parse } = require('../../utils/parser');
async function callDeobfuscator(ast, obfuscator) {
const withTimeout = (promise) => {
let timeoutPid;
const timeoutPromise = new Promise((resolve, reject) =>
timeoutPid = setTimeout(reject, timeout));
return Promise.race([
promise,
timeoutPromise
]).finally(() => {
if (timeoutPid) {
clearTimeout(timeoutPid);
}
});
};
const synchrony = new Deobfuscator();
return await withTimeout(synchrony.deobfuscateNode(ast));
};
const fs = require('fs');
fs.readFile('script.js', 'utf8', async function(err, source){
let ast = parse(source);
ast = await callDeobfuscator(ast);
console.log(ast);
});
但是,每当
callDeobfuscator
花费的时间超过超时承诺时,就不会抛出异常(超时承诺不会拒绝),并且程序无论如何都会等待 callDeobfuscator
解决。我尝试用另一个超时承诺替换 callDeobfuscator
逻辑 (testPromise
):
async function callDeobfuscator(ast, obfuscator) {
const withTimeout = (promise) => {
let timeoutPid;
const timeoutPromise = new Promise((resolve, reject) =>
timeoutPid = setTimeout(reject, timeout));
return Promise.race([
promise,
timeoutPromise
]).finally(() => {
if (timeoutPid) {
clearTimeout(timeoutPid);
}
});
};
const testPromise = new Promise((resolve, reject) => {
setTimeout(resolve, 1000000000, 'two');
});
return await withTimeout(testPromise);
};
现在它按预期工作了,所以我猜我无法理解的
callDeobfuscator
承诺一定有问题。有什么见解吗?
我快速浏览了synchrony的源代码并查看了
deobfuscateNode
函数。
transform
。尽管这些转换器具有 async 函数签名,但我没有找到一个真正以异步方式工作的转换器(这意味着没有使用异步 IO 方法,并且在实现中甚至没有等待任何内容)。这意味着,即使从 deobfuscateNode
返回了一个 Promise,所有代码实际上都是同步执行的,并且会让 JS 解释器保持忙碌。
这意味着,一旦您开始运行
deobfuscateNode
,您将无法以任何方式中断它。为了能够做到这一点,必须改变同步库的工作方式。