mirror of https://github.com/google/oss-fuzz.git
[typescript] improve harness that has hopefully no timeout issues (#10612)
These harnesses seem to run a lot better and don't need the adjusted `--timeout` option any more from what I was able to observe. Also, the tested API increased a bit.
This commit is contained in:
parent
fdcf8b1d21
commit
9fca6817ed
|
@ -20,7 +20,6 @@ npm install
|
|||
npm install --save-dev @jazzer.js/core
|
||||
|
||||
# Build Fuzzers.
|
||||
# Fuzzing is kinda slow and a resource hog so we have to adjust the timeout and
|
||||
# memory limit to satisfy libfuzzer
|
||||
compile_javascript_fuzzer TypeScript fuzz_ast -i typescript --sync --timeout=30000 -- -rss_limit_mb=4096
|
||||
compile_javascript_fuzzer TypeScript fuzz_compiler -i typescript --sync --timeout=30000 -- -rss_limit_mb=4096
|
||||
# Fuzzing TS is a resource hog so we have to adjust the rss limit a bit
|
||||
compile_javascript_fuzzer TypeScript fuzz_ast -i typescript -- -rss_limit_mb=4096
|
||||
compile_javascript_fuzzer TypeScript fuzz_compiler -i typescript --sync -- -rss_limit_mb=4096
|
||||
|
|
|
@ -14,17 +14,16 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const { FuzzedDataProvider } = require('@jazzer.js/core');
|
||||
const ts = require('typescript');
|
||||
const { FuzzedDataProvider } = require("@jazzer.js/core");
|
||||
const ts = require("typescript");
|
||||
|
||||
module.exports.fuzz = function(data) {
|
||||
module.exports.fuzz = async function(data) {
|
||||
const provider = new FuzzedDataProvider(data);
|
||||
|
||||
try {
|
||||
const fileName = provider.consumeString(10) + '.ts';
|
||||
const fileName = provider.consumeString(10) + ".ts";
|
||||
const fileContents = provider.consumeString(1000);
|
||||
|
||||
// Parse the source file
|
||||
const sourceFile = ts.createSourceFile(
|
||||
fileName,
|
||||
fileContents,
|
||||
|
@ -32,9 +31,12 @@ module.exports.fuzz = function(data) {
|
|||
/*setParentNodes */ true
|
||||
);
|
||||
|
||||
// Get the diagnostics for the source file
|
||||
// Fuzzing parsing and lexing
|
||||
ts.getPreEmitDiagnostics(sourceFile);
|
||||
|
||||
// Fuzzing type inference
|
||||
ts.getTypeChecker(sourceFile);
|
||||
|
||||
// Consume a boolean and use it to randomly remove a node from the AST
|
||||
const shouldRemoveNode = provider.consumeBoolean();
|
||||
if (shouldRemoveNode) {
|
||||
|
@ -75,13 +77,124 @@ module.exports.fuzz = function(data) {
|
|||
ts.replaceNode(nodeToReplace, newNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Fuzzing transformation and emit
|
||||
const transformed = ts.transform(sourceFile, [/* transformation functions */]);
|
||||
const transformedSourceFile = transformed.transformed[0];
|
||||
|
||||
// Fuzzing language features
|
||||
const shouldFuzzLanguageFeature = provider.consumeBoolean();
|
||||
if (shouldFuzzLanguageFeature) {
|
||||
// Fuzzing classes
|
||||
const classDeclaration = ts.createClassDeclaration(
|
||||
/* decorators */[],
|
||||
/* modifiers */[],
|
||||
provider.consumeString(10),
|
||||
/* typeParameters */[],
|
||||
/* heritageClauses */[],
|
||||
/* members */[]
|
||||
);
|
||||
ts.addDeclaration(sourceFile, classDeclaration);
|
||||
|
||||
// Fuzzing interfaces
|
||||
const interfaceDeclaration = ts.createInterfaceDeclaration(
|
||||
/* decorators */[],
|
||||
/* modifiers */[],
|
||||
provider.consumeString(10),
|
||||
/* typeParameters */[],
|
||||
/* heritageClauses */[],
|
||||
/* members */[]
|
||||
);
|
||||
ts.addDeclaration(sourceFile, interfaceDeclaration);
|
||||
|
||||
// Fuzzing modules
|
||||
const moduleDeclaration = ts.createModuleDeclaration(
|
||||
/* decorators */[],
|
||||
/* modifiers */[],
|
||||
ts.createIdentifier(provider.consumeString(10)),
|
||||
ts.createModuleBlock([]),
|
||||
ts.NodeFlags.Namespace
|
||||
);
|
||||
ts.addDeclaration(sourceFile, moduleDeclaration);
|
||||
|
||||
// Fuzzing generics
|
||||
const genericFunctionDeclaration = ts.createFunctionDeclaration(
|
||||
/* decorators */[],
|
||||
/* modifiers */[],
|
||||
/* asteriskToken */ undefined,
|
||||
provider.consumeString(10),
|
||||
/* typeParameters */[
|
||||
ts.createTypeParameterDeclaration(
|
||||
ts.createIdentifier(provider.consumeString(10)),
|
||||
/* constraint */ undefined,
|
||||
/* defaultType */ undefined
|
||||
)
|
||||
],
|
||||
/* parameters */[],
|
||||
/* type */ undefined,
|
||||
/* body */ undefined
|
||||
);
|
||||
ts.addDeclaration(sourceFile, genericFunctionDeclaration);
|
||||
|
||||
// Fuzzing decorators
|
||||
const decorator = ts.createDecorator(
|
||||
ts.createCall(
|
||||
ts.createIdentifier(provider.consumeString(10)),
|
||||
/* typeArguments */[],
|
||||
/* argumentsArray */[]
|
||||
)
|
||||
);
|
||||
ts.addDeclaration(sourceFile, decorator);
|
||||
|
||||
// Fuzzing async/await
|
||||
const asyncFunctionDeclaration = ts.createFunctionDeclaration(
|
||||
/* decorators */[],
|
||||
/* modifiers */[],
|
||||
/* asteriskToken */ undefined,
|
||||
provider.consumeString(10),
|
||||
/* typeParameters */[],
|
||||
/* parameters */[],
|
||||
/* type */ undefined,
|
||||
ts.createBlock([
|
||||
ts.createAwaitExpression(
|
||||
ts.createCall(
|
||||
ts.createIdentifier(provider.consumeString(10)),
|
||||
/* typeArguments */[],
|
||||
/* argumentsArray */[]
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
ts.addDeclaration(sourceFile, asyncFunctionDeclaration);
|
||||
}
|
||||
|
||||
// Fuzzing compiler options
|
||||
const compilerOptions = {
|
||||
target: ts.ScriptTarget.ES5,
|
||||
module: ts.ModuleKind.CommonJS,
|
||||
strict: provider.consumeBoolean(),
|
||||
// ...
|
||||
};
|
||||
const program = ts.createProgram([fileName], compilerOptions);
|
||||
program.emit();
|
||||
|
||||
// Fuzzing API functions
|
||||
const shouldFuzzApiFunction = provider.consumeBoolean();
|
||||
if (shouldFuzzApiFunction) {
|
||||
// Fuzzing type checking
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const randomSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
||||
typeChecker.getTypeOfSymbolAtLocation(randomSymbol, sourceFile);
|
||||
// ...
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (!ignoredError(error)) throw error;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function ignoredError(error) {
|
||||
return !!ignored.find((message) => error.message.indexOf(message) !== -1);
|
||||
return !!ignored.find(message => error.message.indexOf(message) !== -1);
|
||||
}
|
||||
|
||||
const ignored = [
|
||||
|
|
|
@ -14,28 +14,21 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const { FuzzedDataProvider } = require('@jazzer.js/core');
|
||||
const ts = require('typescript');
|
||||
const { FuzzedDataProvider } = require("@jazzer.js/core");
|
||||
const ts = require("typescript");
|
||||
|
||||
module.exports.fuzz = function(data) {
|
||||
const provider = new FuzzedDataProvider(data);
|
||||
|
||||
try {
|
||||
// Generate a random file name and path.
|
||||
const fileName = provider.consumeString(10) + '.ts';
|
||||
const filePath = provider.consumeString(10) + '/' + fileName;
|
||||
const fileName = provider.consumeString(10) + ".ts";
|
||||
const filePath = provider.consumeString(10) + "/" + fileName;
|
||||
const fileContent = provider.consumeString(100);
|
||||
|
||||
// Generate a random file content.
|
||||
const fileContent = provider.consumeString(1000);
|
||||
|
||||
// Create a source file from the generated file content.
|
||||
const sourceFile = ts.createSourceFile(fileName, fileContent, ts.ScriptTarget.Latest);
|
||||
|
||||
// Parse the source file.
|
||||
const result = ts.parseSourceFile(sourceFile, ts.ScriptTarget.Latest, true);
|
||||
|
||||
// Consume the diagnostics array generated by the parseSourceFile function.
|
||||
const diagnostics = result.diagnostics.map(diagnostic => {
|
||||
const _diagnostics = result.diagnostics.map(diagnostic => {
|
||||
return {
|
||||
message: diagnostic.messageText,
|
||||
start: diagnostic.start,
|
||||
|
@ -44,7 +37,7 @@ module.exports.fuzz = function(data) {
|
|||
};
|
||||
});
|
||||
|
||||
// Generate random inputs for additional TypeScript compiler API functions.
|
||||
|
||||
const program = ts.createProgram([fileName], { allowJs: true });
|
||||
const printer = ts.createPrinter();
|
||||
const nodes = ts.createNodeArray([sourceFile]);
|
||||
|
@ -59,13 +52,20 @@ module.exports.fuzz = function(data) {
|
|||
ts.createSymbol(ts.SymbolFlags.Type, identifier);
|
||||
ts.createType(typeNode);
|
||||
|
||||
ts.createWatchCompilerHost([fileName], { allowJs: true }, ts.sys, ts.createSemanticDiagnosticsBuilderProgram, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
} catch (error) {
|
||||
const watchCompilerHost = ts.createWatchCompilerHost([fileName], { allowJs: true }, ts.sys, ts.createSemanticDiagnosticsBuilderProgram, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
|
||||
program.getTypeChecker();
|
||||
program.emit();
|
||||
program.getTypeRoots();
|
||||
ts.getParsedCommandLineOfConfigFile(fileName, {}, ts.sys).errors;
|
||||
program.getDeclarationDiagnostics();
|
||||
}
|
||||
catch (error) {
|
||||
if (!ignoredError(error)) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function ignoredError(error) {
|
||||
return !!ignored.find((message) => error.message.indexOf(message) !== -1);
|
||||
|
|
Loading…
Reference in New Issue