Skip to content

Commit

Permalink
vscode: add CFLite helper for C++ (#11364)
Browse files Browse the repository at this point in the history
Adds helpers to:
- Generate files needed for a CFLite set up (the content of
`.clusterfuzzlite`, not the GH workflow)
- Test fuzzers in a CFLite set up

Only CPP support for now.

Follow-up PRs will:
- Add support for the rest of the languages
- Add support for code coverage generation
- Add support for yaml generation.

Signed-off-by: David Korczynski <[email protected]>
  • Loading branch information
DavidKorczynski authored Dec 14, 2023
1 parent f55f09e commit 6bcb160
Show file tree
Hide file tree
Showing 9 changed files with 443 additions and 40 deletions.
4 changes: 2 additions & 2 deletions tools/vscode-extension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions tools/vscode-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@
"command": "oss-fuzz.Template",
"title": "OSS-Fuzz: Fuzzer Creation Using Templates",
"description": "Creates a template fuzzer file using a catalogue of templates available."
},
{
"command": "oss-fuzz.GenerateClusterfuzzLite",
"title": "OSS-Fuzz: Generate ClusterfuzzLite setup",
"description": "Creates the files needed for ClusterfuzzLite integration."
},
{
"command": "oss-fuzz.WSBuildFuzzersCFLite",
"title": "OSS-Fuzz: [CFLite] Build Fuzzers In Workspace",
"description": "Builds the ClusterfuzzLite fuzzers from the project in the current VSCode workspace."
},
{
"command": "oss-fuzz.testFuzzerCFLite",
"title": "OSS-Fuzz: [CFLite] Test running a specific fuzzer.",
"description": "Builds the CFLite setup and runs a fuzzer for a short period of time."
}
],
"walkthroughs":[
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

import {commandHistory} from '../commandUtils';
import {setStatusText} from '../utils';
import {buildFuzzersFromWorkspaceClusterfuzzLite} from '../ossfuzzWrappers';

export async function cmdInputCollectorBuildFuzzersFromWorkspaceCFLite() {
// Create an history object
const args = new Object({
toClean: false,
});

const commandObject = new Object({
commandType: 'oss-fuzz.WSBuildFuzzers',
Arguments: args,
dispatcherFunc: cmdDispatchbuildFuzzersFromWorkspaceClusterfuzzLite,
});
console.log('L1: ' + commandHistory.length);
commandHistory.push(commandObject);

await cmdDispatchbuildFuzzersFromWorkspaceClusterfuzzLite(args);
return true;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
async function cmdDispatchbuildFuzzersFromWorkspaceClusterfuzzLite(_args: any) {
await setStatusText('[CFLite] Building fuzzers: starting');
const res = await buildFuzzersFromWorkspaceClusterfuzzLite();
if (res) {
await setStatusText('[CFLite] Building fuzzers: finished');
} else {
await setStatusText('[CFLite] Building fuzzers: failed');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {setStatusText} from '../utils';

export async function createOssFuzzSetup() {
await setStatusText('Creating OSS-Fuzz setup: starting');
const res = await setupProjectInitialFiles();
const res = await setupProjectInitialFiles(false);
if (res) {
await setStatusText('Creating OSS-Fuzz setup: finished');
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

/**
* Command for generating template fuzzers. This is a short-cut for rapid
* prototyping as well as an archive for inspiration.
*/
import * as vscode from 'vscode';
import {setStatusText} from '../utils';

import {setupProjectInitialFiles} from '../projectIntegrationHelper';

export async function cmdDispatcherGenerateClusterfuzzLite(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_context: vscode.ExtensionContext
) {
await setStatusText('Creating OSS-Fuzz setup: starting');
const res = await setupProjectInitialFiles(true);
if (res) {
await setStatusText('Creating OSS-Fuzz setup: finished');
} else {
await setStatusText('Creating OSS-Fuzz setup: failed');
}
return;
}
89 changes: 89 additions & 0 deletions tools/vscode-extension/src/commands/cmdTestFuzzerCFLite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

import path = require('path');
import * as vscode from 'vscode';
import {println} from '../logger';
import {
runFuzzerHandlerCFLite,
buildFuzzersFromWorkspaceClusterfuzzLite,
} from '../ossfuzzWrappers';
import {setStatusText} from '../utils';
import {commandHistory} from '../commandUtils';
import {extensionConfig} from '../config';

/**
* Does an end-to-end test of a project/fuzzer. This is done by
* first building the project and then running the fuzzer.
* @param context
* @returns
*/

export async function cmdInputCollectorTestFuzzerCFLite() {
setStatusText('Testing specific fuzzer: getting input');
// Get the fuzzer to run
const fuzzerNameInput = await vscode.window.showInputBox({
value: '',
placeHolder: 'Type a fuzzer name',
});
if (!fuzzerNameInput) {
println('Failed to get fuzzer name');
return;
}

// Create the args object for the dispatcher
const args = new Object({
fuzzerName: fuzzerNameInput.toString(),
});

// Create a dispatcher object.
const commandObject = new Object({
commandType: 'oss-fuzz.TestFuzzerCFLite',
Arguments: args,
dispatcherFunc: cmdDispatchTestFuzzerHandlerCFLite,
});
commandHistory.push(commandObject);

await cmdDispatchTestFuzzerHandlerCFLite(args);
}

async function cmdDispatchTestFuzzerHandlerCFLite(args: any) {
// Build the project
setStatusText('Test specific fuzzer: building fuzzers in workspace');
if (!(await buildFuzzersFromWorkspaceClusterfuzzLite())) {
println('Build projects');
return;
}

const workspaceFolder = vscode.workspace.workspaceFolders;
if (!workspaceFolder) {
return;
}

const pathOfLocal = workspaceFolder[0].uri.path;
println('path of local: ' + pathOfLocal);

// Run the fuzzer for 10 seconds
println('Running fuzzer');
setStatusText('Test specific fuzzer: running fuzzer ' + args.fuzzerName);
await runFuzzerHandlerCFLite(
pathOfLocal,
args.fuzzerName,
extensionConfig.numberOfSecondsForTestRuns.toString()
);
setStatusText('Test specific fuzzer: test completed of ' + args.fuzzerName);
return;
}
33 changes: 33 additions & 0 deletions tools/vscode-extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {println} from './logger';
// Import the command dispatcher functions
import {cmdInputCollectorRunSpecificFuzzer} from './commands/cmdRunFuzzer';
import {cmdInputCollectorBuildFuzzersFromWorkspace} from './commands/cmdBuildFuzzerFromWorkspace';
import {cmdInputCollectorBuildFuzzersFromWorkspaceCFLite} from './commands/cmdBuildFuzzerFromWorkspaceCFLite';
import {cmdInputCollectorTestFuzzerCFLite} from './commands/cmdTestFuzzerCFLite';
import {cmdDispatcherRe} from './commands/cmdRedo';
import {setupCIFuzzHandler} from './commands/cmdSetupCIFuzz';
import {cmdInputCollectorTestFuzzer} from './commands/cmdTestFuzzer';
Expand All @@ -31,6 +33,7 @@ import {runEndToEndAndGetCoverage} from './commands/cmdEndToEndCoverage';
import {listFuzzersHandler} from './commands/cmdListFuzzers';
import {cmdInputCollectorReproduceTestcase} from './commands/cmdReproduceTestcase';
import {cmdDispatcherTemplate} from './commands/cmdTemplate';
import {cmdDispatcherGenerateClusterfuzzLite} from './commands/cmdDispatcherGenerateClusterfuzzLite';
import {setUpOssFuzzHandler} from './commands/cmdSetupOSSFuzz';
import {setOssFuzzPath} from './commands/cmdSetOSSFuzzPath';
import {extensionConfig} from './config';
Expand Down Expand Up @@ -156,6 +159,36 @@ export function activate(context: vscode.ExtensionContext) {
println('CMD end: template');
})
);

context.subscriptions.push(
vscode.commands.registerCommand(
'oss-fuzz.GenerateClusterfuzzLite',
async () => {
println('CMD start: GenerateClusterfuzzLite');
await cmdDispatcherGenerateClusterfuzzLite(context);
println('CMD end: GenerateClusterfuzzLite');
}
)
);

context.subscriptions.push(
vscode.commands.registerCommand(
'oss-fuzz.WSBuildFuzzersCFLite',
async () => {
println('CMD start: WSBuildFuzzersCFLite');
await cmdInputCollectorBuildFuzzersFromWorkspaceCFLite();
println('CMD end: WSBuildFuzzersCFLite');
}
)
);

context.subscriptions.push(
vscode.commands.registerCommand('oss-fuzz.testFuzzerCFLite', async () => {
println('CMD start: testFuzzerCFLite');
await cmdInputCollectorTestFuzzerCFLite();
println('CMD end: testFuzzerCFLite');
})
);
}

// This method is called when your extension is deactivated
Expand Down
69 changes: 68 additions & 1 deletion tools/vscode-extension/src/ossfuzzWrappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@ import {
import {println} from './logger';
import {extensionConfig} from './config';

export async function buildFuzzersFromWorkspaceClusterfuzzLite() {
const workspaceFolder = vscode.workspace.workspaceFolders;
if (!workspaceFolder) {
println('No workspace folder, exiting');
return false;
}

// Build the fuzzers using OSS-Fuzz infrastructure.
const cmdToExec = 'python3';
const args = [
extensionConfig.ossFuzzPepositoryWorkPath + '/infra/helper.py',
'build_fuzzers',
];

args.push('--external');
args.push(workspaceFolder[0].uri.path);
println('Building fuzzers');
if (!(await systemSyncLogIfFailure(cmdToExec, args))) {
println('Failed to build fuzzers');
return false;
}
return true;
}

/**
* Builds the fuzzers for a given workspace.
*
Expand All @@ -37,7 +61,7 @@ export async function buildFuzzersFromWorkspace(
sanitizer: string,
toClean: boolean
) {
// println('Building fuzzers locally2');
// println('Building fuzzers locally');

// Check if there is an OSS-Fuzz set up, and exit if not.
if (
Expand Down Expand Up @@ -244,6 +268,49 @@ export async function buildFuzzersFromWorkspace(
return true;
}

/**
* Runs the fuzzer for a given CFLite project
*/
export async function runFuzzerHandlerCFLite(
projectNameArg: string,
fuzzerNameArg: string,
secondsToRunArg: string
) {
// The fuzzer is run by way of OSS-Fuzz's helper.py so we use python3 to launch
// this script.
const cmdToExec = 'python3';

// Set the arguments correctly. The ordering here is important for compatibility
// with the underlying argparse used by OSS-Fuzz helper.py.
const args: Array<string> = [
extensionConfig.ossFuzzPepositoryWorkPath + '/infra/helper.py',
'run_fuzzer',
];

args.push('--external');
args.push(projectNameArg);
args.push(fuzzerNameArg);
args.push('--');
args.push('-max_total_time=' + secondsToRunArg);

println(
'Running fuzzer' +
fuzzerNameArg +
' from project ' +
projectNameArg +
' for ' +
secondsToRunArg +
' seconds.'
);

// Run the actual command
if (!(await systemSyncLogIfFailure(cmdToExec, args))) {
println('Failed to run fuzzer');
return false;
}
return true;
}

/**
* Runs the fuzzer for a given project.
*/
Expand Down
Loading

0 comments on commit 6bcb160

Please sign in to comment.