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.

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::createWithLength` is not greater than JSBigInt::maxLength.
When the length is greater than maxLength, we then throw OOM
exception.
This required 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/206341@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238132 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
caiolima committed Nov 13, 2018
1 parent d5aad7c commit cf781820858f2fb23271c6a42b6eeb7f28cdfed9
@@ -1,3 +1,12 @@
2018-11-13 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.

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

2018-11-08 Ross Kirsling <ross.kirsling@sony.com>

U+180E is no longer a whitespace character
@@ -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 *= 2n;
}

return out;
}

let a = lshift(16384 * 63);
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-13 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.

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::createWithLength` is not greater than JSBigInt::maxLength.
When the length is greater than maxLength, we then throw OOM
exception.
This required 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-12 Devin Rousso <drousso@apple.com>

Web Inspector: Network: show secure certificate details per-request
@@ -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 cf78182

Please sign in to comment.