修复WeakRef的适配问题;兼容2.4的eruda;兼容worker在序列化封送对象的问题;去除禁止二次传播的检查(修复联机卡死问题)

This commit is contained in:
IceCola 2024-05-31 02:03:02 +08:00
parent 50083b3a07
commit 848c69386e
3 changed files with 105 additions and 20 deletions

View File

@ -1551,12 +1551,7 @@ export class Get {
if (func._filter_args) { if (func._filter_args) {
return "_noname_func:" + JSON.stringify(get.stringifiedResult(func._filter_args, 3)); return "_noname_func:" + JSON.stringify(get.stringifiedResult(func._filter_args, 3));
} }
const { Marshal, Sandbox } = security.importSandbox(); const { Marshal } = security.importSandbox();
const domain = Marshal.getMarshalledDomain(func);
if (domain) {
const sandbox = Sandbox.from(domain);
if (sandbox && "client" in sandbox) throw new Error("不应该二次扩散远程代码");
}
const str = Marshal.decompileFunction(func); const str = Marshal.decompileFunction(func);
// js内置的函数 // js内置的函数
if (/\{\s*\[native code\]\s*\}/.test(str)) return "_noname_func:function () {}"; if (/\{\s*\[native code\]\s*\}/.test(str)) return "_noname_func:function () {}";

View File

@ -41,6 +41,28 @@ const SandboxSignal_ListMonitor = Symbol("ListMonitor");
const SandboxSignal_ExposeInfo = Symbol("ExposeInfo"); const SandboxSignal_ExposeInfo = Symbol("ExposeInfo");
const SandboxSignal_TryFunctionRefs = Symbol("TryFunctionRefs"); const SandboxSignal_TryFunctionRefs = Symbol("TryFunctionRefs");
// 用于适配 < Chrome 84 的设备
const WeakRef = window.WeakRef || class WeakRef {
/**
* @param {any} target
*/
constructor(target) {
this.target = target;
}
/**
* @returns {any}
*/
deref() {
return this.target;
}
/**
* @type {"WeakRef"}
*/
[Symbol.toStringTag] = "WeakRef";
};
/** /**
* ```plain * ```plain
* 判断是否为基元类型 * 判断是否为基元类型
@ -914,19 +936,18 @@ class NativeWrapper {
const prototype = NativeWrapper.#currentFunction.prototype; const prototype = NativeWrapper.#currentFunction.prototype;
// 根据是否装箱进行不同的封装 // 根据是否装箱进行不同的封装
const wrapped = (flags & 2) const wrapped = (flags & 2)
? function (...args) { ? function (/** @type {any[]} */ ...args) {
const list = args.map(a => const list = args.map(a =>
NativeWrapper.boxCallback(a, prototype)); NativeWrapper.boxCallback(a, prototype));
// @ts-ignore // @ts-ignore
return ContextInvoker1(func, this, list); return ContextInvoker1(func, this, list);
} }
: function (...args) { : function (/** @type {any[]} */ ...args) {
// @ts-ignore // @ts-ignore
return ContextInvoker1(func, this, args); return ContextInvoker1(func, this, args);
}; };
// 构造原型链 // 构造原型链
sealObjectTree(wrapped);
Reflect.setPrototypeOf(wrapped, prototype); Reflect.setPrototypeOf(wrapped, prototype);
return wrapped; return wrapped;
} }
@ -945,17 +966,16 @@ class NativeWrapper {
const prototype = NativeWrapper.#currentFunction.prototype; const prototype = NativeWrapper.#currentFunction.prototype;
// 根据是否装箱进行不同的封装 // 根据是否装箱进行不同的封装
const wrapped = (flags & 2) const wrapped = (flags & 2)
? function (...args) { ? function (/** @type {any[]} */ ...args) {
const list = args.map(a => const list = args.map(a =>
NativeWrapper.boxCallback(a, prototype)); NativeWrapper.boxCallback(a, prototype));
return ContextInvoker2(func, list, new.target); return ContextInvoker2(func, list, new.target);
} }
: function (...args) { : function (/** @type {any[]} */ ...args) {
return ContextInvoker2(func, args, new.target); return ContextInvoker2(func, args, new.target);
}; };
// 构造原型链 // 构造原型链
sealObjectTree(wrapped);
Reflect.setPrototypeOf(wrapped, prototype); Reflect.setPrototypeOf(wrapped, prototype);
return wrapped; return wrapped;
} }
@ -977,7 +997,6 @@ class NativeWrapper {
}; };
// 构造原型链 // 构造原型链
sealObjectTree(wrapped);
Reflect.setPrototypeOf(wrapped, prototype); Reflect.setPrototypeOf(wrapped, prototype);
return wrapped; return wrapped;
} }
@ -993,14 +1012,13 @@ class NativeWrapper {
static wrapSetter(func) { static wrapSetter(func) {
// @ts-ignore // @ts-ignore
const prototype = NativeWrapper.#currentFunction.prototype; const prototype = NativeWrapper.#currentFunction.prototype;
const wrapped = function (value) { const wrapped = function (/** @type {ProxyConstructor} */ value) {
// @ts-ignore // @ts-ignore
return ContextInvoker1(func, this, return ContextInvoker1(func, this,
[NativeWrapper.boxCallback(value, prototype)]); [NativeWrapper.boxCallback(value, prototype)]);
}; };
// 构造原型链 // 构造原型链
sealObjectTree(wrapped);
Reflect.setPrototypeOf(wrapped, prototype); Reflect.setPrototypeOf(wrapped, prototype);
return wrapped; return wrapped;
} }
@ -1025,7 +1043,7 @@ class NativeWrapper {
// 缓存不存在则创建 // 缓存不存在则创建
wrapped = ContextInvokerCreator({ wrapped = ContextInvokerCreator({
unboxed, // 向封装函数提供unboxed函数 unboxed, // 向封装函数提供unboxed函数
}, function (thiz, args, newTarget) { }, function (/** @type {any} */ thiz, /** @type {readonly any[]} */ args, /** @type {(new (...args: any) => any) | undefined} */ newTarget) {
return newTarget return newTarget
// @ts-ignore // @ts-ignore
? Reflect.construct(this.unboxed, args, newTarget) ? Reflect.construct(this.unboxed, args, newTarget)
@ -1034,13 +1052,12 @@ class NativeWrapper {
}); });
// 设置暴露器 // 设置暴露器
wrapped[SandboxExposer] = (signal) => { wrapped[SandboxExposer] = (/** @type {symbol} */ signal) => {
if (signal === NativeWrapper.#unboxedFunction) if (signal === NativeWrapper.#unboxedFunction)
return unboxed; return unboxed;
}; };
// 构造原型链 // 构造原型链
sealObjectTree(wrapped);
Reflect.setPrototypeOf(wrapped, prototype); Reflect.setPrototypeOf(wrapped, prototype);
NativeWrapper.#boxedMap.set(unboxed, wrapped); NativeWrapper.#boxedMap.set(unboxed, wrapped);
} }
@ -1132,6 +1149,9 @@ class DomainMonitors {
return; return;
} }
/**
* @param {{ [x: number]: Set<Monitor>; }} actionMap
*/
function addToActionMap(actionMap) { function addToActionMap(actionMap) {
for (const action of actions) { for (const action of actions) {
let monitorMap = actionMap[action]; let monitorMap = actionMap[action];
@ -1205,6 +1225,9 @@ class DomainMonitors {
return; return;
} }
/**
* @param {{ [x: number]: Set<Monitor>; }} actionMap
*/
function removeFromActionMap(actionMap) { function removeFromActionMap(actionMap) {
for (const action of actions) { for (const action of actions) {
const monitorMap = actionMap[action]; const monitorMap = actionMap[action];
@ -1465,12 +1488,19 @@ class DomainMonitors {
stopPropagation() { stopPropagation() {
result.stopPropagation = true; result.stopPropagation = true;
}, },
/**
* @param {string} name
* @param {any} value
*/
overrideParameter(name, value) { overrideParameter(name, value) {
if (!(name in indexMap)) if (!(name in indexMap))
throw new TypeError(`参数 ${name} 没有找到`); throw new TypeError(`参数 ${name} 没有找到`);
args[indexMap[name]] = value; args[indexMap[name]] = value;
}, },
/**
* @param {undefined} value
*/
setReturnValue(value) { setReturnValue(value) {
result.returnValue = value; result.returnValue = value;
}, },
@ -2923,6 +2953,7 @@ class Domain {
* 确保 Array.isArray 对代理数组放宽 * 确保 Array.isArray 对代理数组放宽
* ``` * ```
* *
* @param {Domain} domain
* @param {any} array * @param {any} array
* @returns {boolean} * @returns {boolean}
*/ */
@ -3212,14 +3243,28 @@ class Sandbox {
} }
const handler = { const handler = {
/**
* @param {FunctionConstructor} target
* @param {any} thisArg
* @param {any[]} argArray
*/
apply(target, thisArg, argArray) { apply(target, thisArg, argArray) {
return functionCtor(target, argArray); return functionCtor(target, argArray);
}, },
/**
* @param {FunctionConstructor} target
* @param {any[]} argArray
* @param {any} newTarget
*/
construct(target, argArray, newTarget) { construct(target, argArray, newTarget) {
return functionCtor(target, argArray); return functionCtor(target, argArray);
}, },
}; };
/**
* @param {object} prototype
* @param {any} newCtor
*/
function rewriteCtor(prototype, newCtor) { function rewriteCtor(prototype, newCtor) {
const descriptor = Object.getOwnPropertyDescriptor(prototype, 'constructor') const descriptor = Object.getOwnPropertyDescriptor(prototype, 'constructor')
|| { configurable: true, writable: true, enumerable: false }; || { configurable: true, writable: true, enumerable: false };
@ -3759,7 +3804,7 @@ class Sandbox {
Object.defineProperties(rawScope, descriptors); Object.defineProperties(rawScope, descriptors);
} }
static #makeName = function (prefix, conflict) { static #makeName = function (/** @type {string} */ prefix, /** @type {any} */ conflict) {
let builtName; let builtName;
do { do {
@ -3782,6 +3827,9 @@ class Sandbox {
} }
} }
/**
* @param {any} clazz
*/
function sealClass(clazz) { function sealClass(clazz) {
sealObjectTree(clazz); sealObjectTree(clazz);
@ -3792,9 +3840,12 @@ function sealClass(clazz) {
} }
// FREEZE FROM SOUL! // FREEZE FROM SOUL!
/**
* @param {any} obj
*/
function sealObjectTree(obj) { function sealObjectTree(obj) {
// @ts-ignore // @ts-ignore
sealObject(obj, o => { sealObject(obj, (/** @type {object} */ o) => {
if (!Reflect.isExtensible(o)) // 防止1103 if (!Reflect.isExtensible(o)) // 防止1103
return; return;
if (o === obj) if (o === obj)
@ -3804,6 +3855,9 @@ function sealObjectTree(obj) {
}); });
} }
/**
* @param {any} obj
*/
function sealObject(obj, freeze = Object.freeze) { function sealObject(obj, freeze = Object.freeze) {
if (isPrimitive(obj)) if (isPrimitive(obj))
return; return;

View File

@ -415,6 +415,7 @@ async function initSecurity({
return; return;
loadPolyfills(); loadPolyfills();
initSerializeNeeded();
initIsolatedEnvironment(); initIsolatedEnvironment();
// 不允许被远程代码访问的game函数 // 不允许被远程代码访问的game函数
@ -810,6 +811,41 @@ function initIsolatedEnvironment() {
rewriteCtor(defaultAsyncGeneratorFunction.prototype, ModAsyncGeneratorFunction); rewriteCtor(defaultAsyncGeneratorFunction.prototype, ModAsyncGeneratorFunction);
} }
/**
* ```plain
* 初始化需要额外序列化的函数
*
* 适配扩展当在skillcontent里面调用皮切的playEffect时会报错
* ```
*/
function initSerializeNeeded() {
const structuredClone = window.structuredClone;
const deepClone = (/** @type {any} */ obj) => {
try {
return structuredClone(obj);
} catch (e) {
return obj;
}
};
/** @type {Array<[string, number[]]>} */
const funcList = [
["Worker.prototype.postMessage", [0]],
];
for (const [funcCode, argIndexes] of funcList) {
const originalFunc = new Function(`return ${funcCode}`)();
const newFunc = /** @this {any} */ function (/** @type {any[]} */ ...args) {
for (const index of argIndexes)
args[index] = deepClone(args[index]);
return originalFunc.apply(this, args);
};
new Function("_", `${funcCode} = _;`)(newFunc);
}
}
/** /**
* ```plain * ```plain
* 加载当前的垫片函数 * 加载当前的垫片函数