mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
[INFER] Don't collect type objects with unknown properties for mutable __proto__, bug 639126.
This commit is contained in:
parent
eef5f2fae3
commit
37ffca03a9
4
js/src/jit-test/tests/basic/bug639126.js
Normal file
4
js/src/jit-test/tests/basic/bug639126.js
Normal file
@ -0,0 +1,4 @@
|
||||
Array.__proto__ = Array.__proto__;
|
||||
gc();
|
||||
Array["name" + ""];
|
||||
Array();
|
@ -935,7 +935,7 @@ TypeConstraintCall::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
TypeFunction *function = NULL;
|
||||
if (TypeIsObject(type)) {
|
||||
TypeObject *object = (TypeObject*) type;
|
||||
if (object->isFunction) {
|
||||
if (object->isFunction && !object->unknownProperties) {
|
||||
function = (TypeFunction*) object;
|
||||
} else {
|
||||
/* Unknown return value for calls on non-function objects. */
|
||||
@ -1302,6 +1302,14 @@ TypeSet::getKnownTypeTag(JSContext *cx, JSScript *script)
|
||||
static inline ObjectKind
|
||||
CombineObjectKind(TypeObject *object, ObjectKind kind)
|
||||
{
|
||||
/*
|
||||
* All type objects with unknown properties are considered interchangeable
|
||||
* with one another, as they can be freely exchanged in type sets to handle
|
||||
* objects whose __proto__ has been changed.
|
||||
*/
|
||||
if (object->unknownProperties)
|
||||
return OBJECT_UNKNOWN;
|
||||
|
||||
ObjectKind nkind;
|
||||
if (object->isFunction)
|
||||
nkind = object->asFunction()->script ? OBJECT_SCRIPTED_FUNCTION : OBJECT_NATIVE_FUNCTION;
|
||||
@ -3796,8 +3804,22 @@ CondenseSweepTypeSet(JSContext *cx, TypeCompartment *compartment,
|
||||
for (unsigned i = 0; i < objectCapacity; i++) {
|
||||
TypeObject *object = types->objectSet[i];
|
||||
if (object && !object->marked) {
|
||||
/*
|
||||
* If the object has unknown properties, instead of removing it
|
||||
* replace it with the compartment's empty type object. This is
|
||||
* needed to handle mutable __proto__ --- the type object in
|
||||
* the set may no longer be used but there could be a JSObject
|
||||
* which originally had the type and was changed to a different
|
||||
* type object with unknown properties.
|
||||
*/
|
||||
if (object->unknownProperties) {
|
||||
types->objectSet[i] = cx->getTypeEmpty();
|
||||
if (!types->objectSet[i])
|
||||
compartment->setPendingNukeTypes(cx);
|
||||
} else {
|
||||
types->objectSet[i] = NULL;
|
||||
}
|
||||
removed = true;
|
||||
types->objectSet[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
@ -3819,8 +3841,14 @@ CondenseSweepTypeSet(JSContext *cx, TypeCompartment *compartment,
|
||||
} else if (types->objectCount == 1) {
|
||||
TypeObject *object = (TypeObject*) types->objectSet;
|
||||
if (!object->marked) {
|
||||
types->objectSet = NULL;
|
||||
types->objectCount = 0;
|
||||
if (object->unknownProperties) {
|
||||
types->objectSet = (TypeObject**) cx->getTypeEmpty();
|
||||
if (!types->objectSet)
|
||||
compartment->setPendingNukeTypes(cx);
|
||||
} else {
|
||||
types->objectSet = NULL;
|
||||
types->objectCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,7 +383,13 @@ struct TypeObject
|
||||
*/
|
||||
TypeObject *next;
|
||||
|
||||
/* Whether all the properties of this object are unknown. */
|
||||
/*
|
||||
* Whether all the properties of this object are unknown. When this object
|
||||
* appears in a type set, nothing can be assumed about its contents, including
|
||||
* whether the .proto field is correct. This is needed to handle mutable
|
||||
* __proto__, which requires us to unify all type objects with unknown
|
||||
* properties in type sets (see SetProto).
|
||||
*/
|
||||
bool unknownProperties;
|
||||
|
||||
/* Whether all objects this represents are dense arrays. */
|
||||
|
@ -316,8 +316,11 @@ JSContext::addTypePropertyId(js::types::TypeObject *obj, jsid id, const js::Valu
|
||||
inline js::types::TypeObject *
|
||||
JSContext::getTypeEmpty()
|
||||
{
|
||||
if (!compartment->types.typeEmpty)
|
||||
if (!compartment->types.typeEmpty) {
|
||||
compartment->types.typeEmpty = newTypeObject("Empty", NULL);
|
||||
if (compartment->types.typeEmpty)
|
||||
compartment->types.typeEmpty->unknownProperties = true;
|
||||
}
|
||||
return compartment->types.typeEmpty;
|
||||
}
|
||||
|
||||
|
@ -4288,6 +4288,9 @@ SetProto(JSContext *cx, JSObject *obj, JSObject *proto, bool checkForCycles)
|
||||
/*
|
||||
* Setting __proto__ on an object that has escaped and may be referenced by
|
||||
* other heap objects can only be done if the properties of both objects are unknown.
|
||||
* Type sets containing this object will contain the original type but not the
|
||||
* new type of the object, which is OK since we treat objects in type sets with
|
||||
* unknown properties as interchangeable.
|
||||
*/
|
||||
if (!cx->markTypeObjectUnknownProperties(obj->getType()) ||
|
||||
!cx->markTypeObjectUnknownProperties(type)) {
|
||||
|
Loading…
Reference in New Issue
Block a user