[constant-tracking] Fix RegExp.p.exec tampering check.
Bug: v8:5495, v8:8361 Change-Id: I8bf37c75113cff212d9899c39cffbca47c448924 Reviewed-on: https://chromium-review.googlesource.com/c/1297310 Commit-Queue: Jaroslav Sevcik <jarin@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#56927}
This commit is contained in:
parent
68bd0a6b5d
commit
f289f1cafb
@ -2534,6 +2534,10 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
Handle<JSFunction> fun = SimpleInstallFunction(
|
||||
isolate_, prototype, factory->exec_string(),
|
||||
Builtins::kRegExpPrototypeExec, 1, true, DONT_ENUM);
|
||||
// Check that index of "exec" function in JSRegExp is correct.
|
||||
DCHECK_EQ(JSRegExp::kExecFunctionDescriptorIndex,
|
||||
prototype->map()->LastAdded());
|
||||
|
||||
native_context()->set_regexp_exec_function(*fun);
|
||||
}
|
||||
|
||||
|
@ -916,9 +916,6 @@ void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context,
|
||||
|
||||
GotoIfForceSlowPath(if_ismodified);
|
||||
|
||||
// TODO(ishell): Update this check once map changes for constant field
|
||||
// tracking are landing.
|
||||
|
||||
Node* const native_context = LoadNativeContext(context);
|
||||
Node* const regexp_fun =
|
||||
LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX);
|
||||
@ -931,11 +928,42 @@ void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context,
|
||||
Node* const initial_proto_initial_map =
|
||||
LoadContextElement(native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX);
|
||||
Node* const proto_map = LoadMap(LoadMapPrototype(map));
|
||||
|
||||
Node* const proto_has_initialmap =
|
||||
WordEqual(proto_map, initial_proto_initial_map);
|
||||
|
||||
GotoIfNot(proto_has_initialmap, if_ismodified);
|
||||
|
||||
if (FLAG_track_constant_fields) {
|
||||
// With constant field tracking, we need to make sure that the exec
|
||||
// function in the prototype has not been tampered with. We do this by
|
||||
// checking that the slot in the prototype's descriptor array is still
|
||||
// marked as const.
|
||||
TNode<DescriptorArray> descriptors = LoadMapDescriptors(proto_map);
|
||||
|
||||
const int index = JSRegExp::kExecFunctionDescriptorIndex;
|
||||
// Assert the index is in-bounds.
|
||||
CSA_ASSERT(this, SmiLessThan(SmiConstant(index),
|
||||
LoadWeakFixedArrayLength(descriptors)));
|
||||
// Assert that the name is correct. This essentially checks that
|
||||
// the index corresponds to the insertion order in the bootstrapper.
|
||||
CSA_ASSERT(this,
|
||||
WordEqual(LoadWeakFixedArrayElement(
|
||||
descriptors, DescriptorArray::ToKeyIndex(index)),
|
||||
LoadRoot(RootIndex::kexec_string)));
|
||||
|
||||
TNode<Uint32T> details =
|
||||
DescriptorArrayGetDetails(descriptors, Uint32Constant(index));
|
||||
|
||||
TNode<Uint32T> constness =
|
||||
DecodeWord32<PropertyDetails::ConstnessField>(details);
|
||||
|
||||
GotoIfNot(
|
||||
Word32Equal(constness,
|
||||
Int32Constant(static_cast<int>(PropertyConstness::kConst))),
|
||||
if_ismodified);
|
||||
}
|
||||
|
||||
// The smi check is required to omit ToLength(lastIndex) calls with possible
|
||||
// user-code execution on the fast path.
|
||||
Node* const last_index = FastLoadLastIndex(CAST(object));
|
||||
|
@ -131,6 +131,9 @@ class JSRegExp : public JSObject {
|
||||
static const int kLastIndexFieldIndex = 0;
|
||||
static const int kInObjectFieldCount = 1;
|
||||
|
||||
// Descriptor array index to the exec method in the prototype.
|
||||
static const int kExecFunctionDescriptorIndex = 1;
|
||||
|
||||
// The uninitialized value for a regexp code object.
|
||||
static const int kUninitializedValue = -1;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user