Ignore:
Timestamp:
Jun 16, 2022, 1:11:51 PM (3 years ago)
Author:
Alexey Shvayka
Message:

CommonSlowPaths::putDirectWithReify() is incorrect for DontDelete properties
https://bugs.webkit.org/show_bug.cgi?id=241651
<rdar://94016559>

Reviewed by Saam Barati.

Provided the base object has no read-only / accessor / custom properties,
putDirectWithReify() is incorrect for an object with non-configurable property,
whether it's on the structure or a non-reified static none.

In that case, putDirectWithReify() ignores existing non-configurable / non-reified
descriptor and produces an incorrect property descriptor instead of throwing TypeError.
One it's observed in the wild is via an instance field [1].

The issue was due to incorrect ReadOnly-focused check for putDirect() fast path,
which would be correct for Set but not for DefineOwnProperty.

Apart from introducing tighter fast patch check, this change extracts
JSFunction::mayHaveNonReifiedPrototype() helper, cleaning up JSFunction's overrides,
and removes now unused PutModeDefineOwnPropertyIgnoringExtensibility, which apart from
ignoring extensibility, also ignored read-only / accessor / custom properties,
which felt a bit counter-intuitive.

This change carefully preserves the fast path introduced in webkit.org/b/232479.

[1]: https://tc39.es/ecma262/#sec-definefield

  • Source/JavaScriptCore/runtime/CommonSlowPaths.h:

(JSC::CommonSlowPaths::originalStructureBeforePut):
(JSC::CommonSlowPaths::canPutDirectFast):
(JSC::CommonSlowPaths::putDirectWithReify):
(JSC::CommonSlowPaths::putDirectAccessorWithReify):

  • Source/JavaScriptCore/runtime/JSFunction.cpp:

(JSC::JSFunction::getOwnPropertySlot):
(JSC::JSFunction::put):
(JSC::JSFunction::deleteProperty):
(JSC::JSFunction::defineOwnProperty):
(JSC::JSFunction::reifyLazyPropertyIfNeeded):
(JSC::JSFunction::reifyLazyPrototypeIfNeeded):

  • Source/JavaScriptCore/runtime/JSFunction.h:
  • Source/JavaScriptCore/runtime/JSFunctionInlines.h:

(JSC::JSFunction::mayHaveNonReifiedPrototype):

  • Source/JavaScriptCore/runtime/JSObject.cpp:

(JSC::JSObject::putDirectCustomAccessor):
(JSC::JSObject::putDirectNonIndexAccessor):

  • Source/JavaScriptCore/runtime/JSObject.h:

(JSC::JSObject::putDirect):
(JSC::JSObject::putDirectRespectingExtensibility): Deleted.

  • Source/JavaScriptCore/runtime/JSObjectInlines.h:

(JSC::JSObject::putDirectInternal):

  • Source/JavaScriptCore/tools/JSDollarVM.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSDollarVM::finishCreation):

Canonical link: https://commits.webkit.org/251613@main

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp

    r295270 r295608  
    888888};
    889889
     890static JSC_DECLARE_HOST_FUNCTION(staticDontDeleteDontEnumMethod);
     891
     892class StaticDontDeleteDontEnum : public JSNonFinalObject {
     893public:
     894    using Base = JSNonFinalObject;
     895    static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
     896
     897    StaticDontDeleteDontEnum(VM& vm, Structure* structure)
     898        : Base(vm, structure)
     899    {
     900        DollarVMAssertScope assertScope;
     901    }
     902
     903    DECLARE_INFO;
     904
     905    template<typename CellType, SubspaceAccess>
     906    static CompleteSubspace* subspaceFor(VM& vm)
     907    {
     908        return &vm.cellSpace();
     909    }
     910
     911    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     912    {
     913        DollarVMAssertScope assertScope;
     914        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     915    }
     916
     917    static StaticDontDeleteDontEnum* create(VM& vm, Structure* structure)
     918    {
     919        DollarVMAssertScope assertScope;
     920        StaticDontDeleteDontEnum* result = new (NotNull, allocateCell<StaticDontDeleteDontEnum>(vm)) StaticDontDeleteDontEnum(vm, structure);
     921        result->finishCreation(vm);
     922        return result;
     923    }
     924};
     925
     926JSC_DEFINE_HOST_FUNCTION(staticDontDeleteDontEnumMethod, (JSGlobalObject*, CallFrame*))
     927{
     928    DollarVMAssertScope assertScope;
     929    return encodedJSUndefined();
     930}
     931
     932static const struct CompactHashIndex staticDontDeleteDontEnumTableIndex[8] = {
     933    { 0, -1 },
     934    { 1, -1 },
     935    { -1, -1 },
     936    { -1, -1 },
     937    { -1, -1 },
     938    { 2, -1 },
     939    { -1, -1 },
     940    { -1, -1 },
     941};
     942
     943static const struct HashTableValue staticDontDeleteDontEnumTableValues[3] = {
     944   { "dontEnum"_s, static_cast<unsigned>(PropertyAttribute::Function|PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t)static_cast<RawNativeFunction>(staticDontDeleteDontEnumMethod), (intptr_t)(0) } },
     945   { "dontDelete"_s, static_cast<unsigned>(PropertyAttribute::Function|PropertyAttribute::DontDelete), NoIntrinsic, { (intptr_t)static_cast<RawNativeFunction>(staticDontDeleteDontEnumMethod), (intptr_t)(0) } },
     946   { "dontDeleteDontEnum"_s, static_cast<unsigned>(PropertyAttribute::Function|PropertyAttribute::DontDelete|PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t)static_cast<RawNativeFunction>(staticDontDeleteDontEnumMethod), (intptr_t)(0) } },
     947};
     948
     949static const struct HashTable staticDontDeleteDontEnumTable =
     950    { 3, 7, false, nullptr, staticDontDeleteDontEnumTableValues, staticDontDeleteDontEnumTableIndex };
     951
    890952class ObjectDoingSideEffectPutWithoutCorrectSlotStatus : public JSNonFinalObject {
    891953    using Base = JSNonFinalObject;
     
    18041866const ClassInfo StaticCustomAccessor::s_info = { "StaticCustomAccessor"_s, &Base::s_info, &staticCustomAccessorTable, nullptr, CREATE_METHOD_TABLE(StaticCustomAccessor) };
    18051867const ClassInfo StaticCustomValue::s_info = { "StaticCustomValue"_s, &Base::s_info, &staticCustomValueTable, nullptr, CREATE_METHOD_TABLE(StaticCustomValue) };
     1868const ClassInfo StaticDontDeleteDontEnum::s_info = { "StaticDontDeleteDontEnum"_s, &Base::s_info, &staticDontDeleteDontEnumTable, nullptr, CREATE_METHOD_TABLE(StaticDontDeleteDontEnum) };
    18061869const ClassInfo ObjectDoingSideEffectPutWithoutCorrectSlotStatus::s_info = { "ObjectDoingSideEffectPutWithoutCorrectSlotStatus"_s, &Base::s_info, &staticCustomAccessorTable, nullptr, CREATE_METHOD_TABLE(ObjectDoingSideEffectPutWithoutCorrectSlotStatus) };
    18071870
     
    20802143static JSC_DECLARE_HOST_FUNCTION(functionCreateStaticCustomAccessor);
    20812144static JSC_DECLARE_HOST_FUNCTION(functionCreateStaticCustomValue);
     2145static JSC_DECLARE_HOST_FUNCTION(functionCreateStaticDontDeleteDontEnum);
    20822146static JSC_DECLARE_HOST_FUNCTION(functionCreateObjectDoingSideEffectPutWithoutCorrectSlotStatus);
    20832147static JSC_DECLARE_HOST_FUNCTION(functionCreateEmptyFunctionWithName);
     
    30823146}
    30833147
     3148JSC_DEFINE_HOST_FUNCTION(functionCreateStaticDontDeleteDontEnum, (JSGlobalObject* globalObject, CallFrame*))
     3149{
     3150    DollarVMAssertScope assertScope;
     3151    VM& vm = globalObject->vm();
     3152    JSLockHolder lock(vm);
     3153    Structure* structure = StaticDontDeleteDontEnum::createStructure(vm, globalObject, jsNull());
     3154    auto* result = StaticDontDeleteDontEnum::create(vm, structure);
     3155    return JSValue::encode(result);
     3156}
     3157
    30843158JSC_DEFINE_HOST_FUNCTION(functionCreateObjectDoingSideEffectPutWithoutCorrectSlotStatus, (JSGlobalObject* globalObject, CallFrame* callFrame))
    30853159{
     
    39284002    addFunction(vm, "createStaticCustomAccessor"_s, functionCreateStaticCustomAccessor, 0);
    39294003    addFunction(vm, "createStaticCustomValue"_s, functionCreateStaticCustomValue, 0);
     4004    addFunction(vm, "createStaticDontDeleteDontEnum"_s, functionCreateStaticDontDeleteDontEnum, 0);
    39304005    addFunction(vm, "createObjectDoingSideEffectPutWithoutCorrectSlotStatus"_s, functionCreateObjectDoingSideEffectPutWithoutCorrectSlotStatus, 0);
    39314006    addFunction(vm, "createEmptyFunctionWithName"_s, functionCreateEmptyFunctionWithName, 1);
Note: See TracChangeset for help on using the changeset viewer.