A stack overflow in the parsing of a builtin (called by createExecutable) cause a...
authorrmorisset@apple.com <rmorisset@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Mar 2018 12:39:43 +0000 (12:39 +0000)
committerrmorisset@apple.com <rmorisset@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Mar 2018 12:39:43 +0000 (12:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184074
<rdar://problem/37165897>

Reviewed by Keith Miller.

JSTests:

* stress/stack-overflow-while-parsing-builtin.js: Added.
(f):

Source/JavaScriptCore:

Fixing this requires getting the ParserError (with information about the failure) and an ExecState* (to throw an exception) in the same place.
It is surprisingly painful, with quite a long call stack between the last function with an access to an ExecState* and the first function with the ParserError.
Even worse, many of these functions are generated by macros, themselves generated by a maze of python scripts.
As a result, this patch is grotesquely large, while all it does is adding enough plumbing to throw a proper exception in this specific case.

There are now bare calls to '.value()' on several paths that may crash. It is not a problem in my opinion, since we previously crashed in every case regardless of the path that took us to createExecutable when encountering a stack overflow.
If we ever find an example that can cause these calls to fail, it should be doable to throw a proper exception there too.

Two other minor changes:
- I removed BuiltinExecutableCreator.{cpp, h} as it was nearly empty, and only used in one place. That place now includes BuiltinExecutables.h directly instead.
- I moved code from ParserError.h into a newly created ParserError.cpp, as I see no need to inline functions that are only used when encountering a parser error, and ParserError.h is now included in quite a few places.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Scripts/builtins/builtins_generate_combined_header.py:
(BuiltinsCombinedHeaderGenerator.generate_forward_declarations):
(ParserError):
(generate_section_for_object): Deleted.
(generate_externs_for_object): Deleted.
(generate_macros_for_object): Deleted.
(generate_section_for_code_table_macro): Deleted.
(generate_section_for_code_name_macro): Deleted.
(generate_section_for_global_private_code_name_macro): Deleted.
* Scripts/builtins/builtins_generate_separate_header.py:
(generate_secondary_header_includes):
* Scripts/builtins/builtins_templates.py:
* Sources.txt:
* builtins/BuiltinExecutableCreator.cpp: Removed.
* builtins/BuiltinExecutableCreator.h: Removed.
* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createDefaultConstructor):
(JSC::BuiltinExecutables::createBuiltinExecutable):
(JSC::createBuiltinExecutable):
(JSC::BuiltinExecutables::createExecutableOrCrash):
(JSC::BuiltinExecutables::createExecutable):
* builtins/BuiltinExecutables.h:
* bytecompiler/BytecodeGenerator.h:
* parser/ParserError.cpp: Added.
(JSC::ParserError::toErrorObject):
(JSC::ParserError::throwStackOverflowOrOutOfMemory):
(WTF::printInternal):
* parser/ParserError.h:
(JSC::ParserError::toErrorObject): Deleted.
(WTF::printInternal): Deleted.
* runtime/AsyncIteratorPrototype.cpp:
(JSC::AsyncIteratorPrototype::finishCreation):
* runtime/FunctionPrototype.cpp:
(JSC::FunctionPrototype::addFunctionProperties):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSObject.cpp:
(JSC::JSObject::getOwnStaticPropertySlot):
(JSC::JSObject::reifyAllStaticProperties):
* runtime/JSObject.h:
(JSC::JSObject::getOwnNonIndexPropertySlot):
(JSC::JSObject::getOwnPropertySlot):
(JSC::JSObject::getPropertySlot):
* runtime/JSObjectInlines.h:
(JSC::JSObject::getNonIndexPropertySlot):
* runtime/JSTypedArrayViewPrototype.cpp:
(JSC::JSTypedArrayViewPrototype::finishCreation):
* runtime/Lookup.cpp:
(JSC::reifyStaticAccessor):
(JSC::setUpStaticFunctionSlot):
* runtime/Lookup.h:
(JSC::getStaticPropertySlotFromTable):
(JSC::reifyStaticProperty):
* runtime/MapPrototype.cpp:
(JSC::MapPrototype::finishCreation):
* runtime/SetPrototype.cpp:
(JSC::SetPrototype::finishCreation):
* tools/JSDollarVM.cpp:
(JSC::functionCreateBuiltin):

Source/WebCore:

I had to slightly change the type of some bindings between JSC and WebCore. No functional change intended on the WebCore side.

* bindings/js/JSReadableStreamPrivateConstructors.cpp:
(WebCore::JSBuiltinReadableStreamDefaultReaderPrivateConstructor::initializeExecutable):
(WebCore::JSBuiltinReadableStreamDefaultControllerPrivateConstructor::initializeExecutable):
(WebCore::JSBuiltinReadableByteStreamControllerPrivateConstructor::initializeExecutable):
(WebCore::JSBuiltinReadableStreamBYOBReaderPrivateConstructor::initializeExecutable):
(WebCore::JSBuiltinReadableStreamBYOBRequestPrivateConstructor::initializeExecutable):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateConstructorHelperMethods):
* bindings/scripts/test/JS/JSTestClassWithJSBuiltinConstructor.cpp:
(WebCore::JSTestClassWithJSBuiltinConstructorConstructor::initializeExecutable):
* bindings/scripts/test/JS/JSTestJSBuiltinConstructor.cpp:
(WebCore::JSTestJSBuiltinConstructorConstructor::initializeExecutable):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230102 268f45cc-cd09-0410-ab3c-d52691b4dbfc

32 files changed:
JSTests/ChangeLog
JSTests/stress/stack-overflow-while-parsing-builtin.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Scripts/builtins/builtins_generate_combined_header.py
Source/JavaScriptCore/Scripts/builtins/builtins_generate_separate_header.py
Source/JavaScriptCore/Scripts/builtins/builtins_templates.py
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp [deleted file]
Source/JavaScriptCore/builtins/BuiltinExecutableCreator.h [deleted file]
Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
Source/JavaScriptCore/builtins/BuiltinExecutables.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/parser/ParserError.cpp [new file with mode: 0644]
Source/JavaScriptCore/parser/ParserError.h
Source/JavaScriptCore/runtime/AsyncIteratorPrototype.cpp
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSObjectInlines.h
Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.cpp
Source/JavaScriptCore/runtime/Lookup.cpp
Source/JavaScriptCore/runtime/Lookup.h
Source/JavaScriptCore/runtime/MapPrototype.cpp
Source/JavaScriptCore/runtime/SetPrototype.cpp
Source/JavaScriptCore/tools/JSDollarVM.cpp
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestClassWithJSBuiltinConstructor.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestJSBuiltinConstructor.cpp

index cfb478e..0954167 100644 (file)
@@ -1,5 +1,16 @@
 2018-03-30  Robin Morisset  <rmorisset@apple.com>
 
+        A stack overflow in the parsing of a builtin (called by createExecutable) cause a crash instead of a catchable js exception
+        https://bugs.webkit.org/show_bug.cgi?id=184074
+        <rdar://problem/37165897>
+
+        Reviewed by Keith Miller.
+
+        * stress/stack-overflow-while-parsing-builtin.js: Added.
+        (f):
+
+2018-03-30  Robin Morisset  <rmorisset@apple.com>
+
         Out-of-bounds accesses due to a missing check for MAX_STORAGE_VECTOR_LENGTH in unshiftCountForAnyIndexingType
         https://bugs.webkit.org/show_bug.cgi?id=183657
 
diff --git a/JSTests/stress/stack-overflow-while-parsing-builtin.js b/JSTests/stress/stack-overflow-while-parsing-builtin.js
new file mode 100644 (file)
index 0000000..bb99a17
--- /dev/null
@@ -0,0 +1,11 @@
+function f() {
+    try {
+        f();
+    } catch (e) {
+        try {
+            Map.prototype.forEach.call('', {});
+        } catch {}
+    }
+}
+
+f()
index 74205d1..bfb2088 100644 (file)
@@ -1,5 +1,86 @@
 2018-03-30  Robin Morisset  <rmorisset@apple.com>
 
+        A stack overflow in the parsing of a builtin (called by createExecutable) cause a crash instead of a catchable js exception
+        https://bugs.webkit.org/show_bug.cgi?id=184074
+        <rdar://problem/37165897>
+
+        Reviewed by Keith Miller.
+
+        Fixing this requires getting the ParserError (with information about the failure) and an ExecState* (to throw an exception) in the same place.
+        It is surprisingly painful, with quite a long call stack between the last function with an access to an ExecState* and the first function with the ParserError.
+        Even worse, many of these functions are generated by macros, themselves generated by a maze of python scripts.
+        As a result, this patch is grotesquely large, while all it does is adding enough plumbing to throw a proper exception in this specific case.
+
+        There are now bare calls to '.value()' on several paths that may crash. It is not a problem in my opinion, since we previously crashed in every case regardless of the path that took us to createExecutable when encountering a stack overflow.
+        If we ever find an example that can cause these calls to fail, it should be doable to throw a proper exception there too.
+
+        Two other minor changes:
+        - I removed BuiltinExecutableCreator.{cpp, h} as it was nearly empty, and only used in one place. That place now includes BuiltinExecutables.h directly instead.
+        - I moved code from ParserError.h into a newly created ParserError.cpp, as I see no need to inline functions that are only used when encountering a parser error, and ParserError.h is now included in quite a few places.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Scripts/builtins/builtins_generate_combined_header.py:
+        (BuiltinsCombinedHeaderGenerator.generate_forward_declarations):
+        (ParserError):
+        (generate_section_for_object): Deleted.
+        (generate_externs_for_object): Deleted.
+        (generate_macros_for_object): Deleted.
+        (generate_section_for_code_table_macro): Deleted.
+        (generate_section_for_code_name_macro): Deleted.
+        (generate_section_for_global_private_code_name_macro): Deleted.
+        * Scripts/builtins/builtins_generate_separate_header.py:
+        (generate_secondary_header_includes):
+        * Scripts/builtins/builtins_templates.py:
+        * Sources.txt:
+        * builtins/BuiltinExecutableCreator.cpp: Removed.
+        * builtins/BuiltinExecutableCreator.h: Removed.
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::BuiltinExecutables::createDefaultConstructor):
+        (JSC::BuiltinExecutables::createBuiltinExecutable):
+        (JSC::createBuiltinExecutable):
+        (JSC::BuiltinExecutables::createExecutableOrCrash):
+        (JSC::BuiltinExecutables::createExecutable):
+        * builtins/BuiltinExecutables.h:
+        * bytecompiler/BytecodeGenerator.h:
+        * parser/ParserError.cpp: Added.
+        (JSC::ParserError::toErrorObject):
+        (JSC::ParserError::throwStackOverflowOrOutOfMemory):
+        (WTF::printInternal):
+        * parser/ParserError.h:
+        (JSC::ParserError::toErrorObject): Deleted.
+        (WTF::printInternal): Deleted.
+        * runtime/AsyncIteratorPrototype.cpp:
+        (JSC::AsyncIteratorPrototype::finishCreation):
+        * runtime/FunctionPrototype.cpp:
+        (JSC::FunctionPrototype::addFunctionProperties):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::getOwnStaticPropertySlot):
+        (JSC::JSObject::reifyAllStaticProperties):
+        * runtime/JSObject.h:
+        (JSC::JSObject::getOwnNonIndexPropertySlot):
+        (JSC::JSObject::getOwnPropertySlot):
+        (JSC::JSObject::getPropertySlot):
+        * runtime/JSObjectInlines.h:
+        (JSC::JSObject::getNonIndexPropertySlot):
+        * runtime/JSTypedArrayViewPrototype.cpp:
+        (JSC::JSTypedArrayViewPrototype::finishCreation):
+        * runtime/Lookup.cpp:
+        (JSC::reifyStaticAccessor):
+        (JSC::setUpStaticFunctionSlot):
+        * runtime/Lookup.h:
+        (JSC::getStaticPropertySlotFromTable):
+        (JSC::reifyStaticProperty):
+        * runtime/MapPrototype.cpp:
+        (JSC::MapPrototype::finishCreation):
+        * runtime/SetPrototype.cpp:
+        (JSC::SetPrototype::finishCreation):
+        * tools/JSDollarVM.cpp:
+        (JSC::functionCreateBuiltin):
+
+2018-03-30  Robin Morisset  <rmorisset@apple.com>
+
         Out-of-bounds accesses due to a missing check for MAX_STORAGE_VECTOR_LENGTH in unshiftCountForAnyIndexingType
         https://bugs.webkit.org/show_bug.cgi?id=183657
         <rdar://problem/38464399>
index 7548bac..9948574 100644 (file)
                DCF3D56D1CD29476003D5C65 /* LazyPropertyInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF3D5681CD29468003D5C65 /* LazyPropertyInlines.h */; };
                DCFDFBD91D1F5D9B00FE3D72 /* B3BottomProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = DCFDFBD71D1F5D9800FE3D72 /* B3BottomProvider.h */; };
                DCFDFBDA1D1F5D9E00FE3D72 /* B3TypeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = DCFDFBD81D1F5D9800FE3D72 /* B3TypeMap.h */; };
-               DE26E9031CB5DD0500D2BE82 /* BuiltinExecutableCreator.h in Headers */ = {isa = PBXBuildFile; fileRef = DE26E9021CB5DD0500D2BE82 /* BuiltinExecutableCreator.h */; };
                DEA7E2451BBC677F00D78440 /* JSTypedArrayViewPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E31618131EC5FE170006A218 /* DOMAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = E31618101EC5FE080006A218 /* DOMAnnotation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScript.h; sourceTree = "<group>"; };
                1CAA8B4B0D32C39A0041BCFF /* JavaScriptCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptCore.h; sourceTree = "<group>"; };
                20ECB15EFC524624BC2F02D5 /* ModuleNamespaceAccessCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleNamespaceAccessCase.cpp; sourceTree = "<group>"; };
+               220C60C6206CEABD00FC4637 /* ParserError.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ParserError.cpp; sourceTree = "<group>"; };
                2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringJoiner.cpp; sourceTree = "<group>"; };
                2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = "<group>"; };
                262D85B41C0D650F006ACB61 /* AirFixPartialRegisterStalls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirFixPartialRegisterStalls.cpp; path = b3/air/AirFixPartialRegisterStalls.cpp; sourceTree = "<group>"; };
                DCF3D5681CD29468003D5C65 /* LazyPropertyInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyPropertyInlines.h; sourceTree = "<group>"; };
                DCFDFBD71D1F5D9800FE3D72 /* B3BottomProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3BottomProvider.h; path = b3/B3BottomProvider.h; sourceTree = "<group>"; };
                DCFDFBD81D1F5D9800FE3D72 /* B3TypeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3TypeMap.h; path = b3/B3TypeMap.h; sourceTree = "<group>"; };
-               DE26E9021CB5DD0500D2BE82 /* BuiltinExecutableCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinExecutableCreator.h; sourceTree = "<group>"; };
-               DE26E9061CB5DD9600D2BE82 /* BuiltinExecutableCreator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BuiltinExecutableCreator.cpp; sourceTree = "<group>"; };
                DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntrinsicEmitter.cpp; sourceTree = "<group>"; };
                E124A8F50E555775003091F1 /* OpaqueJSString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueJSString.h; sourceTree = "<group>"; };
                E124A8F60E555775003091F1 /* OpaqueJSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpaqueJSString.cpp; sourceTree = "<group>"; };
                                93F0B3AA09BB4DC00068FCE3 /* Parser.h */,
                                93052C320FB792190048FDC3 /* ParserArena.cpp */,
                                93052C330FB792190048FDC3 /* ParserArena.h */,
+                               220C60C6206CEABD00FC4637 /* ParserError.cpp */,
                                0FCCAE4316D0CF6E00D0C65B /* ParserError.h */,
                                9B4954E81A6640DB002815A6 /* ParserFunctionInfo.h */,
                                A77F18241641925400640A47 /* ParserModes.h */,
                                5B8243041DB7AA4900EA6384 /* AsyncFunctionPrototype.js */,
                                8BC064821E180B4A00B2B8CA /* AsyncGeneratorPrototype.js */,
                                8BC064951E1D838B00B2B8CA /* AsyncIteratorPrototype.js */,
-                               DE26E9061CB5DD9600D2BE82 /* BuiltinExecutableCreator.cpp */,
-                               DE26E9021CB5DD0500D2BE82 /* BuiltinExecutableCreator.h */,
                                A7D801A11880D66E0026C39B /* BuiltinExecutables.cpp */,
                                A7D801A21880D66E0026C39B /* BuiltinExecutables.h */,
                                E380D66B1F19249D00A59095 /* BuiltinNames.cpp */,
                                9B4694391F97439E00CCB3F9 /* BooleanPrototype.h in Headers */,
                                996B73191BDA068000331B84 /* BooleanPrototype.lut.h in Headers */,
                                FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */,
-                               DE26E9031CB5DD0500D2BE82 /* BuiltinExecutableCreator.h in Headers */,
                                A7D801A51880D66E0026C39B /* BuiltinExecutables.h in Headers */,
                                A75EE9B218AAB7E200AAD043 /* BuiltinNames.h in Headers */,
                                99DA00A61BD5993100F4575C /* builtins.py in Headers */,
                                A503FA1E188E0FB000110F14 /* JSJavaScriptCallFramePrototype.h in Headers */,
                                7013CA8C1B491A9400CAE613 /* JSJob.h in Headers */,
                                BC18C4160E16F5CD00B34460 /* JSLexicalEnvironment.h in Headers */,
-                               7A9774A8206B82E4008D03D0 /* JSWeakValue.h in Headers */,
                                BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */,
                                C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */,
                                2A4BB7F318A41179008A0FCD /* JSManagedValueInternal.h in Headers */,
                                A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */,
                                0F0B286B1EB8E6CF000EB5D2 /* JSWeakPrivate.h in Headers */,
                                709FB8681AE335C60039D069 /* JSWeakSet.h in Headers */,
+                               7A9774A8206B82E4008D03D0 /* JSWeakValue.h in Headers */,
                                AD5C36EB1F75AD73000BCAAF /* JSWebAssembly.h in Headers */,
                                AD9E852F1E8A0C7C008DE39E /* JSWebAssemblyCodeBlock.h in Headers */,
                                79EFD4841EBC045C00F3DFEA /* JSWebAssemblyCodeBlockHeapCellType.h in Headers */,
index cde357c..7214cda 100755 (executable)
@@ -66,12 +66,17 @@ class BuiltinsCombinedHeaderGenerator(BuiltinsGenerator):
         return "\n\n".join(sections)
 
     def generate_forward_declarations(self):
-        return """namespace JSC {
+        return """
+#include <wtf/Expected.h>
+
+namespace JSC {
 class FunctionExecutable;
 class VM;
+class ParserError;
 
 enum class ConstructAbility : unsigned;
-}"""
+}
+"""
 
     def generate_section_for_object(self, object):
         lines = []
index 58c8f2a..1889625 100755 (executable)
@@ -93,6 +93,10 @@ class FunctionExecutable;
             ),
 
             (["WebCore"],
+                ("JavaScriptCore", "parser/ParserError.h"),
+            ),
+
+            (["WebCore"],
                 ("JavaScriptCore", "builtins/BuiltinUtils.h"),
             ),
 
index 907a6d7..dd98947 100644 (file)
@@ -68,14 +68,14 @@ THE POSSIBILITY OF SUCH DAMAGE.
 
     CombinedHeaderStaticMacros = (
     """#define DECLARE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
-    JSC::FunctionExecutable* codeName##Generator(JSC::VM&);
+    Expected<JSC::FunctionExecutable*, JSC::ParserError> codeName##Generator(JSC::VM&);
 
 ${macroPrefix}_FOREACH_BUILTIN_CODE(DECLARE_BUILTIN_GENERATOR)
 #undef DECLARE_BUILTIN_GENERATOR""")
 
     SeparateHeaderStaticMacros = (
     """#define DECLARE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
-    JSC::FunctionExecutable* codeName##Generator(JSC::VM&);
+    Expected<JSC::FunctionExecutable*, JSC::ParserError> codeName##Generator(JSC::VM&);
 
 ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(DECLARE_BUILTIN_GENERATOR)
 #undef DECLARE_BUILTIN_GENERATOR""")
@@ -83,9 +83,12 @@ ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(DECLARE_BUILTIN_GENERATOR)
     CombinedJSCImplementationStaticMacros = (
     """
 #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
-JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\
+Expected<JSC::FunctionExecutable*, JSC::ParserError> codeName##Generator(JSC::VM& vm) \\
 {\\
-    return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \
+    auto expectedUnlinked = vm.builtinExecutables()->codeName##Executable();\\
+    if (!expectedUnlinked.has_value())\\
+        return makeUnexpected(expectedUnlinked.error());\\
+        return expectedUnlinked.value()->link(vm, vm.builtinExecutables()->codeName##Source(), std::nullopt, s_##codeName##Intrinsic);\\
 }
 ${macroPrefix}_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
 #undef DEFINE_BUILTIN_GENERATOR
@@ -94,9 +97,12 @@ ${macroPrefix}_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
     SeparateJSCImplementationStaticMacros = (
     """
 #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
-JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\
+Expected<JSC::FunctionExecutable*, JSC::ParserError> codeName##Generator(JSC::VM& vm) \\
 {\\
-    return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \
+    auto expectedUnlinked = vm.builtinExecutables()->codeName##Executable();\\
+    if (!expectedUnlinked.has_value())\\
+        return makeUnexpected(expectedUnlinked.error());\\
+    return expectedUnlinked.value()->link(vm, vm.builtinExecutables()->codeName##Source(), std::nullopt, s_##codeName##Intrinsic);\\
 }
 ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
 #undef DEFINE_BUILTIN_GENERATOR
@@ -105,10 +111,10 @@ ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
     CombinedWebCoreImplementationStaticMacros = (
         """
 #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
-JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\
+Expected<JSC::FunctionExecutable*, JSC::ParserError> codeName##Generator(JSC::VM& vm) \\
 {\\
     JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \\
-    return clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Executable()->link(vm, clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \\
+    return clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Executable().value()->link(vm, clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \\
 }
 ${macroPrefix}_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
 #undef DEFINE_BUILTIN_GENERATOR
@@ -117,10 +123,10 @@ ${macroPrefix}_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
     SeparateWebCoreImplementationStaticMacros = (
         """
 #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
-JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\
+Expected<JSC::FunctionExecutable*, JSC::ParserError> codeName##Generator(JSC::VM& vm) \\
 {\\
     JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \\
-    return clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Executable()->link(vm, clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \\
+    return clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Executable().value()->link(vm, clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \\
 }
 ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
 #undef DEFINE_BUILTIN_GENERATOR
@@ -139,7 +145,7 @@ public:
     }
 
 #define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \\
-    JSC::UnlinkedFunctionExecutable* name##Executable(); \\
+Expected<JSC::UnlinkedFunctionExecutable*, JSC::ParserError> name##Executable(); \\
     const JSC::SourceCode& name##Source() const { return m_##name##Source; }
     ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(EXPOSE_BUILTIN_EXECUTABLES)
 #undef EXPOSE_BUILTIN_EXECUTABLES
@@ -162,7 +168,7 @@ private:
 };
 
 #define DEFINE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \\
-inline JSC::UnlinkedFunctionExecutable* ${objectName}BuiltinsWrapper::name##Executable() \\
+inline Expected<JSC::UnlinkedFunctionExecutable*, JSC::ParserError> ${objectName}BuiltinsWrapper::name##Executable() \\
 {\\
     if (!m_##name##Executable) {\\
         JSC::Identifier executableName = functionName##PublicName();\\
@@ -202,7 +208,7 @@ public:
 inline void ${objectName}BuiltinFunctions::init(JSC::JSGlobalObject& globalObject)
 {
 #define EXPORT_FUNCTION(codeName, functionName, overriddenName, length)\\
-    m_##functionName##Function.set(m_vm, &globalObject, JSC::JSFunction::create(m_vm, codeName##Generator(m_vm), &globalObject));
+    m_##functionName##Function.set(m_vm, &globalObject, JSC::JSFunction::create(m_vm, codeName##Generator(m_vm).value(), &globalObject));
     ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(EXPORT_FUNCTION)
 #undef EXPORT_FUNCTION
 }
index aa963f5..49f57dd 100644 (file)
@@ -179,7 +179,6 @@ bindings/ScriptObject.cpp
 bindings/ScriptValue.cpp
 
 builtins/BuiltinExecutables.cpp
-builtins/BuiltinExecutableCreator.cpp
 builtins/BuiltinNames.cpp
 
 bytecode/AccessCase.cpp
@@ -654,6 +653,7 @@ parser/Nodes.cpp
 parser/NodesAnalyzeModule.cpp
 parser/Parser.cpp
 parser/ParserArena.cpp
+parser/ParserError.cpp
 parser/SourceProvider.cpp
 parser/SourceProviderCache.cpp
 parser/UnlinkedSourceCode.cpp
diff --git a/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp b/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp
deleted file mode 100644 (file)
index 2b79e7e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "BuiltinExecutableCreator.h"
-
-#include "BuiltinExecutables.h"
-
-namespace JSC {
-
-UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& source, const Identifier& ident, ConstructorKind kind, ConstructAbility ability)
-{
-    return BuiltinExecutables::createExecutable(vm, source, ident, kind, ability);
-}
-    
-} // namespace JSC
diff --git a/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.h b/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.h
deleted file mode 100644 (file)
index 19c0884..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "ConstructAbility.h"
-#include "ParserModes.h"
-#include "SourceCode.h"
-
-namespace JSC {
-
-JS_EXPORT_PRIVATE UnlinkedFunctionExecutable* createBuiltinExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
-
-} // namespace JSC
index ad0d839..ef69960 100644 (file)
@@ -30,6 +30,7 @@
 #include "BuiltinNames.h"
 #include "JSCInlines.h"
 #include "Parser.h"
+#include <wtf/Expected.h>
 #include <wtf/NeverDestroyed.h>
 
 namespace JSC {
@@ -51,25 +52,34 @@ UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(Constru
     case ConstructorKind::None:
         break;
     case ConstructorKind::Base:
-        return createExecutable(m_vm, makeSource(baseConstructorCode, { }), name, constructorKind, ConstructAbility::CanConstruct);
+        return createExecutableOrCrash(m_vm, makeSource(baseConstructorCode, { }), name, constructorKind, ConstructAbility::CanConstruct);
     case ConstructorKind::Extends:
-        return createExecutable(m_vm, makeSource(derivedConstructorCode, { }), name, constructorKind, ConstructAbility::CanConstruct);
+        return createExecutableOrCrash(m_vm, makeSource(derivedConstructorCode, { }), name, constructorKind, ConstructAbility::CanConstruct);
     }
-    ASSERT_NOT_REACHED();
-    return nullptr;
+    RELEASE_ASSERT_NOT_REACHED();
 }
 
-UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const SourceCode& code, const Identifier& name, ConstructAbility constructAbility)
+ExpectedUnlinkedFunctionExecutable BuiltinExecutables::createBuiltinExecutable(const SourceCode& code, const Identifier& name, ConstructAbility constructAbility)
 {
     return createExecutable(m_vm, code, name, ConstructorKind::None, constructAbility);
 }
 
 UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& code, const Identifier& name, ConstructAbility constructAbility)
 {
-    return BuiltinExecutables::createExecutable(vm, code, name, ConstructorKind::None, constructAbility);
+    return BuiltinExecutables::createExecutableOrCrash(vm, code, name, ConstructorKind::None, constructAbility);
 }
 
-UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility)
+UnlinkedFunctionExecutable* BuiltinExecutables::createExecutableOrCrash(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility)
+{
+    auto expected = BuiltinExecutables::createExecutable(vm, source, name, constructorKind, constructAbility);
+    if (!expected.has_value()) {
+        dataLogLn("Fatal error compiling builtin function '", name.string(), "'");
+        CRASH();
+    }
+    return expected.value();
+}
+
+ExpectedUnlinkedFunctionExecutable BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility)
 {
     JSTextPosition positionBeforeLastNewline;
     ParserError error;
@@ -83,8 +93,8 @@ UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const S
         &positionBeforeLastNewline, constructorKind);
 
     if (!program) {
-        dataLog("Fatal error compiling builtin function '", name.string(), "': ", error.message());
-        CRASH();
+        RELEASE_ASSERT(error.isValid());
+        return makeUnexpected(WTFMove(error));
     }
 
     StatementNode* exprStatement = program->singleStatement();
@@ -106,7 +116,7 @@ UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const S
     metadata->overrideName(name);
     VariableEnvironment dummyTDZVariables;
     UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, JSParserScriptMode::Classic, dummyTDZVariables, DerivedContextType::None, WTFMove(parentSourceOverride));
-    return functionExecutable;
+    return ExpectedUnlinkedFunctionExecutable(functionExecutable);
 }
 
 void BuiltinExecutables::finalize(Handle<Unknown>, void* context)
@@ -115,15 +125,18 @@ void BuiltinExecutables::finalize(Handle<Unknown>, void* context)
 }
 
 #define DEFINE_BUILTIN_EXECUTABLES(name, functionName, overrideName, length) \
-UnlinkedFunctionExecutable* BuiltinExecutables::name##Executable() \
+ExpectedUnlinkedFunctionExecutable BuiltinExecutables::name##Executable() \
 {\
     if (!m_##name##Executable) {\
         Identifier executableName = m_vm.propertyNames->builtinNames().functionName##PublicName();\
         if (overrideName)\
             executableName = Identifier::fromString(&m_vm, overrideName);\
-        m_##name##Executable = Weak<UnlinkedFunctionExecutable>(createBuiltinExecutable(m_##name##Source, executableName, s_##name##ConstructAbility), this, &m_##name##Executable);\
+        ExpectedUnlinkedFunctionExecutable f = createBuiltinExecutable(m_##name##Source, executableName, s_##name##ConstructAbility);\
+        if (!f.has_value())\
+            return f;\
+        m_##name##Executable = Weak<UnlinkedFunctionExecutable>(f.value(), this, &m_##name##Executable);\
     }\
-    return m_##name##Executable.get();\
+    return ExpectedUnlinkedFunctionExecutable(m_##name##Executable.get());\
 }
 JSC_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_EXECUTABLES)
 #undef EXPOSE_BUILTIN_SOURCES
index 368a31b..ce508be 100644 (file)
 #pragma once
 
 #include "JSCBuiltins.h"
-#include "ParserModes.h"
+#include "Parser.h"
 #include "SourceCode.h"
 #include "Weak.h"
 #include "WeakHandleOwner.h"
+#include <wtf/Expected.h>
 
 namespace JSC {
 
@@ -37,13 +38,15 @@ class UnlinkedFunctionExecutable;
 class Identifier;
 class VM;
 
+using ExpectedUnlinkedFunctionExecutable = Expected<UnlinkedFunctionExecutable*, ParserError>;
+
 class BuiltinExecutables final: private WeakHandleOwner {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     explicit BuiltinExecutables(VM&);
 
 #define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \
-UnlinkedFunctionExecutable* name##Executable(); \
+ExpectedUnlinkedFunctionExecutable name##Executable(); \
 const SourceCode& name##Source() { return m_##name##Source; }
     
     JSC_FOREACH_BUILTIN_CODE(EXPOSE_BUILTIN_EXECUTABLES)
@@ -51,13 +54,14 @@ const SourceCode& name##Source() { return m_##name##Source; }
 
     UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name);
 
-    static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
+    static ExpectedUnlinkedFunctionExecutable createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
+    static UnlinkedFunctionExecutable* createExecutableOrCrash(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
 private:
     void finalize(Handle<Unknown>, void* context) override;
 
     VM& m_vm;
 
-    UnlinkedFunctionExecutable* createBuiltinExecutable(const SourceCode&, const Identifier&, ConstructAbility);
+    ExpectedUnlinkedFunctionExecutable createBuiltinExecutable(const SourceCode&, const Identifier&, ConstructAbility);
 
 #define DECLARE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length)\
     SourceCode m_##name##Source; \
index 0edfe3d..ddb4612 100644 (file)
@@ -31,6 +31,7 @@
 #pragma once
 
 #include "CodeBlock.h"
+#include "Error.h"
 #include "Instruction.h"
 #include "Interpreter.h"
 #include "JSAsyncGeneratorFunction.h"
diff --git a/Source/JavaScriptCore/parser/ParserError.cpp b/Source/JavaScriptCore/parser/ParserError.cpp
new file mode 100644 (file)
index 0000000..2f9ac7a
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ParserError.h"
+
+#include "ErrorHandlingScope.h"
+#include "ExceptionHelpers.h"
+#include "HeapCellInlines.h"
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+JSObject* ParserError::toErrorObject(JSGlobalObject* globalObject, const SourceCode& source, int overrideLineNumber)
+{
+    ExecState* exec = globalObject->globalExec();
+    switch (m_type) {
+    case ErrorNone:
+        return nullptr;
+    case SyntaxError: {
+        auto syntaxError = createSyntaxError(exec, m_message);
+        auto line = overrideLineNumber == -1 ? m_line : overrideLineNumber;
+        return addErrorInfo(exec, syntaxError, line, source);
+    }
+    case EvalError:
+        return createSyntaxError(exec, m_message);
+    case StackOverflow: {
+        ErrorHandlingScope errorScope(globalObject->vm());
+        return createStackOverflowError(exec);
+    }
+    case OutOfMemory:
+        return createOutOfMemoryError(exec);
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+JSObject* ParserError::throwStackOverflowOrOutOfMemory(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    switch (m_type) {
+    case ErrorNone:
+    case EvalError:
+    case SyntaxError:
+        RELEASE_ASSERT_NOT_REACHED();
+    case StackOverflow:
+        return throwStackOverflowError(exec, scope);
+    case OutOfMemory:
+        return throwOutOfMemoryError(exec, scope);
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+} // namespace JSC
+
+namespace WTF {
+void printInternal(PrintStream& out, JSC::ParserError::SyntaxErrorType type)
+{
+    switch (type) {
+    case JSC::ParserError::SyntaxErrorNone:
+        out.print("SyntaxErrorNone");
+        return;
+    case JSC::ParserError::SyntaxErrorIrrecoverable:
+        out.print("SyntaxErrorIrrecoverable");
+        return;
+    case JSC::ParserError::SyntaxErrorUnterminatedLiteral:
+        out.print("SyntaxErrorUnterminatedLiteral");
+        return;
+    case JSC::ParserError::SyntaxErrorRecoverable:
+        out.print("SyntaxErrorRecoverable");
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void printInternal(PrintStream& out, JSC::ParserError::ErrorType type)
+{
+    switch (type) {
+    case JSC::ParserError::ErrorNone:
+        out.print("ErrorNone");
+        return;
+    case JSC::ParserError::StackOverflow:
+        out.print("StackOverflow");
+        return;
+    case JSC::ParserError::EvalError:
+        out.print("EvalError");
+        return;
+    case JSC::ParserError::OutOfMemory:
+        out.print("OutOfMemory");
+        return;
+    case JSC::ParserError::SyntaxError:
+        out.print("SyntaxError");
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+} // namespace WTF
index 7883efe..c0bc399 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2013, 2018 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,9 +25,6 @@
 
 #pragma once
 
-#include "Error.h"
-#include "ErrorHandlingScope.h"
-#include "ExceptionHelpers.h"
 #include "ParserTokens.h"
 #include <wtf/text/WTFString.h>
 
@@ -84,31 +81,8 @@ public:
     const String& message() const { return m_message; }
     int line() const { return m_line; }
 
-    JSObject* toErrorObject(
-        JSGlobalObject* globalObject, const SourceCode& source, 
-        int overrideLineNumber = -1)
-    {
-        ExecState* exec = globalObject->globalExec();
-        switch (m_type) {
-        case ErrorNone:
-            return nullptr;
-        case SyntaxError:
-            return addErrorInfo(
-                exec, 
-                createSyntaxError(exec, m_message), 
-                overrideLineNumber == -1 ? m_line : overrideLineNumber, source);
-        case EvalError:
-            return createSyntaxError(exec, m_message);
-        case StackOverflow: {
-            ErrorHandlingScope errorScope(globalObject->vm());
-            return createStackOverflowError(exec);
-        }
-        case OutOfMemory:
-            return createOutOfMemoryError(exec);
-        }
-        CRASH();
-        return nullptr;
-    }
+    JSObject* toErrorObject(JSGlobalObject*, const SourceCode&, int overrideLineNumber = -1);
+    JS_EXPORT_PRIVATE JSObject* throwStackOverflowOrOutOfMemory(ExecState* = nullptr);
 
 private:
     JSToken m_token;
@@ -121,48 +95,6 @@ private:
 } // namespace JSC
 
 namespace WTF {
-
-inline void printInternal(PrintStream& out, JSC::ParserError::SyntaxErrorType type)
-{
-    switch (type) {
-    case JSC::ParserError::SyntaxErrorNone:
-        out.print("SyntaxErrorNone");
-        return;
-    case JSC::ParserError::SyntaxErrorIrrecoverable:
-        out.print("SyntaxErrorIrrecoverable");
-        return;
-    case JSC::ParserError::SyntaxErrorUnterminatedLiteral:
-        out.print("SyntaxErrorUnterminatedLiteral");
-        return;
-    case JSC::ParserError::SyntaxErrorRecoverable:
-        out.print("SyntaxErrorRecoverable");
-        return;
-    }
-    
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-inline void printInternal(PrintStream& out, JSC::ParserError::ErrorType type)
-{
-    switch (type) {
-    case JSC::ParserError::ErrorNone:
-        out.print("ErrorNone");
-        return;
-    case JSC::ParserError::StackOverflow:
-        out.print("StackOverflow");
-        return;
-    case JSC::ParserError::EvalError:
-        out.print("EvalError");
-        return;
-    case JSC::ParserError::OutOfMemory:
-        out.print("OutOfMemory");
-        return;
-    case JSC::ParserError::SyntaxError:
-        out.print("SyntaxError");
-        return;
-    }
-    
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
+void printInternal(PrintStream&, JSC::ParserError::SyntaxErrorType);
+void printInternal(PrintStream&, JSC::ParserError::ErrorType);
 } // namespace WTF
index 800cfa0..1761990 100644 (file)
@@ -41,7 +41,7 @@ void AsyncIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject
     ASSERT(inherits(vm, info()));
     didBecomePrototype();
 
-    JSFunction* asyncIteratorPrototypeFunction = JSFunction::create(vm, asyncIteratorPrototypeSymbolAsyncIteratorGetterCodeGenerator(vm), globalObject);
+    JSFunction* asyncIteratorPrototypeFunction = JSFunction::create(vm, asyncIteratorPrototypeSymbolAsyncIteratorGetterCodeGenerator(vm).value(), globalObject);
     putDirectWithoutTransition(vm, vm.propertyNames->asyncIteratorSymbol, asyncIteratorPrototypeFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
 }
 
index d0fd762..a6ed35a 100644 (file)
@@ -63,11 +63,11 @@ void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* g
     JSFunction* toStringFunction = JSFunction::create(vm, globalObject, 0, vm.propertyNames->toString.string(), functionProtoFuncToString);
     putDirectWithoutTransition(vm, vm.propertyNames->toString, toStringFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
 
-    *applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
-    *callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
-    putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->bind, functionPrototypeBindCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
+    *applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm).value(), static_cast<unsigned>(PropertyAttribute::DontEnum));
+    *callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm).value(), static_cast<unsigned>(PropertyAttribute::DontEnum));
+    putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->bind, functionPrototypeBindCodeGenerator(vm).value(), static_cast<unsigned>(PropertyAttribute::DontEnum));
 
-    *hasInstanceSymbolFunction = JSFunction::create(vm, functionPrototypeSymbolHasInstanceCodeGenerator(vm), globalObject);
+    *hasInstanceSymbolFunction = JSFunction::create(vm, functionPrototypeSymbolHasInstanceCodeGenerator(vm).value(), globalObject);
     putDirectWithoutTransition(vm, vm.propertyNames->hasInstanceSymbol, *hasInstanceSymbolFunction, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
 }
     
index 8f840cc..d9a9a27 100644 (file)
@@ -443,24 +443,24 @@ void JSGlobalObject::init(VM& vm)
         });
     m_arrayProtoValuesFunction.initLater(
         [] (const Initializer<JSFunction>& init) {
-            init.set(JSFunction::create(init.vm, arrayPrototypeValuesCodeGenerator(init.vm), init.owner));
+            init.set(JSFunction::create(init.vm, arrayPrototypeValuesCodeGenerator(init.vm).value(), init.owner));
         });
     m_initializePromiseFunction.initLater(
         [] (const Initializer<JSFunction>& init) {
-            init.set(JSFunction::create(init.vm, promiseOperationsInitializePromiseCodeGenerator(init.vm), init.owner));
+            init.set(JSFunction::create(init.vm, promiseOperationsInitializePromiseCodeGenerator(init.vm).value(), init.owner));
         });
 
     m_iteratorProtocolFunction.initLater(
         [] (const Initializer<JSFunction>& init) {
-            init.set(JSFunction::create(init.vm, iteratorHelpersPerformIterationCodeGenerator(init.vm), init.owner));
+            init.set(JSFunction::create(init.vm, iteratorHelpersPerformIterationCodeGenerator(init.vm).value(), init.owner));
         });
 
     m_promiseResolveFunction.initLater(
         [] (const Initializer<JSFunction>& init) {
-            init.set(JSFunction::create(init.vm, promiseConstructorResolveCodeGenerator(init.vm), init.owner));
+            init.set(JSFunction::create(init.vm, promiseConstructorResolveCodeGenerator(init.vm).value(), init.owner));
         });
 
-    m_newPromiseCapabilityFunction.set(vm, this, JSFunction::create(vm, promiseOperationsNewPromiseCapabilityCodeGenerator(vm), this));
+    m_newPromiseCapabilityFunction.set(vm, this, JSFunction::create(vm, promiseOperationsNewPromiseCapabilityCodeGenerator(vm).value(), this));
     m_functionProtoHasInstanceSymbolFunction.set(vm, this, hasInstanceSymbolFunction);
     m_throwTypeErrorGetterSetter.initLater(
         [] (const Initializer<GetterSetter>& init) {
@@ -491,7 +491,7 @@ void JSGlobalObject::init(VM& vm)
     m_functionPrototype->initRestrictedProperties(exec, this);
 
     m_speciesGetterSetter.set(vm, this, GetterSetter::create(vm, this));
-    m_speciesGetterSetter->setGetter(vm, this, JSFunction::create(vm, globalOperationsSpeciesGetterCodeGenerator(vm), this));
+    m_speciesGetterSetter->setGetter(vm, this, JSFunction::create(vm, globalOperationsSpeciesGetterCodeGenerator(vm).value(), this));
 
     m_typedArrayProto.initLater(
         [] (const Initializer<JSTypedArrayViewPrototype>& init) {
@@ -513,7 +513,7 @@ void JSGlobalObject::init(VM& vm)
         [] (LazyClassStructure::Initializer& init) { \
             init.setPrototype(JS ## type ## ArrayPrototype::create(init.vm, init.global, JS ## type ## ArrayPrototype::createStructure(init.vm, init.global, init.global->m_typedArrayProto.get(init.global)))); \
             init.setStructure(JS ## type ## Array::createStructure(init.vm, init.global, init.prototype)); \
-            init.setConstructor(JS ## type ## ArrayConstructor::create(init.vm, init.global, JS ## type ## ArrayConstructor::createStructure(init.vm, init.global, init.global->m_typedArraySuperConstructor.get(init.global)), init.prototype, ASCIILiteral(#type "Array"), typedArrayConstructorAllocate ## type ## ArrayCodeGenerator(init.vm))); \
+            init.setConstructor(JS ## type ## ArrayConstructor::create(init.vm, init.global, JS ## type ## ArrayConstructor::createStructure(init.vm, init.global, init.global->m_typedArraySuperConstructor.get(init.global)), init.prototype, ASCIILiteral(#type "Array"), typedArrayConstructorAllocate ## type ## ArrayCodeGenerator(init.vm).value())); \
             init.global->putDirectWithoutTransition(init.vm, init.vm.propertyNames->builtinNames().type ## ArrayPrivateName(), init.constructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); \
         });
     FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(INIT_TYPED_ARRAY_LATER)
@@ -837,7 +837,7 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
     JSObject* regExpSymbolReplace = asObject(m_regExpPrototype->getDirect(vm, vm.propertyNames->replaceSymbol).asCell());
     m_regExpProtoSymbolReplace.set(vm, this, regExpSymbolReplace);
 
-#define CREATE_PRIVATE_GLOBAL_FUNCTION(name, code) JSFunction* name ## PrivateFunction = JSFunction::create(vm, code ## CodeGenerator(vm), this);
+#define CREATE_PRIVATE_GLOBAL_FUNCTION(name, code) JSFunction* name ## PrivateFunction = JSFunction::create(vm, code ## CodeGenerator(vm).value(), this);
     JSC_FOREACH_BUILTIN_FUNCTION_PRIVATE_GLOBAL_NAME(CREATE_PRIVATE_GLOBAL_FUNCTION)
 #undef CREATE_PRIVATE_GLOBAL_FUNCTION
 
index 2525913..be6dc99 100644 (file)
@@ -2034,12 +2034,15 @@ bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue& resu
     return !result.isString();
 }
 
-bool JSObject::getOwnStaticPropertySlot(VM& vm, PropertyName propertyName, PropertySlot& slot)
+bool JSObject::getOwnStaticPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     for (auto* info = classInfo(vm); info; info = info->parentClass) {
         if (auto* table = info->staticPropHashTable) {
-            if (getStaticPropertySlotFromTable(vm, table->classForThis, *table, this, propertyName, slot))
+            if (getStaticPropertySlotFromTable(exec, table->classForThis, *table, this, propertyName, slot))
                 return true;
+            RETURN_IF_EXCEPTION(scope, false);
         }
     }
     return false;
@@ -2325,6 +2328,7 @@ void JSObject::reifyAllStaticProperties(ExecState* exec)
 {
     ASSERT(!staticPropertiesReified());
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     // If this object's ClassInfo has no static properties, then nothing to reify!
     // We can safely set the flag to avoid the expensive check again in the future.
@@ -2345,8 +2349,10 @@ void JSObject::reifyAllStaticProperties(ExecState* exec)
             unsigned attributes;
             auto key = Identifier::fromString(&vm, value.m_key);
             PropertyOffset offset = getDirectOffset(vm, key, attributes);
-            if (!isValidOffset(offset))
-                reifyStaticProperty(vm, hashTable->classForThis, key, value, *this);
+            if (!isValidOffset(offset)) {
+                reifyStaticProperty(vm, exec, hashTable->classForThis, key, value, *this);
+                RETURN_IF_EXCEPTION(scope, void());
+            }
         }
     }
 
index bed80df..e34a8cd 100644 (file)
@@ -94,7 +94,7 @@ class JSObject : public JSCell {
     friend class JSCell;
     friend class JSFinalObject;
     friend class MarkedBlock;
-    JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(VM&, const HashTableValue*, JSObject*, PropertyName, PropertySlot&);
+    JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState*, const HashTableValue*, JSObject*, PropertyName, PropertySlot&);
 
     enum PutMode {
         PutModePut,
@@ -1027,11 +1027,11 @@ private:
     JS_EXPORT_PRIVATE NEVER_INLINE bool putInlineSlow(ExecState*, PropertyName, JSValue, PutPropertySlot&);
 
     bool getNonIndexPropertySlot(ExecState*, PropertyName, PropertySlot&);
-    bool getOwnNonIndexPropertySlot(VM&, Structure*, PropertyName, PropertySlot&);
+    bool getOwnNonIndexPropertySlot(ExecState*, Structure*, PropertyName, PropertySlot&);
     JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, JSCell*, unsigned, PropertyOffset);
     void fillCustomGetterPropertySlot(VM&, PropertySlot&, CustomGetterSetter*, unsigned, Structure*);
 
-    JS_EXPORT_PRIVATE bool getOwnStaticPropertySlot(VM&, PropertyName, PropertySlot&);
+    JS_EXPORT_PRIVATE bool getOwnStaticPropertySlot(ExecState*, PropertyName, PropertySlot&);
     struct PropertyHashEntry {
         const HashTable* table;
         const HashTableValue* value;
@@ -1343,14 +1343,15 @@ inline JSValue JSObject::getPrototype(VM& vm, ExecState* exec)
 
 // It is safe to call this method with a PropertyName that is actually an index,
 // but if so will always return false (doesn't search index storage).
-ALWAYS_INLINE bool JSObject::getOwnNonIndexPropertySlot(VM& vm, Structure* structure, PropertyName propertyName, PropertySlot& slot)
+ALWAYS_INLINE bool JSObject::getOwnNonIndexPropertySlot(ExecState* exec, Structure* structure, PropertyName propertyName, PropertySlot& slot)
 {
+    VM& vm = exec->vm();
     unsigned attributes;
     PropertyOffset offset = structure->get(vm, propertyName, attributes);
     if (!isValidOffset(offset)) {
         if (!TypeInfo::hasStaticPropertyTable(inlineTypeFlags()))
             return false;
-        return getOwnStaticPropertySlot(vm, propertyName, slot);
+        return getOwnStaticPropertySlot(exec, propertyName, slot);
     }
     
     // getPropertySlot relies on this method never returning index properties!
@@ -1400,19 +1401,22 @@ ALWAYS_INLINE void JSObject::fillCustomGetterPropertySlot(VM& vm, PropertySlot&
 ALWAYS_INLINE bool JSObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     Structure* structure = object->structure(vm);
-    if (object->getOwnNonIndexPropertySlot(vm, structure, propertyName, slot))
+    if (object->getOwnNonIndexPropertySlot(exec, structure, propertyName, slot))
         return true;
+    RETURN_IF_EXCEPTION(scope, false);
     if (std::optional<uint32_t> index = parseIndex(propertyName))
         return getOwnPropertySlotByIndex(object, exec, index.value(), slot);
     return false;
 }
 
 // It may seem crazy to inline a function this large but it makes a big difference
-// since this is function very hot in variable lookup
+// since this function is very hot in variable lookup
 ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     auto& structureIDTable = vm.heap.structureIDTable();
     JSObject* object = this;
     while (true) {
@@ -1429,8 +1433,9 @@ ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, PropertyName prope
         }
         ASSERT(object->type() != ProxyObjectType);
         Structure* structure = structureIDTable.get(object->structureID());
-        if (object->getOwnNonIndexPropertySlot(vm, structure, propertyName, slot))
+        if (object->getOwnNonIndexPropertySlot(exec, structure, propertyName, slot))
             return true;
+        RETURN_IF_EXCEPTION(scope, false);
         // FIXME: This doesn't look like it's following the specification:
         // https://bugs.webkit.org/show_bug.cgi?id=172572
         JSValue prototype = structure->storedPrototype(object);
@@ -1631,7 +1636,7 @@ JS_EXPORT_PRIVATE NEVER_INLINE bool ordinarySetSlow(ExecState*, JSObject*, Prope
 
 #define JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(jsName, generatorName, attributes) \
     putDirectBuiltinFunctionWithoutTransition(\
-        vm, globalObject, makeIdentifier(vm, (jsName)), (generatorName)(vm), (attributes))
+        vm, globalObject, makeIdentifier(vm, (jsName)), (generatorName)(vm).value(), (attributes))
 
 // Helper for defining native getters on properties.
 #define JSC_NATIVE_INTRINSIC_GETTER(jsName, cppName, attributes, intrinsic)  \
index 892e2ca..b4b570e 100644 (file)
@@ -140,8 +140,9 @@ ALWAYS_INLINE bool JSObject::getNonIndexPropertySlot(ExecState* exec, PropertyNa
     while (true) {
         Structure* structure = structureIDTable.get(object->structureID());
         if (LIKELY(!TypeInfo::overridesGetOwnPropertySlot(object->inlineTypeFlags()))) {
-            if (object->getOwnNonIndexPropertySlot(vm, structure, propertyName, slot))
+            if (object->getOwnNonIndexPropertySlot(exec, structure, propertyName, slot))
                 return true;
+            RETURN_IF_EXCEPTION(scope, false);
         } else {
             bool hasSlot = structure->classInfo()->methodTable.getOwnPropertySlot(object, exec, propertyName, slot);
             RETURN_IF_EXCEPTION(scope, false);
index 75b0c11..87fda3a 100644 (file)
@@ -330,7 +330,7 @@ void JSTypedArrayViewPrototype::finishCreation(VM& vm, JSGlobalObject* globalObj
     toStringTagAccessor->setGetter(vm, globalObject, toStringTagFunction);
     putDirectNonIndexAccessor(vm, vm.propertyNames->toStringTagSymbol, toStringTagAccessor, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly | PropertyAttribute::Accessor);
 
-    JSFunction* valuesFunction = JSFunction::create(vm, typedArrayPrototypeValuesCodeGenerator(vm), globalObject);
+    JSFunction* valuesFunction = JSFunction::create(vm, typedArrayPrototypeValuesCodeGenerator(vm).value(), globalObject);
 
     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), valuesFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, valuesFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
index 966c71e..8eac0f9 100644 (file)
@@ -33,7 +33,7 @@ void reifyStaticAccessor(VM& vm, const HashTableValue& value, JSObject& thisObje
     if (value.accessorGetter()) {
         JSFunction* function = nullptr;
         if (value.attributes() & PropertyAttribute::Builtin)
-            function = JSFunction::create(vm, value.builtinAccessorGetterGenerator()(vm), globalObject);
+            function = JSFunction::create(vm, value.builtinAccessorGetterGenerator()(vm).value(), globalObject);
         else {
             String getterName = tryMakeString(ASCIILiteral("get "), String(*propertyName.publicName()));
             if (!getterName)
@@ -45,8 +45,10 @@ void reifyStaticAccessor(VM& vm, const HashTableValue& value, JSObject& thisObje
     thisObject.putDirectNonIndexAccessor(vm, propertyName, accessor, attributesForStructure(value.attributes()));
 }
 
-bool setUpStaticFunctionSlot(VM& vm, const ClassInfo* classInfo, const HashTableValue* entry, JSObject* thisObject, PropertyName propertyName, PropertySlot& slot)
+bool setUpStaticFunctionSlot(ExecState* exec, const ClassInfo* classInfo, const HashTableValue* entry, JSObject* thisObject, PropertyName propertyName, PropertySlot& slot)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     ASSERT(thisObject->globalObject());
     ASSERT(entry->attributes() & PropertyAttribute::BuiltinOrFunctionOrAccessorOrLazyProperty);
     unsigned attributes;
@@ -59,7 +61,8 @@ bool setUpStaticFunctionSlot(VM& vm, const ClassInfo* classInfo, const HashTable
         if (thisObject->staticPropertiesReified())
             return false;
 
-        reifyStaticProperty(vm, classInfo, propertyName, *entry, *thisObject);
+        reifyStaticProperty(vm, exec, classInfo, propertyName, *entry, *thisObject);
+        RETURN_IF_EXCEPTION(scope, false);
 
         offset = thisObject->getDirectOffset(vm, propertyName, attributes);
         if (!isValidOffset(offset)) {
index bfee51e..66e7a11 100644 (file)
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "LazyProperty.h"
+#include "ParserError.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
 #include "TypeError.h"
 #include <wtf/Assertions.h>
+#include <wtf/Expected.h>
 
 namespace JSC {
 
@@ -47,7 +49,7 @@ struct CompactHashIndex {
 // ie. typedef JSValue (*GetFunction)(ExecState*, JSObject* baseObject)
 typedef PropertySlot::GetValueFunc GetFunction;
 typedef PutPropertySlot::PutValueFunc PutFunction;
-typedef FunctionExecutable* (*BuiltinGenerator)(VM&);
+typedef Expected<FunctionExecutable*, ParserError> (*BuiltinGenerator)(VM&);
 typedef JSValue (*LazyPropertyCallback)(VM&, JSObject*);
 
 // Hash table generated by the create_hash_table script.
@@ -203,7 +205,7 @@ struct HashTable {
     }
 };
 
-JS_EXPORT_PRIVATE bool setUpStaticFunctionSlot(VM&, const ClassInfo*, const HashTableValue*, JSObject* thisObject, PropertyName, PropertySlot&);
+JS_EXPORT_PRIVATE bool setUpStaticFunctionSlot(ExecState*, const ClassInfo*, const HashTableValue*, JSObject* thisObject, PropertyName, PropertySlot&);
 JS_EXPORT_PRIVATE void reifyStaticAccessor(VM&, const HashTableValue&, JSObject& thisObject, PropertyName);
 
 inline BuiltinGenerator HashTableValue::builtinAccessorGetterGenerator() const
@@ -220,7 +222,7 @@ inline BuiltinGenerator HashTableValue::builtinAccessorSetterGenerator() const
     return reinterpret_cast<BuiltinGenerator>(m_values.value2);
 }
 
-inline bool getStaticPropertySlotFromTable(VM& vm, const ClassInfo* classInfo, const HashTable& table, JSObject* thisObject, PropertyName propertyName, PropertySlot& slot)
+inline bool getStaticPropertySlotFromTable(ExecState* exec, const ClassInfo* classInfo, const HashTable& table, JSObject* thisObject, PropertyName propertyName, PropertySlot& slot)
 {
     if (thisObject->staticPropertiesReified())
         return false;
@@ -230,7 +232,7 @@ inline bool getStaticPropertySlotFromTable(VM& vm, const ClassInfo* classInfo, c
         return false;
 
     if (entry->attributes() & PropertyAttribute::BuiltinOrFunctionOrAccessorOrLazyProperty)
-        return setUpStaticFunctionSlot(vm, classInfo, entry, thisObject, propertyName, slot);
+        return setUpStaticFunctionSlot(exec, classInfo, entry, thisObject, propertyName, slot);
 
     if (entry->attributes() & PropertyAttribute::ConstantInteger) {
         slot.setValue(thisObject, attributesForStructure(entry->attributes()), jsNumber(entry->constantInteger()));
@@ -319,13 +321,24 @@ inline bool lookupPut(ExecState* exec, PropertyName propertyName, JSObject* base
     return true;
 }
 
-inline void reifyStaticProperty(VM& vm, const ClassInfo* classInfo, const PropertyName& propertyName, const HashTableValue& value, JSObject& thisObj)
+inline void reifyStaticProperty(VM& vm, ExecState* execIfAvailable, const ClassInfo* classInfo, const PropertyName& propertyName, const HashTableValue& value, JSObject& thisObj)
 {
+    ASSERT(execIfAvailable == nullptr || &vm == &(execIfAvailable->vm()));
+
     if (value.attributes() & PropertyAttribute::Builtin) {
         if (value.attributes() & PropertyAttribute::Accessor)
             reifyStaticAccessor(vm, value, thisObj, propertyName);
-        else
-            thisObj.putDirectBuiltinFunction(vm, thisObj.globalObject(), propertyName, value.builtinGenerator()(vm), attributesForStructure(value.attributes()));
+        else {
+            Expected<FunctionExecutable*, ParserError> f = value.builtinGenerator()(vm);
+            if (f.has_value())
+                thisObj.putDirectBuiltinFunction(vm, thisObj.globalObject(), propertyName, f.value(), attributesForStructure(value.attributes()));
+            else if (execIfAvailable)
+                f.error().throwStackOverflowOrOutOfMemory(execIfAvailable);
+            else {
+                dataLogLn("Fatal parser error (probably a stack overflow), and no ExecState available for throwing a JS exception");
+                CRASH();
+            }
+        }
         return;
     }
 
@@ -400,7 +413,7 @@ inline void reifyStaticProperties(VM& vm, const ClassInfo* classInfo, const Hash
         if (!value.m_key)
             continue;
         auto key = Identifier::fromString(&vm, reinterpret_cast<const LChar*>(value.m_key), strlen(value.m_key));
-        reifyStaticProperty(vm, classInfo, key, value, thisObj);
+        reifyStaticProperty(vm, nullptr, classInfo, key, value, thisObj);
     }
 }
 
index 53568b7..fe2b6be 100644 (file)
@@ -71,7 +71,7 @@ void MapPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrivateName(), mapProtoFuncGet, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSMapGetIntrinsic);
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().setPrivateName(), mapProtoFuncSet, static_cast<unsigned>(PropertyAttribute::DontEnum), 2, JSMapSetIntrinsic);
 
-    JSFunction* entries = JSFunction::create(vm, mapPrototypeEntriesCodeGenerator(vm), globalObject);
+    JSFunction* entries = JSFunction::create(vm, mapPrototypeEntriesCodeGenerator(vm).value(), globalObject);
     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().entriesPublicName(), entries, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, entries, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Map"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
index 2934396..f2f05e3 100644 (file)
@@ -68,7 +68,7 @@ void SetPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().hasPrivateName(), setProtoFuncHas, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetHasIntrinsic);
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().addPrivateName(), setProtoFuncAdd, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetAddIntrinsic);
 
-    JSFunction* values = JSFunction::create(vm, setPrototypeValuesCodeGenerator(vm), globalObject);
+    JSFunction* values = JSFunction::create(vm, setPrototypeValuesCodeGenerator(vm).value(), globalObject);
     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), values, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().keysPublicName(), values, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, values, static_cast<unsigned>(PropertyAttribute::DontEnum));
index 77f6039..36dbd4f 100644 (file)
@@ -26,7 +26,7 @@
 #include "config.h"
 #include "JSDollarVM.h"
 
-#include "BuiltinExecutableCreator.h"
+#include "BuiltinExecutables.h"
 #include "CodeBlock.h"
 #include "DOMAttributeGetterSetter.h"
 #include "DOMJITGetterSetter.h"
@@ -1522,9 +1522,8 @@ static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     const SourceCode& source = makeSource(functionText, { });
-    JSFunction* func = JSFunction::create(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
-
-    return JSValue::encode(func);
+    auto unlinked = BuiltinExecutables::createExecutableOrCrash(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct);
+    return JSValue::encode(JSFunction::create(vm, unlinked->link(vm, source), exec->lexicalGlobalObject()));
 }
 
 static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
index 3627f41..2645453 100644 (file)
@@ -1,3 +1,26 @@
+2018-03-30  Robin Morisset  <rmorisset@apple.com>
+
+        A stack overflow in the parsing of a builtin (called by createExecutable) cause a crash instead of a catchable js exception
+        https://bugs.webkit.org/show_bug.cgi?id=184074
+        <rdar://problem/37165897>
+
+        Reviewed by Keith Miller.
+
+        I had to slightly change the type of some bindings between JSC and WebCore. No functional change intended on the WebCore side.
+
+        * bindings/js/JSReadableStreamPrivateConstructors.cpp:
+        (WebCore::JSBuiltinReadableStreamDefaultReaderPrivateConstructor::initializeExecutable):
+        (WebCore::JSBuiltinReadableStreamDefaultControllerPrivateConstructor::initializeExecutable):
+        (WebCore::JSBuiltinReadableByteStreamControllerPrivateConstructor::initializeExecutable):
+        (WebCore::JSBuiltinReadableStreamBYOBReaderPrivateConstructor::initializeExecutable):
+        (WebCore::JSBuiltinReadableStreamBYOBRequestPrivateConstructor::initializeExecutable):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateConstructorHelperMethods):
+        * bindings/scripts/test/JS/JSTestClassWithJSBuiltinConstructor.cpp:
+        (WebCore::JSTestClassWithJSBuiltinConstructorConstructor::initializeExecutable):
+        * bindings/scripts/test/JS/JSTestJSBuiltinConstructor.cpp:
+        (WebCore::JSTestJSBuiltinConstructorConstructor::initializeExecutable):
+
 2018-03-29  Antoine Quint  <graouts@apple.com>
 
         [Web Animations] Correctly obtain the timing function for a given keyframe
index ca97e96..14c2bcd 100644 (file)
@@ -124,27 +124,27 @@ template<> const ClassInfo JSBuiltinReadableStreamBYOBRequestPrivateConstructor:
 
 template<> FunctionExecutable* JSBuiltinReadableStreamDefaultReaderPrivateConstructor::initializeExecutable(JSC::VM& vm)
 {
-    return readableStreamInternalsPrivateInitializeReadableStreamDefaultReaderCodeGenerator(vm);
+    return readableStreamInternalsPrivateInitializeReadableStreamDefaultReaderCodeGenerator(vm).value();
 }
 
 template<> FunctionExecutable* JSBuiltinReadableStreamDefaultControllerPrivateConstructor::initializeExecutable(JSC::VM& vm)
 {
-    return readableStreamInternalsPrivateInitializeReadableStreamDefaultControllerCodeGenerator(vm);
+    return readableStreamInternalsPrivateInitializeReadableStreamDefaultControllerCodeGenerator(vm).value();
 }
 
 template<> FunctionExecutable* JSBuiltinReadableByteStreamControllerPrivateConstructor::initializeExecutable(JSC::VM& vm)
 {
-    return readableByteStreamInternalsPrivateInitializeReadableByteStreamControllerCodeGenerator(vm);
+    return readableByteStreamInternalsPrivateInitializeReadableByteStreamControllerCodeGenerator(vm).value();
 }
 
 template<> FunctionExecutable* JSBuiltinReadableStreamBYOBReaderPrivateConstructor::initializeExecutable(JSC::VM& vm)
 {
-    return readableByteStreamInternalsPrivateInitializeReadableStreamBYOBReaderCodeGenerator(vm);
+    return readableByteStreamInternalsPrivateInitializeReadableStreamBYOBReaderCodeGenerator(vm).value();
 }
 
 template<> FunctionExecutable* JSBuiltinReadableStreamBYOBRequestPrivateConstructor::initializeExecutable(JSC::VM& vm)
 {
-    return readableByteStreamInternalsPrivateInitializeReadableStreamBYOBRequestCodeGenerator(vm);
+    return readableByteStreamInternalsPrivateInitializeReadableStreamBYOBRequestCodeGenerator(vm).value();
 }
 
 JSObject* createReadableStreamDefaultReaderPrivateConstructor(VM& vm, JSDOMGlobalObject& globalObject)
index c4f5128..63b0593 100644 (file)
@@ -7173,7 +7173,7 @@ sub GenerateConstructorHelperMethods
     if (IsJSBuiltinConstructor($interface)) {
         push(@$outputArray, "template<> FunctionExecutable* ${constructorClassName}::initializeExecutable(VM& vm)\n");
         push(@$outputArray, "{\n");
-        push(@$outputArray, "    return " . GetJSBuiltinFunctionNameFromString($interface->type->name, "initialize" . $interface->type->name) . "(vm);\n");
+        push(@$outputArray, "    return " . GetJSBuiltinFunctionNameFromString($interface->type->name, "initialize" . $interface->type->name) . "(vm).value();\n");
         push(@$outputArray, "}\n");
         push(@$outputArray, "\n");
     }
index 1ac6eab..e0b1608 100644 (file)
@@ -82,7 +82,7 @@ template<> void JSTestClassWithJSBuiltinConstructorConstructor::initializeProper
 
 template<> FunctionExecutable* JSTestClassWithJSBuiltinConstructorConstructor::initializeExecutable(VM& vm)
 {
-    return testClassWithJSBuiltinConstructorInitializeTestClassWithJSBuiltinConstructorCodeGenerator(vm);
+    return testClassWithJSBuiltinConstructorInitializeTestClassWithJSBuiltinConstructorCodeGenerator(vm).value();
 }
 
 template<> const ClassInfo JSTestClassWithJSBuiltinConstructorConstructor::s_info = { "TestClassWithJSBuiltinConstructor", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestClassWithJSBuiltinConstructorConstructor) };
index e2ae5bd..8253bab 100644 (file)
@@ -91,7 +91,7 @@ template<> void JSTestJSBuiltinConstructorConstructor::initializeProperties(VM&
 
 template<> FunctionExecutable* JSTestJSBuiltinConstructorConstructor::initializeExecutable(VM& vm)
 {
-    return testJSBuiltinConstructorInitializeTestJSBuiltinConstructorCodeGenerator(vm);
+    return testJSBuiltinConstructorInitializeTestJSBuiltinConstructorCodeGenerator(vm).value();
 }
 
 template<> const ClassInfo JSTestJSBuiltinConstructorConstructor::s_info = { "TestJSBuiltinConstructor", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestJSBuiltinConstructorConstructor) };