Currently FuzzIL's object literals and class definitions to not allow executing arbitrary expressions for property values and computed property names. Instead, these operations simply require an existing input:
BeginObjectLiteral
ObjectLiteralAddComputedProperty v3, v27
EndObjectLiteral
As such, the values need to be computed first, and so during compilation, code such as
let o = {
[Symbol.toPrimitive]: function () { return this.foo; },
foo: "bar" + "baz",
};
Becomes
function f0() {
return this.foo;
}
const v4 = Symbol.toPrimitive;
const v7 = "bar" + "baz";
const o8 = {
[v4]: f0,
"foo": v7,
};
While somewhat harder to read, this is semantically identical. However, there are cases where this behavior is observable, for example with a test case such as:
class X {
static i = 0;
static j = X.i + 1;
}
console.log(X);
Moreover, there have been bugs in the past where it was necessary to compute expressions inside class/object literals. While Fuzzilli is not the ideal fuzzer for such types of bugs, adding support for these features would still help find similar bugs in the future.
I think the proper way to support this would be by converting the single instructions into block instructions such as
BeginObjectLiteral
BeginObjectLiteralComputedPropertyName
v11 <- CreateNamedVariable "Symbol"
v12 <- GetProperty v11, "toPrimitive"
BeginObjectLiteralComputedPropertyValue v12
v13 <- BeginPlainFunction
...
EndPlainFunction
EndObjectLiteralComputedProperty v13
EndObjectLiteral
Which would then lift to
let o = {
[Symbol.toPrimitive]: function() { ... },
};
This is adds a bit of bloat, but on the other hand is really flexible and allows us to perform any computation in these contexts. We already support lifting into a "single-expression" context so we can reuse all of that logic in the lifter, and so this change should mostly just affect the FuzzIL operations.
Currently FuzzIL's object literals and class definitions to not allow executing arbitrary expressions for property values and computed property names. Instead, these operations simply require an existing input:
As such, the values need to be computed first, and so during compilation, code such as
Becomes
While somewhat harder to read, this is semantically identical. However, there are cases where this behavior is observable, for example with a test case such as:
Moreover, there have been bugs in the past where it was necessary to compute expressions inside class/object literals. While Fuzzilli is not the ideal fuzzer for such types of bugs, adding support for these features would still help find similar bugs in the future.
I think the proper way to support this would be by converting the single instructions into block instructions such as
Which would then lift to
This is adds a bit of bloat, but on the other hand is really flexible and allows us to perform any computation in these contexts. We already support lifting into a "single-expression" context so we can reuse all of that logic in the lifter, and so this change should mostly just affect the FuzzIL operations.