Commit cf05e4ca authored by Michael Achenbach's avatar Michael Achenbach Committed by Commit Bot

Make using natives for fuzzing more permissive

This makes creating whitelisted runtime functions more permissive on
fuzzers (when --allow-natives-for-fuzzing is passed).

- Runtime functions with too few arguments are replaced with undefined.
- Superfluous arguments are ignored.

This reduces syntax-error rate on fuzzers. Also prevents
dcheck errors when fuzzing debug builds and fuzzers use too many
arguments for runtime functions.

Bug: chromium:1044942
Change-Id: I23b45398421c50bc82d1e8bfdf019f565253db96
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2039352
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66202}
parent f925176e
......@@ -356,17 +356,16 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
const Runtime::Function* function =
Runtime::FunctionForName(name->raw_data(), name->length());
// Be more premissive when fuzzing. Intrinsics are not supported.
if (FLAG_allow_natives_for_fuzzing) {
return NewV8RuntimeFunctionForFuzzing(function, args, pos);
}
if (function != nullptr) {
// Check for possible name clash.
DCHECK_EQ(Context::kNotFound,
Context::IntrinsicIndexForName(name->raw_data(), name->length()));
// When fuzzing, only allow whitelisted runtime functions.
if (FLAG_allow_natives_for_fuzzing &&
!Runtime::IsWhitelistedForFuzzing(function->function_id)) {
return factory()->NewUndefinedLiteral(kNoSourcePosition);
}
// Check that the expected number of arguments are being passed.
if (function->nargs != -1 && function->nargs != args.length()) {
ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
......@@ -376,11 +375,6 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
return factory()->NewCallRuntime(function, args, pos);
}
// Intrinsics are not supported for fuzzing.
if (FLAG_allow_natives_for_fuzzing) {
return factory()->NewUndefinedLiteral(kNoSourcePosition);
}
int context_index =
Context::IntrinsicIndexForName(name->raw_data(), name->length());
......@@ -393,6 +387,34 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
return factory()->NewCallRuntime(context_index, args, pos);
}
// More permissive runtime-function creation on fuzzers.
Expression* Parser::NewV8RuntimeFunctionForFuzzing(
const Runtime::Function* function, const ScopedPtrList<Expression>& args,
int pos) {
CHECK(FLAG_allow_natives_for_fuzzing);
// Intrinsics are not supported for fuzzing. Only allow whitelisted runtime
// functions. Also prevent later errors due to too few arguments and just
// ignore this call.
if (function == nullptr ||
!Runtime::IsWhitelistedForFuzzing(function->function_id) ||
function->nargs > args.length()) {
return factory()->NewUndefinedLiteral(kNoSourcePosition);
}
// Flexible number of arguments permitted.
if (function->nargs == -1) {
return factory()->NewCallRuntime(function, args, pos);
}
// Otherwise ignore superfluous arguments.
ScopedPtrList<Expression> permissive_args(pointer_buffer());
for (int i = 0; i < function->nargs; i++) {
permissive_args.Add(args.at(i));
}
return factory()->NewCallRuntime(function, permissive_args, pos);
}
Parser::Parser(ParseInfo* info)
: ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
info->extension(), info->GetOrCreateAstValueFactory(),
......
......@@ -833,6 +833,10 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Expression* NewV8Intrinsic(const AstRawString* name,
const ScopedPtrList<Expression>& args, int pos);
Expression* NewV8RuntimeFunctionForFuzzing(
const Runtime::Function* function, const ScopedPtrList<Expression>& args,
int pos);
V8_INLINE Statement* NewThrowStatement(Expression* exception, int pos) {
return factory()->NewExpressionStatement(
factory()->NewThrow(exception, pos), pos);
......
......@@ -10,10 +10,17 @@
assertEquals(undefined, %GetOptimizationStatus(function (){}));
// Blacklisted intrinsics can have wrong arguments.
%GetOptimizationStatus(1, 2, 3, 4);
assertEquals(undefined, %GetOptimizationStatus(1, 2, 3, 4));
// We don't care if an intrinsic actually exists.
assertEquals(undefined, %FooBar());
// Check whitelisted intrinsic.
assertNotEquals(undefined, %IsBeingInterpreted());
// Whitelisted runtime functions with too few args are ignored.
assertEquals(undefined, %DeoptimizeFunction());
// Superfluous arguments are ignored.
%DeoptimizeFunction(function() {}, undefined);
assertNotEquals(undefined, %IsBeingInterpreted(1, 2, 3));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment