Changeset 83645 in webkit
- Timestamp:
- Apr 12, 2011 2:50:04 PM (13 years ago)
- Location:
- trunk/Source
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r83641 r83645 1 2011-04-11 Stephanie Lewis <slewis@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 https://bugs.webkit.org/show_bug.cgi?id=58280 6 <rdar://problem/9252824> javascript in an inconsistent state due to serialization returning an un-handled exception 7 Currently serialization and deserialization can throw javascript exceptions. Since SerializedScriptValue is called in 8 several places that do not always involve direct calls into javascript have the functions return an error code and the callers 9 decide whether or not to throw exceptions. 10 11 Don't allow SerializedScriptValue to attempt to serialize objects that inherit from JSNavigator.h. Walking that object creates 12 additional objects which eventually causes serialization to end up throwing a stack overflow error. Instead fail immediately. 13 14 Untangle header includes. SerializedScriptValue was inheriting ScriptValue.h, but not using it. Since ScriptValue depends on 15 SerializedScriptValue this could lead to a circular header dependency. 16 17 No change in functionality, covered by current tests 18 19 * WebCore.exp.in: 20 * bindings/js/JSMessageEventCustom.cpp: 21 (WebCore::JSMessageEvent::initMessageEvent): 22 * bindings/js/ScriptValue.cpp: 23 (WebCore::ScriptValue::serialize): 24 (WebCore::ScriptValue::deserialize): 25 * bindings/js/ScriptValue.h: 26 * bindings/js/SerializedScriptValue.cpp: 27 (WebCore::CloneSerializer::serialize): 28 (WebCore::CloneSerializer::dumpIfTerminal): 29 (WebCore::CloneDeserializer::deserialize): 30 (WebCore::SerializedScriptValue::create): 31 (WebCore::SerializedScriptValue::deserialize): 32 (WebCore::SerializedScriptValue::maybeThrowExceptionIfSerializationFailed): 33 (WebCore::SerializedScriptValue::serializationDidCompleteSuccessfully): 34 * bindings/js/SerializedScriptValue.h: 35 36 * bindings/js/JSWorkerContextBase.cpp: header include fix 37 * loader/FrameLoader.h: header include fix 38 * page/Frame.cpp: header include fix 39 1 40 2011-03-28 Adam Barth <abarth@webkit.org> 2 41 -
trunk/Source/WebCore/WebCore.exp.in
r83628 r83645 548 548 __ZN7WebCore21SerializedScriptValue11deserializeEPK15OpaqueJSContextPPK13OpaqueJSValue 549 549 __ZN7WebCore21SerializedScriptValue6createEPK15OpaqueJSContextPK13OpaqueJSValuePS6_ 550 __ZN7WebCore21SerializedScriptValue6createEPN3JSC9ExecStateENS1_7JSValueE551 550 __ZN7WebCore21SerializedScriptValueC1ERN3WTF6VectorIhLm0EEE 552 551 __ZN7WebCore21SerializedScriptValueD1Ev -
trunk/Source/WebCore/bindings/js/JSMessageEventCustom.cpp
r60392 r83645 61 61 bool cancelableArg = exec->argument(2).toBoolean(exec); 62 62 PassRefPtr<SerializedScriptValue> dataArg = SerializedScriptValue::create(exec, exec->argument(3)); 63 if (exec->hadException()) 64 return jsUndefined(); 63 65 const UString& originArg = exec->argument(4).toString(exec); 64 66 const UString& lastEventIdArg = exec->argument(5).toString(exec); -
trunk/Source/WebCore/bindings/js/JSWorkerContextBase.cpp
r80742 r83645 32 32 #include "JSWorkerContextBase.h" 33 33 34 #include "DOMWrapperWorld.h" 34 35 #include "JSDedicatedWorkerContext.h" 35 36 #include "JSSharedWorkerContext.h" -
trunk/Source/WebCore/bindings/js/ScriptValue.cpp
r83385 r83645 101 101 } 102 102 103 PassRefPtr<SerializedScriptValue> ScriptValue::serialize(ScriptState* scriptState )103 PassRefPtr<SerializedScriptValue> ScriptValue::serialize(ScriptState* scriptState, SerializationErrorMode throwExceptions) 104 104 { 105 return SerializedScriptValue::create(scriptState, jsValue() );105 return SerializedScriptValue::create(scriptState, jsValue(), throwExceptions); 106 106 } 107 107 108 ScriptValue ScriptValue::deserialize(ScriptState* scriptState, SerializedScriptValue* value )108 ScriptValue ScriptValue::deserialize(ScriptState* scriptState, SerializedScriptValue* value, SerializationErrorMode throwExceptions) 109 109 { 110 return ScriptValue(scriptState->globalData(), value->deserialize(scriptState, scriptState->lexicalGlobalObject() ));110 return ScriptValue(scriptState->globalData(), value->deserialize(scriptState, scriptState->lexicalGlobalObject(), throwExceptions)); 111 111 } 112 112 -
trunk/Source/WebCore/bindings/js/ScriptValue.h
r83385 r83645 34 34 #include "JSDOMBinding.h" 35 35 #include "PlatformString.h" 36 #include "SerializedScriptValue.h" 36 37 #include "ScriptState.h" 37 38 #include <heap/Strong.h> … … 62 63 bool operator==(const ScriptValue& other) const { return m_value == other.m_value; } 63 64 64 PassRefPtr<SerializedScriptValue> serialize(ScriptState* );65 static ScriptValue deserialize(ScriptState*, SerializedScriptValue* );65 PassRefPtr<SerializedScriptValue> serialize(ScriptState*, SerializationErrorMode = Throwing); 66 static ScriptValue deserialize(ScriptState*, SerializedScriptValue*, SerializationErrorMode = Throwing); 66 67 67 68 static ScriptValue undefined(); -
trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp
r80951 r83645 37 37 #include "JSFileList.h" 38 38 #include "JSImageData.h" 39 #include "JSNavigator.h" 39 40 #include "SharedBuffer.h" 40 41 #include <limits> … … 161 162 */ 162 163 164 typedef pair<JSC::JSValue, SerializationReturnCode> DeserializationResult; 165 163 166 class CloneBase { 164 167 protected: … … 248 251 class CloneSerializer : CloneBase { 249 252 public: 250 static boolserialize(ExecState* exec, JSValue value, Vector<uint8_t>& out)253 static SerializationReturnCode serialize(ExecState* exec, JSValue value, Vector<uint8_t>& out) 251 254 { 252 255 CloneSerializer serializer(exec, out); … … 275 278 } 276 279 277 boolserialize(JSValue in);280 SerializationReturnCode serialize(JSValue in); 278 281 279 282 bool isArray(JSValue value) … … 415 418 if (isArray(value)) 416 419 return false; 420 421 // Object cannot be serialized because the act of walking the object creates new objects 422 if (value.isObject() && asObject(value)->inherits(&JSNavigator::s_info)) { 423 fail(); 424 write(NullTag); 425 return true; 426 } 417 427 418 428 if (value.isObject()) { … … 599 609 }; 600 610 601 boolCloneSerializer::serialize(JSValue in)611 SerializationReturnCode CloneSerializer::serialize(JSValue in) 602 612 { 603 613 Vector<uint32_t, 16> indexStack; … … 615 625 case ArrayStartState: { 616 626 ASSERT(isArray(inValue)); 617 if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) { 618 throwStackOverflow(); 619 return false; 620 } 627 if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) 628 return StackOverflowError; 621 629 622 630 JSArray* inArray = asArray(inValue); … … 632 640 case ArrayStartVisitMember: { 633 641 if (!--tickCount) { 634 if (didTimeOut()) { 635 throwInterruptedException(); 636 return false; 637 } 642 if (didTimeOut()) 643 return InterruptedExecutionError; 638 644 tickCount = ticksUntilNextCheck(); 639 645 } … … 674 680 case ObjectStartState: { 675 681 ASSERT(inValue.isObject()); 676 if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) { 677 throwStackOverflow(); 678 return false; 679 } 682 if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) 683 return StackOverflowError; 680 684 JSObject* inObject = asObject(inValue); 681 685 if (!startObject(inObject)) … … 690 694 case ObjectStartVisitMember: { 691 695 if (!--tickCount) { 692 if (didTimeOut()) { 693 throwInterruptedException(); 694 return false; 695 } 696 if (didTimeOut()) 697 return InterruptedExecutionError; 696 698 tickCount = ticksUntilNextCheck(); 697 699 } … … 709 711 inValue = getProperty(object, properties[index]); 710 712 if (shouldTerminate()) 711 return false;713 return ExistingExceptionError; 712 714 713 715 if (!inValue) { … … 719 721 720 722 if (shouldTerminate()) 721 return false;723 return ExistingExceptionError; 722 724 723 725 if (!dumpIfTerminal(inValue)) { … … 729 731 case ObjectEndVisitMember: { 730 732 if (shouldTerminate()) 731 return false;733 return ExistingExceptionError; 732 734 733 735 indexStack.last()++; … … 750 752 751 753 if (!--tickCount) { 752 if (didTimeOut()) { 753 throwInterruptedException(); 754 return false; 755 } 754 if (didTimeOut()) 755 return InterruptedExecutionError; 756 756 tickCount = ticksUntilNextCheck(); 757 757 } 758 758 } 759 759 if (m_failed) 760 return false;761 762 return true;760 return UnspecifiedError; 761 762 return SuccessfullyCompleted; 763 763 } 764 764 … … 784 784 } 785 785 786 static JSValuedeserialize(ExecState* exec, JSGlobalObject* globalObject, const Vector<uint8_t>& buffer)786 static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject, const Vector<uint8_t>& buffer) 787 787 { 788 788 if (!buffer.size()) 789 return jsNull();789 return make_pair(jsNull(), UnspecifiedError); 790 790 CloneDeserializer deserializer(exec, globalObject, buffer); 791 if (!deserializer.isValid()) { 792 deserializer.throwValidationError(); 793 return JSValue(); 794 } 791 if (!deserializer.isValid()) 792 return make_pair(JSValue(), ValidationError); 795 793 return deserializer.deserialize(); 796 794 } … … 847 845 } 848 846 849 JSValuedeserialize();847 DeserializationResult deserialize(); 850 848 851 849 void throwValidationError() … … 1194 1192 }; 1195 1193 1196 JSValueCloneDeserializer::deserialize()1194 DeserializationResult CloneDeserializer::deserialize() 1197 1195 { 1198 1196 Vector<uint32_t, 16> indexStack; … … 1223 1221 case ArrayStartVisitMember: { 1224 1222 if (!--tickCount) { 1225 if (didTimeOut()) { 1226 throwInterruptedException(); 1227 return JSValue(); 1228 } 1223 if (didTimeOut()) 1224 return make_pair(JSValue(), InterruptedExecutionError); 1229 1225 tickCount = ticksUntilNextCheck(); 1230 1226 } … … 1260 1256 objectStartState: 1261 1257 case ObjectStartState: { 1262 if (outputObjectStack.size() + outputArrayStack.size() > maximumFilterRecursion) { 1263 throwStackOverflow(); 1264 return JSValue(); 1265 } 1258 if (outputObjectStack.size() + outputArrayStack.size() > maximumFilterRecursion) 1259 return make_pair(JSValue(), StackOverflowError); 1266 1260 JSObject* outObject = constructEmptyObject(m_exec, m_globalObject); 1267 1261 m_gcBuffer.append(outObject); … … 1272 1266 case ObjectStartVisitMember: { 1273 1267 if (!--tickCount) { 1274 if (didTimeOut()) { 1275 throwInterruptedException(); 1276 return JSValue(); 1277 } 1268 if (didTimeOut()) 1269 return make_pair(JSValue(), InterruptedExecutionError); 1278 1270 tickCount = ticksUntilNextCheck(); 1279 1271 } … … 1323 1315 1324 1316 if (!--tickCount) { 1325 if (didTimeOut()) { 1326 throwInterruptedException(); 1327 return JSValue(); 1328 } 1317 if (didTimeOut()) 1318 return make_pair(JSValue(), InterruptedExecutionError); 1329 1319 tickCount = ticksUntilNextCheck(); 1330 1320 } … … 1332 1322 ASSERT(outValue); 1333 1323 ASSERT(!m_failed); 1334 return outValue;1324 return make_pair(outValue, SuccessfullyCompleted); 1335 1325 error: 1336 1326 fail(); 1337 throwValidationError(); 1338 return JSValue(); 1327 return make_pair(JSValue(), ValidationError); 1339 1328 } 1340 1329 … … 1350 1339 } 1351 1340 1352 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value )1341 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value, SerializationErrorMode throwExceptions) 1353 1342 { 1354 1343 Vector<uint8_t> buffer; 1355 if (!CloneSerializer::serialize(exec, value, buffer)) 1344 SerializationReturnCode code = CloneSerializer::serialize(exec, value, buffer); 1345 if (throwExceptions) 1346 maybeThrowExceptionIfSerializationFailed(exec, code); 1347 1348 if (!serializationDidCompleteSuccessfully(code)) 1356 1349 return 0; 1350 1357 1351 return adoptRef(new SerializedScriptValue(buffer)); 1358 1352 } … … 1393 1387 } 1394 1388 1395 JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject) 1396 { 1397 return CloneDeserializer::deserialize(exec, globalObject, m_data); 1389 JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject, SerializationErrorMode throwExceptions) 1390 { 1391 DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, m_data); 1392 if (throwExceptions) 1393 maybeThrowExceptionIfSerializationFailed(exec, result.second); 1394 return result.first; 1398 1395 } 1399 1396 … … 1419 1416 } 1420 1417 1421 } 1418 void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code) 1419 { 1420 if (code == SuccessfullyCompleted) 1421 return; 1422 1423 switch (code) { 1424 case StackOverflowError: 1425 throwError(exec, createStackOverflowError(exec)); 1426 break; 1427 case InterruptedExecutionError: 1428 throwError(exec, createInterruptedExecutionException(&exec->globalData())); 1429 break; 1430 case ValidationError: 1431 throwError(exec, createTypeError(exec, "Unable to deserialize data.")); 1432 break; 1433 case ExistingExceptionError: 1434 throwError(exec, createTypeError(exec, "Javascript has thrown an exception. Halting serialization.")); 1435 break; 1436 case UnspecifiedError: 1437 throwError(exec, createTypeError(exec, "Unknown error while serializing or deserializing data.")); 1438 break; 1439 default: 1440 ASSERT_NOT_REACHED(); 1441 } 1442 } 1443 1444 bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code) 1445 { 1446 return (code == SuccessfullyCompleted); 1447 } 1448 1449 } -
trunk/Source/WebCore/bindings/js/SerializedScriptValue.h
r66995 r83645 28 28 #define SerializedScriptValue_h 29 29 30 #include "ScriptValue.h" 30 #include <heap/Strong.h> 31 #include <runtime/JSValue.h> 31 32 #include <wtf/Forward.h> 33 #include <wtf/PassRefPtr.h> 32 34 33 35 typedef const struct OpaqueJSContext* JSContextRef; … … 36 38 namespace WebCore { 37 39 40 41 enum SerializationReturnCode { 42 SuccessfullyCompleted, 43 StackOverflowError, 44 InterruptedExecutionError, 45 ValidationError, 46 ExistingExceptionError, 47 UnspecifiedError 48 }; 49 50 enum SerializationErrorMode { Throwing, NonThrowing }; 51 38 52 class SharedBuffer; 39 53 40 54 class SerializedScriptValue : public RefCounted<SerializedScriptValue> { 41 55 public: 42 static PassRefPtr<SerializedScriptValue> create(JSC::ExecState* exec, JSC::JSValue value);56 static PassRefPtr<SerializedScriptValue> create(JSC::ExecState*, JSC::JSValue, SerializationErrorMode = Throwing); 43 57 static PassRefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef value, JSValueRef* exception); 44 58 static PassRefPtr<SerializedScriptValue> create(String string); … … 51 65 static SerializedScriptValue* nullValue(); 52 66 53 JSC::JSValue deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject);54 67 String toString(); 68 69 JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*, SerializationErrorMode = Throwing); 55 70 JSValueRef deserialize(JSContextRef, JSValueRef* exception); 71 56 72 const Vector<uint8_t>& data() { return m_data; } 57 73 … … 59 75 60 76 private: 77 static void maybeThrowExceptionIfSerializationFailed(JSC::ExecState*, SerializationReturnCode); 78 static bool serializationDidCompleteSuccessfully(SerializationReturnCode); 79 61 80 SerializedScriptValue(Vector<unsigned char>&); 62 81 Vector<unsigned char> m_data; -
trunk/Source/WebCore/loader/FrameLoader.h
r82580 r83645 39 39 #include "PolicyChecker.h" 40 40 #include "ResourceLoadNotifier.h" 41 #include "ScriptValue.h" 41 42 #include "SubframeLoader.h" 42 43 #include "ThreadableLoader.h" -
trunk/Source/WebCore/page/Frame.cpp
r83344 r83645 73 73 #include "ScriptController.h" 74 74 #include "ScriptSourceCode.h" 75 #include "ScriptValue.h" 75 76 #include "Settings.h" 76 77 #include "TextIterator.h" -
trunk/Source/WebKit/gtk/ChangeLog
r83530 r83645 1 2011-04-12 Stephanie Lewis <slewis@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 https://bugs.webkit.org/show_bug.cgi?id=58280 6 <rdar://problem/9252824> javascript in an inconsistent state due to serialization returning an un-handled exception. 7 8 Add a header include. Fallout from untangling some header files in WebCore. 9 10 * webkit/webkitwebhistoryitem.cpp: 11 1 12 2011-02-03 Martin Robinson <mrobinson@igalia.com> 2 13 -
trunk/Source/WebKit/gtk/webkit/webkitwebhistoryitem.cpp
r74933 r83645 23 23 24 24 #include "HistoryItem.h" 25 #inlcude "KURL.h" 25 26 #include "PlatformString.h" 26 27 #include "webkitglobalsprivate.h" -
trunk/Source/WebKit2/ChangeLog
r83633 r83645 1 2011-04-11 Stephanie Lewis <slewis@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 https://bugs.webkit.org/show_bug.cgi?id=58280 6 <rdar://problem/9252824> javascript in an inconsistent state due to serialization returning an un-handled exception 7 Change use of SerializedScriptValue::Create to use the same api as the rest of WebKit2. This has the benefit 8 of handling any exceptions so Javascript is not in an inconsistent state. 9 10 * Shared/API/c/WKSerializedScriptValue.h: fix a typo 11 * WebProcess/WebPage/WebPage.cpp: 12 (WebKit::WebPage::runJavaScriptInMainFrame): 13 1 14 2011-04-12 Jeff Miller <jeffm@apple.com> 2 15 -
trunk/Source/WebKit2/Shared/API/c/WKSerializedScriptValue.h
r68357 r83645 37 37 38 38 WK_EXPORT WKSerializedScriptValueRef WKSerializedScriptValueCreate(JSContextRef context, JSValueRef value, JSValueRef* exception); 39 WK_EXPORT JSValueRef WKSerializedScriptValueDeserialize(WKSerializedScriptValueRef scriptValue, JSContextRef con stext, JSValueRef* exception);39 WK_EXPORT JSValueRef WKSerializedScriptValueDeserialize(WKSerializedScriptValueRef scriptValue, JSContextRef context, JSValueRef* exception); 40 40 41 41 #ifdef __cplusplus -
trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
r83628 r83645 70 70 #include "WebProcessProxyMessageKinds.h" 71 71 #include "WebProcessProxyMessages.h" 72 #include <JavaScriptCore/APICast.h> 72 73 #include <WebCore/AbstractDatabase.h> 73 74 #include <WebCore/ArchiveResource.h> … … 1236 1237 JSLock lock(SilenceAssertionsOnly); 1237 1238 if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) { 1238 if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue))) 1239 if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), 1240 toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0))) 1239 1241 dataReference = CoreIPC::DataReference(serializedResultValue->data().data(), serializedResultValue->data().size()); 1240 1242 }
Note: See TracChangeset
for help on using the changeset viewer.