Skip to content
Permalink
Browse files
[BigInt] JSBigInt::createWithLength should throw when length is great…
…er than JSBigInt::maxLength

https://bugs.webkit.org/show_bug.cgi?id=190836

Reviewed by Saam Barati and Yusuke Suzuki.

JSTests:

* stress/big-int-out-of-memory-tests.js: Added.

Source/JavaScriptCore:

In this patch we are creating a new method called `JSBigInt::createWithLengthUnchecked`
where we allocate a BigInt trusting the length received as argument.
With this additional method, we now check if length passed to
`JSBigInt::tryCreateWithLength` is not greater than JSBigInt::maxLength.
When the length is greater than JSBigInt::maxLength, we then throw OOM
exception.
This required us to change the interface of some JSBigInt operations to
receive `ExecState*` instead of `VM&`. We changed only operations that
can throw because of OOM.
We beleive that this approach of throwing instead of finishing the
execution abruptly is better because JS programs can catch such
exception and handle this issue properly.

* dfg/DFGOperations.cpp:
* jit/JITOperations.cpp:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/JSBigInt.cpp:
(JSC::JSBigInt::createZero):
(JSC::JSBigInt::tryCreateWithLength):
(JSC::JSBigInt::createWithLengthUnchecked):
(JSC::JSBigInt::createFrom):
(JSC::JSBigInt::multiply):
(JSC::JSBigInt::divide):
(JSC::JSBigInt::copy):
(JSC::JSBigInt::unaryMinus):
(JSC::JSBigInt::remainder):
(JSC::JSBigInt::add):
(JSC::JSBigInt::sub):
(JSC::JSBigInt::bitwiseAnd):
(JSC::JSBigInt::bitwiseOr):
(JSC::JSBigInt::bitwiseXor):
(JSC::JSBigInt::absoluteAdd):
(JSC::JSBigInt::absoluteSub):
(JSC::JSBigInt::absoluteDivWithDigitDivisor):
(JSC::JSBigInt::absoluteDivWithBigIntDivisor):
(JSC::JSBigInt::absoluteLeftShiftAlwaysCopy):
(JSC::JSBigInt::absoluteBitwiseOp):
(JSC::JSBigInt::absoluteAddOne):
(JSC::JSBigInt::absoluteSubOne):
(JSC::JSBigInt::toStringGeneric):
(JSC::JSBigInt::rightTrim):
(JSC::JSBigInt::allocateFor):
(JSC::JSBigInt::createWithLength): Deleted.
* runtime/JSBigInt.h:
* runtime/Operations.cpp:
(JSC::jsAddSlowCase):
* runtime/Operations.h:
(JSC::jsSub):
(JSC::jsMul):


Canonical link: https://commits.webkit.org/206597@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238425 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
caiolima committed Nov 21, 2018
1 parent b85fa30 commit 5a1e0a0a9762616f76313144c5c904aa659b78bd
Showing 10 changed files with 303 additions and 99 deletions.
@@ -1,3 +1,12 @@
2018-11-21 Caio Lima <ticaiolima@gmail.com>

[BigInt] JSBigInt::createWithLength should throw when length is greater than JSBigInt::maxLength
https://bugs.webkit.org/show_bug.cgi?id=190836

Reviewed by Saam Barati and Yusuke Suzuki.

* stress/big-int-out-of-memory-tests.js: Added.

2018-11-20 Mark Lam <mark.lam@apple.com>

Remove invalid assertion in VMTraps::SignalSender's SignalAction.
@@ -0,0 +1,63 @@
//@ runDefault("--useBigInt=true", "--useDFGJIT=false")

function assert(a, message) {
if (!a)
throw new Error(message);
}

function lshift(y) {
let out = 1n;
for (let i = 0; i < y; i++) {
out *= 340282366920938463463374607431768211456n;
}

return out;
}

let a = lshift(8064);
for (let i = 0; i < 256; i++) {
a *= 18446744073709551615n;
}

try {
let b = a + 1n;
assert(false, "Should throw OutOfMemoryError, but executed without exception");
} catch(e) {
assert(e.message == "Out of memory", "Expected OutOfMemoryError, but got: " + e);
}

try {
let b = a - (-1n);
assert(false, "Should throw OutOfMemoryError, but executed without exception");
} catch(e) {
assert(e.message == "Out of memory", "Expected OutOfMemoryError, but got: " + e);
}

try {
let b = a * (-1n);
assert(false, "Should throw OutOfMemoryError, but executed without exception");
} catch(e) {
assert(e.message == "Out of memory", "Expected OutOfMemoryError, but got: " + e);
}

try {
let b = a / a;
assert(false, "Should throw OutOfMemoryError, but executed without exception");
} catch(e) {
assert(e.message == "Out of memory", "Expected OutOfMemoryError, but got: " + e);
}

try {
let b = -a & -1n;
assert(false, "Should throw OutOfMemoryError, but executed without exception");
} catch(e) {
assert(e.message == "Out of memory", "Expected OutOfMemoryError, but got: " + e);
}

try {
let b = a ^ -1n;
assert(false, "Should throw OutOfMemoryError, but executed without exception");
} catch(e) {
assert(e.message == "Out of memory", "Expected OutOfMemoryError, but got: " + e);
}

@@ -1,3 +1,61 @@
2018-11-21 Caio Lima <ticaiolima@gmail.com>

[BigInt] JSBigInt::createWithLength should throw when length is greater than JSBigInt::maxLength
https://bugs.webkit.org/show_bug.cgi?id=190836

Reviewed by Saam Barati and Yusuke Suzuki.

In this patch we are creating a new method called `JSBigInt::createWithLengthUnchecked`
where we allocate a BigInt trusting the length received as argument.
With this additional method, we now check if length passed to
`JSBigInt::tryCreateWithLength` is not greater than JSBigInt::maxLength.
When the length is greater than JSBigInt::maxLength, we then throw OOM
exception.
This required us to change the interface of some JSBigInt operations to
receive `ExecState*` instead of `VM&`. We changed only operations that
can throw because of OOM.
We beleive that this approach of throwing instead of finishing the
execution abruptly is better because JS programs can catch such
exception and handle this issue properly.

* dfg/DFGOperations.cpp:
* jit/JITOperations.cpp:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/JSBigInt.cpp:
(JSC::JSBigInt::createZero):
(JSC::JSBigInt::tryCreateWithLength):
(JSC::JSBigInt::createWithLengthUnchecked):
(JSC::JSBigInt::createFrom):
(JSC::JSBigInt::multiply):
(JSC::JSBigInt::divide):
(JSC::JSBigInt::copy):
(JSC::JSBigInt::unaryMinus):
(JSC::JSBigInt::remainder):
(JSC::JSBigInt::add):
(JSC::JSBigInt::sub):
(JSC::JSBigInt::bitwiseAnd):
(JSC::JSBigInt::bitwiseOr):
(JSC::JSBigInt::bitwiseXor):
(JSC::JSBigInt::absoluteAdd):
(JSC::JSBigInt::absoluteSub):
(JSC::JSBigInt::absoluteDivWithDigitDivisor):
(JSC::JSBigInt::absoluteDivWithBigIntDivisor):
(JSC::JSBigInt::absoluteLeftShiftAlwaysCopy):
(JSC::JSBigInt::absoluteBitwiseOp):
(JSC::JSBigInt::absoluteAddOne):
(JSC::JSBigInt::absoluteSubOne):
(JSC::JSBigInt::toStringGeneric):
(JSC::JSBigInt::rightTrim):
(JSC::JSBigInt::allocateFor):
(JSC::JSBigInt::createWithLength): Deleted.
* runtime/JSBigInt.h:
* runtime/Operations.cpp:
(JSC::jsAddSlowCase):
* runtime/Operations.h:
(JSC::jsSub):
(JSC::jsMul):

2018-11-20 Mark Lam <mark.lam@apple.com>

Remove invalid assertion in VMTraps::SignalSender's SignalAction.
@@ -349,7 +349,7 @@ EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValu

if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
JSBigInt* result = JSBigInt::bitwiseAnd(*vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
JSBigInt* result = JSBigInt::bitwiseAnd(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
RETURN_IF_EXCEPTION(scope, encodedJSValue());
return JSValue::encode(result);
}
@@ -376,7 +376,7 @@ EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue

if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
JSBigInt* result = JSBigInt::bitwiseOr(*vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
JSBigInt* result = JSBigInt::bitwiseOr(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
RETURN_IF_EXCEPTION(scope, encodedJSValue());
return JSValue::encode(result);
}
@@ -1294,7 +1294,7 @@ JSCell* JIT_OPERATION operationSubBigInt(ExecState* exec, JSCell* op1, JSCell* o
JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);

return JSBigInt::sub(*vm, leftOperand, rightOperand);
return JSBigInt::sub(exec, leftOperand, rightOperand);
}

JSCell* JIT_OPERATION operationBitAndBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
@@ -1305,7 +1305,7 @@ JSCell* JIT_OPERATION operationBitAndBigInt(ExecState* exec, JSCell* op1, JSCell
JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);

return JSBigInt::bitwiseAnd(*vm, leftOperand, rightOperand);
return JSBigInt::bitwiseAnd(exec, leftOperand, rightOperand);
}

JSCell* JIT_OPERATION operationAddBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
@@ -1316,7 +1316,7 @@ JSCell* JIT_OPERATION operationAddBigInt(ExecState* exec, JSCell* op1, JSCell* o
JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);

return JSBigInt::add(*vm, leftOperand, rightOperand);
return JSBigInt::add(exec, leftOperand, rightOperand);
}

JSCell* JIT_OPERATION operationBitOrBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
@@ -1327,7 +1327,7 @@ JSCell* JIT_OPERATION operationBitOrBigInt(ExecState* exec, JSCell* op1, JSCell*
JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);

return JSBigInt::bitwiseOr(*vm, leftOperand, rightOperand);
return JSBigInt::bitwiseOr(exec, leftOperand, rightOperand);
}

size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, JSCell* op1, JSCell* op2)
@@ -2766,10 +2766,8 @@ EncodedJSValue JIT_OPERATION operationArithNegateOptimize(ExecState* exec, Encod
JSValue primValue = operand.toPrimitive(exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());

if (primValue.isBigInt()) {
JSBigInt* result = JSBigInt::unaryMinus(vm, asBigInt(primValue));
return JSValue::encode(result);
}
if (primValue.isBigInt())
return JSValue::encode(JSBigInt::unaryMinus(vm, asBigInt(primValue)));

double number = primValue.toNumber(exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
@@ -563,7 +563,8 @@ SLOW_PATH_DECL(slow_path_sub)

if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
JSBigInt* result = JSBigInt::sub(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
JSBigInt* result = JSBigInt::sub(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
CHECK_EXCEPTION();
RETURN_WITH_PROFILING(result, {
updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
});
@@ -699,7 +700,7 @@ SLOW_PATH_DECL(slow_path_bitand)
CHECK_EXCEPTION();
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
JSBigInt* result = JSBigInt::bitwiseAnd(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
JSBigInt* result = JSBigInt::bitwiseAnd(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
CHECK_EXCEPTION();
RETURN_PROFILED(result);
}
@@ -720,7 +721,7 @@ SLOW_PATH_DECL(slow_path_bitor)
CHECK_EXCEPTION();
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
JSBigInt* result = JSBigInt::bitwiseOr(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
JSBigInt* result = JSBigInt::bitwiseOr(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
CHECK_EXCEPTION();
RETURN_PROFILED(result);
}
@@ -741,7 +742,7 @@ SLOW_PATH_DECL(slow_path_bitxor)
CHECK_EXCEPTION();
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
JSBigInt* result = JSBigInt::bitwiseXor(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
JSBigInt* result = JSBigInt::bitwiseXor(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
CHECK_EXCEPTION();
RETURN(result);
}

0 comments on commit 5a1e0a0

Please sign in to comment.