[ESNext] Enables a way to throw an error on ByteCodeGenerator step
https://bugs.webkit.org/show_bug.cgi?id=180139

Reviewed by Mark Lam.

JSTests:

* stress/eval-huge-big-int-memory-overflow.js: Added.

Source/JavaScriptCore:

This is a minimal fix that only deals with overly huge BigInts.
A more thorough solution is rather low priority (since it has neither securities nor performance impact).

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::addBigIntConstant):
* bytecompiler/NodesCodegen.cpp:
(JSC::ConstantNode::emitBytecode):
* runtime/JSBigInt.cpp:
(JSC::JSBigInt::parseInt):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@254738 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog
index 3dbb900..8080fb7 100644
--- a/JSTests/ChangeLog
+++ b/JSTests/ChangeLog
@@ -1,3 +1,12 @@
+2020-01-16  Robin Morisset  <rmorisset@apple.com>
+
+        [ESNext] Enables a way to throw an error on ByteCodeGenerator step
+        https://bugs.webkit.org/show_bug.cgi?id=180139
+
+        Reviewed by Mark Lam.
+
+        * stress/eval-huge-big-int-memory-overflow.js: Added.
+
 2020-01-16  Keith Miller  <keith_miller@apple.com>
 
         Reland bytecode checkpoints since bugs have been fixed
diff --git a/JSTests/stress/eval-huge-big-int-memory-overflow.js b/JSTests/stress/eval-huge-big-int-memory-overflow.js
new file mode 100644
index 0000000..13f488d
--- /dev/null
+++ b/JSTests/stress/eval-huge-big-int-memory-overflow.js
@@ -0,0 +1,5 @@
+//@ if $memoryLimited then skip else runDefault end
+
+try {
+    eval('1'.repeat(2**20)+'n');
+} catch {}
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 215f060..d07ac24 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,20 @@
+2020-01-16  Robin Morisset  <rmorisset@apple.com>
+
+        [ESNext] Enables a way to throw an error on ByteCodeGenerator step
+        https://bugs.webkit.org/show_bug.cgi?id=180139
+
+        Reviewed by Mark Lam.
+
+        This is a minimal fix that only deals with overly huge BigInts.
+        A more thorough solution is rather low priority (since it has neither securities nor performance impact).
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::addBigIntConstant):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ConstantNode::emitBytecode):
+        * runtime/JSBigInt.cpp:
+        (JSC::JSBigInt::parseInt):
+
 2020-01-16  Keith Miller  <keith_miller@apple.com>
 
         Reland bytecode checkpoints since bugs have been fixed
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index c1f8639..e322205 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -2880,10 +2880,7 @@
         auto scope = DECLARE_CATCH_SCOPE(vm());
         auto parseIntSign = sign ? JSBigInt::ParseIntSign::Signed : JSBigInt::ParseIntSign::Unsigned;
         JSBigInt* bigIntInMap = JSBigInt::parseInt(nullptr, vm(), identifier.string(), radix, JSBigInt::ErrorParseMode::ThrowExceptions, parseIntSign);
-        // FIXME: [ESNext] Enables a way to throw an error on ByteCodeGenerator step
-        // https://bugs.webkit.org/show_bug.cgi?id=180139
         scope.assertNoException();
-        RELEASE_ASSERT(bigIntInMap);
         addConstantValue(bigIntInMap);
 
         return bigIntInMap;
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index b61200a..ab96d95 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -119,7 +119,12 @@
 {
     if (dst == generator.ignoredResult())
         return 0;
-    return generator.emitLoad(dst, jsValue(generator));
+    JSValue constant = jsValue(generator);
+    if (UNLIKELY(!constant)) {
+        // This can happen if we try to parse a string or BigInt so enormous that we OOM.
+        return generator.emitThrowExpressionTooDeepException();
+    }
+    return generator.emitLoad(dst, constant);
 }
 
 JSValue StringNode::jsValue(BytecodeGenerator& generator) const
diff --git a/Source/JavaScriptCore/runtime/JSBigInt.cpp b/Source/JavaScriptCore/runtime/JSBigInt.cpp
index 0af9342..9c34544 100644
--- a/Source/JavaScriptCore/runtime/JSBigInt.cpp
+++ b/Source/JavaScriptCore/runtime/JSBigInt.cpp
@@ -1875,6 +1875,9 @@
 
     JSBigInt* result = allocateFor(globalObject, vm, radix, length - p);
     RETURN_IF_EXCEPTION(scope, nullptr);
+    // result can still be null if we don't have access to global object, as allocateFor cannot throw an exception in that case.
+    if (!result)
+        return nullptr;
 
     result->initialize(InitializationType::WithZero);