Changeset 242991 in webkit
- Timestamp:
- Mar 14, 2019, 10:56:24 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 13 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/symbol-is-destructed-before-refing-underlying-symbol-impl.js (added)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGOperations.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/jit/JITOperations.cpp (modified) (12 diffs)
-
Source/JavaScriptCore/runtime/JSFunction.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSModuleLoader.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSONObject.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/Symbol.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/Symbol.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/SymbolConstructor.cpp (modified) (1 diff)
-
Source/JavaScriptCore/tools/JSDollarVM.cpp (modified) (2 diffs)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/bindings/js/ScriptController.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r242989 r242991 1 2019-03-14 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Retain PrivateName of Symbol before passing it to operations potentially incurring GC 4 https://bugs.webkit.org/show_bug.cgi?id=195791 5 <rdar://problem/48806130> 6 7 Reviewed by Mark Lam. 8 9 * stress/symbol-is-destructed-before-refing-underlying-symbol-impl.js: Added. 10 (foo): 11 1 12 2019-03-14 Saam barati <sbarati@apple.com> 2 13 -
trunk/Source/JavaScriptCore/ChangeLog
r242990 r242991 1 2019-03-14 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Retain PrivateName of Symbol before passing it to operations potentially incurring GC 4 https://bugs.webkit.org/show_bug.cgi?id=195791 5 <rdar://problem/48806130> 6 7 Reviewed by Mark Lam. 8 9 Consider the following example: 10 11 void putByVal(JSObject*, PropertyName propertyName, ...); 12 13 putByVal(object, symbol->privateName(), ...); 14 15 PropertyName does not retain the passed UniquedStringImpl*. It just holds the pointer to UniquedStringImpl*. 16 It means that since `Symbol::privateName()` returns `const PrivateName&` instead of `PrivateName`, putByVal 17 and its caller does not retain UniquedStringImpl* held in PropertyName. The problem happens when the putByVal 18 incurs GC, and when the `symbol` is missing in the conservative GC scan. The underlying UniquedStringImpl* of 19 PropertyName can be accidentally destroyed in the middle of the putByVal operation. We should retain PrivateName 20 before passing it to operations which takes it as PropertyName. 21 22 1. We use the code pattern like this. 23 24 auto propertyName = symbol->privateName(); 25 someOperation(..., propertyName); 26 27 This pattern is well aligned to existing `JSValue::toPropertyKey(exec)` and `JSString::toIdentifier(exec)` code patterns. 28 29 auto propertyName = value.toPropertyKey(exec); 30 RETURN_IF_EXCEPTION(scope, { }); 31 someOperation(..., propertyName); 32 33 2. We change `Symbol::privateName()` to returning `PrivateName` instead of `const PrivateName&` to avoid 34 potential dangerous use cases. This is OK because the code using `Symbol::privateName()` is not a critical path, 35 and they typically need to retain PrivateName. 36 37 3. We audit similar functions `toPropertyKey(exec)` and `toIdentifier(exec)` for needed but missing exception checks. 38 BTW, these functions are safe to the problem fixed in this patch since they return `Identifier` instead 39 of `const Identifier&`. 40 41 Mark and Robin investigated and offered important data to understand what went wrong. And figured out the reason behind 42 the mysterious behavior shown in the data, and now, we confirm that this is the right fix for this bug. 43 44 * dfg/DFGOperations.cpp: 45 * jit/JITOperations.cpp: 46 (JSC::tryGetByValOptimize): 47 * runtime/JSFunction.cpp: 48 (JSC::JSFunction::setFunctionName): 49 * runtime/JSModuleLoader.cpp: 50 (JSC::printableModuleKey): 51 * runtime/JSONObject.cpp: 52 (JSC::Stringifier::Stringifier): 53 * runtime/Symbol.cpp: 54 (JSC::Symbol::descriptiveString const): 55 (JSC::Symbol::description const): 56 * runtime/Symbol.h: 57 * runtime/SymbolConstructor.cpp: 58 (JSC::symbolConstructorKeyFor): 59 * tools/JSDollarVM.cpp: 60 (JSC::functionGetGetterSetter): 61 1 62 2019-03-14 Yusuke Suzuki <ysuzuki@apple.com> 2 63 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r242715 r242991 771 771 NativeCallFrameTracer tracer(&vm, exec); 772 772 773 return JSValue::encode(getByValObject(exec, vm, asObject(base), asSymbol(symbol)->privateName())); 773 auto propertyName = asSymbol(symbol)->privateName(); 774 return JSValue::encode(getByValObject(exec, vm, asObject(base), propertyName)); 774 775 } 775 776 … … 827 828 NativeCallFrameTracer tracer(&vm, exec); 828 829 829 putByValCellInternal<true, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue)); 830 auto propertyName = asSymbol(symbol)->privateName(); 831 putByValCellInternal<true, false>(exec, vm, cell, propertyName, JSValue::decode(encodedValue)); 830 832 } 831 833 … … 835 837 NativeCallFrameTracer tracer(&vm, exec); 836 838 837 putByValCellInternal<false, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue)); 839 auto propertyName = asSymbol(symbol)->privateName(); 840 putByValCellInternal<false, false>(exec, vm, cell, propertyName, JSValue::decode(encodedValue)); 838 841 } 839 842 … … 987 990 NativeCallFrameTracer tracer(&vm, exec); 988 991 989 putByValCellInternal<true, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue)); 992 auto propertyName = asSymbol(symbol)->privateName(); 993 putByValCellInternal<true, true>(exec, vm, cell, propertyName, JSValue::decode(encodedValue)); 990 994 } 991 995 … … 995 999 NativeCallFrameTracer tracer(&vm, exec); 996 1000 997 putByValCellInternal<false, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue)); 1001 auto propertyName = asSymbol(symbol)->privateName(); 1002 putByValCellInternal<false, true>(exec, vm, cell, propertyName, JSValue::decode(encodedValue)); 998 1003 } 999 1004 … … 2055 2060 } 2056 2061 2057 EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName) 2058 { 2059 VM& vm = exec->vm(); 2060 NativeCallFrameTracer tracer(&vm, exec); 2062 EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* property) 2063 { 2064 VM& vm = exec->vm(); 2065 NativeCallFrameTracer tracer(&vm, exec); 2066 auto scope = DECLARE_THROW_SCOPE(vm); 2067 2061 2068 JSValue baseValue = JSValue::decode(encodedBaseValue); 2062 2069 if (baseValue.isUndefinedOrNull()) … … 2066 2073 if (!base) 2067 2074 return JSValue::encode(JSValue()); 2068 return JSValue::encode(jsBoolean(base->hasPropertyGeneric(exec, asString(propertyName)->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty))); 2075 auto propertyName = asString(property)->toIdentifier(exec); 2076 RETURN_IF_EXCEPTION(scope, { }); 2077 RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(base->hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::GetOwnProperty)))); 2069 2078 } 2070 2079 -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r242596 r242991 721 721 722 722 VM& vm = exec->vm(); 723 auto scope = DECLARE_THROW_SCOPE(vm); 723 724 724 725 if (baseValue.isObject() && isCopyOnWrite(baseValue.getObject()->indexingMode())) … … 751 752 if (baseValue.isObject() && isStringOrSymbol(subscript)) { 752 753 const Identifier propertyName = subscript.toPropertyKey(exec); 754 RETURN_IF_EXCEPTION(scope, OptimizationResult::GiveUp); 753 755 if (subscript.isSymbol() || !parseIndex(propertyName)) { 754 756 ASSERT(exec->bytecodeOffset()); … … 791 793 VM& vm = exec->vm(); 792 794 NativeCallFrameTracer tracer(&vm, exec); 795 auto scope = DECLARE_THROW_SCOPE(vm); 793 796 794 797 JSValue baseValue = JSValue::decode(encodedBaseValue); 795 798 JSValue subscript = JSValue::decode(encodedSubscript); 796 799 JSValue value = JSValue::decode(encodedValue); 797 if (tryPutByValOptimize(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)) == OptimizationResult::GiveUp) { 800 OptimizationResult result = tryPutByValOptimize(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)); 801 RETURN_IF_EXCEPTION(scope, void()); 802 if (result == OptimizationResult::GiveUp) { 798 803 // Don't ever try to optimize. 799 804 byValInfo->tookSlowPath = true; 800 805 ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), operationPutByValGeneric); 801 806 } 802 putByVal(exec, baseValue, subscript, value, byValInfo);807 RELEASE_AND_RETURN(scope, putByVal(exec, baseValue, subscript, value, byValInfo)); 803 808 } 804 809 … … 809 814 810 815 VM& vm = exec->vm(); 816 auto scope = DECLARE_THROW_SCOPE(vm); 811 817 812 818 if (subscript.isInt32()) { … … 833 839 } else if (isStringOrSymbol(subscript)) { 834 840 const Identifier propertyName = subscript.toPropertyKey(exec); 841 RETURN_IF_EXCEPTION(scope, OptimizationResult::GiveUp); 835 842 if (subscript.isSymbol() || !parseIndex(propertyName)) { 836 843 ASSERT(exec->bytecodeOffset()); … … 873 880 VM& vm = exec->vm(); 874 881 NativeCallFrameTracer tracer(&vm, exec); 882 auto scope = DECLARE_THROW_SCOPE(vm); 875 883 876 884 JSValue baseValue = JSValue::decode(encodedBaseValue); … … 879 887 RELEASE_ASSERT(baseValue.isObject()); 880 888 JSObject* object = asObject(baseValue); 881 if (tryDirectPutByValOptimize(exec, object, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)) == OptimizationResult::GiveUp) { 889 OptimizationResult result = tryDirectPutByValOptimize(exec, object, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)); 890 RETURN_IF_EXCEPTION(scope, void()); 891 if (result == OptimizationResult::GiveUp) { 882 892 // Don't ever try to optimize. 883 893 byValInfo->tookSlowPath = true; … … 885 895 } 886 896 887 directPutByVal(exec, object, subscript, value, byValInfo);897 RELEASE_AND_RETURN(scope, directPutByVal(exec, object, subscript, value, byValInfo)); 888 898 } 889 899 … … 1874 1884 1875 1885 VM& vm = exec->vm(); 1886 auto scope = DECLARE_THROW_SCOPE(vm); 1876 1887 1877 1888 if (baseValue.isObject() && subscript.isInt32()) { … … 1904 1915 if (baseValue.isObject() && isStringOrSymbol(subscript)) { 1905 1916 const Identifier propertyName = subscript.toPropertyKey(exec); 1917 RETURN_IF_EXCEPTION(scope, OptimizationResult::GiveUp); 1906 1918 if (subscript.isSymbol() || !parseIndex(propertyName)) { 1907 1919 ASSERT(exec->bytecodeOffset()); … … 1957 1969 VM& vm = exec->vm(); 1958 1970 NativeCallFrameTracer tracer(&vm, exec); 1971 auto scope = DECLARE_THROW_SCOPE(vm); 1959 1972 1960 1973 JSValue baseValue = JSValue::decode(encodedBase); 1961 1974 JSValue subscript = JSValue::decode(encodedSubscript); 1962 1975 ReturnAddressPtr returnAddress = ReturnAddressPtr(OUR_RETURN_ADDRESS); 1963 if (tryGetByValOptimize(exec, baseValue, subscript, byValInfo, returnAddress) == OptimizationResult::GiveUp) { 1976 OptimizationResult result = tryGetByValOptimize(exec, baseValue, subscript, byValInfo, returnAddress); 1977 RETURN_IF_EXCEPTION(scope, { }); 1978 if (result == OptimizationResult::GiveUp) { 1964 1979 // Don't ever try to optimize. 1965 1980 byValInfo->tookSlowPath = true; … … 1967 1982 } 1968 1983 1969 return JSValue::encode(getByVal(exec, baseValue, subscript, byValInfo, returnAddress));1984 RELEASE_AND_RETURN(scope, JSValue::encode(getByVal(exec, baseValue, subscript, byValInfo, returnAddress))); 1970 1985 } 1971 1986 -
trunk/Source/JavaScriptCore/runtime/JSFunction.cpp
r240796 r242991 670 670 String name; 671 671 if (value.isSymbol()) { 672 SymbolImpl& uid = asSymbol(value)->privateName().uid(); 672 PrivateName privateName = asSymbol(value)->privateName(); 673 SymbolImpl& uid = privateName.uid(); 673 674 if (uid.isNullSymbol()) 674 675 name = emptyString(); -
trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp
r239256 r242991 117 117 { 118 118 VM& vm = exec->vm(); 119 if (key.isString() || key.isSymbol()) 120 return key.toPropertyKey(exec).impl(); 119 auto scope = DECLARE_THROW_SCOPE(vm); 120 if (key.isString() || key.isSymbol()) { 121 auto propertyName = key.toPropertyKey(exec); 122 scope.assertNoException(); // This is OK since this function is just for debugging purpose. 123 return propertyName.impl(); 124 } 121 125 return vm.propertyNames->emptyIdentifier.impl(); 122 126 } -
trunk/Source/JavaScriptCore/runtime/JSONObject.cpp
r239544 r242991 248 248 } else if (!name.isNumber() && !name.isString()) 249 249 continue; 250 m_arrayReplacerPropertyNames.add(name.toString(exec)->toIdentifier(exec));250 JSString* propertyNameString = name.toString(exec); 251 251 RETURN_IF_EXCEPTION(scope, ); 252 auto propertyName = propertyNameString->toIdentifier(exec); 253 RETURN_IF_EXCEPTION(scope, ); 254 m_arrayReplacerPropertyNames.add(WTFMove(propertyName)); 252 255 } 253 256 } -
trunk/Source/JavaScriptCore/runtime/Symbol.cpp
r235712 r242991 101 101 String Symbol::descriptiveString() const 102 102 { 103 return makeString("Symbol(", String( privateName().uid()), ')');103 return makeString("Symbol(", String(m_privateName.uid()), ')'); 104 104 } 105 105 106 106 String Symbol::description() const 107 107 { 108 auto& uid = privateName().uid();108 auto& uid = m_privateName.uid(); 109 109 return uid.isNullSymbol() ? String() : uid; 110 110 } -
trunk/Source/JavaScriptCore/runtime/Symbol.h
r240766 r242991 50 50 JS_EXPORT_PRIVATE static Symbol* create(VM&, SymbolImpl& uid); 51 51 52 const PrivateName&privateName() const { return m_privateName; }52 PrivateName privateName() const { return m_privateName; } 53 53 String descriptiveString() const; 54 54 String description() const; -
trunk/Source/JavaScriptCore/runtime/SymbolConstructor.cpp
r242650 r242991 110 110 return JSValue::encode(throwTypeError(exec, scope, SymbolKeyForTypeError)); 111 111 112 SymbolImpl& uid = asSymbol(symbolValue)->privateName().uid(); 112 PrivateName privateName = asSymbol(symbolValue)->privateName(); 113 SymbolImpl& uid = privateName.uid(); 113 114 if (!uid.symbolRegistry()) 114 115 return JSValue::encode(jsUndefined()); -
trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp
r242397 r242991 2104 2104 static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec) 2105 2105 { 2106 VM& vm = exec->vm(); 2107 auto scope = DECLARE_THROW_SCOPE(vm); 2108 2106 2109 JSValue value = exec->argument(0); 2107 2110 if (!value.isObject()) … … 2112 2115 return JSValue::encode(jsUndefined()); 2113 2116 2117 auto propertyName = asString(property)->toIdentifier(exec); 2118 RETURN_IF_EXCEPTION(scope, { }); 2119 2114 2120 PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry); 2115 value.getPropertySlot(exec, asString(property)->toIdentifier(exec), slot);2121 value.getPropertySlot(exec, propertyName, slot); 2116 2122 2117 2123 JSValue result; -
trunk/Source/WebCore/ChangeLog
r242988 r242991 1 2019-03-14 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Retain PrivateName of Symbol before passing it to operations potentially incurring GC 4 https://bugs.webkit.org/show_bug.cgi?id=195791 5 <rdar://problem/48806130> 6 7 Reviewed by Mark Lam. 8 9 * bindings/js/ScriptController.cpp: 10 (WebCore::ScriptController::setupModuleScriptHandlers): 11 1 12 2019-03-14 Brent Fulgham <bfulgham@apple.com> 2 13 -
trunk/Source/WebCore/bindings/js/ScriptController.cpp
r240323 r242991 279 279 RefPtr<LoadableModuleScript> moduleScript(&moduleScriptRef); 280 280 281 auto& fulfillHandler = *JSNativeStdFunction::create(state.vm(), proxy.window(), 1, String(), [moduleScript](ExecState* exec) { 281 auto& fulfillHandler = *JSNativeStdFunction::create(state.vm(), proxy.window(), 1, String(), [moduleScript](ExecState* exec) -> JSC::EncodedJSValue { 282 VM& vm = exec->vm(); 283 auto scope = DECLARE_THROW_SCOPE(vm); 282 284 Identifier moduleKey = jsValueToModuleKey(exec, exec->argument(0)); 285 RETURN_IF_EXCEPTION(scope, { }); 283 286 moduleScript->notifyLoadCompleted(*moduleKey.impl()); 284 287 return JSValue::encode(jsUndefined());
Note:
See TracChangeset
for help on using the changeset viewer.