vscode: add CFLite helper for C++ (#11364)

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 <david@adalogics.com>
This commit is contained in:
DavidKorczynski 2023-12-14 22:34:12 +00:00 committed by GitHub
parent f55f09e479
commit 6bcb160328
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 442 additions and 39 deletions

View File

@ -1,12 +1,12 @@
{ {
"name": "OSS-Fuzz", "name": "OSS-Fuzz",
"version": "0.0.4", "version": "0.0.5",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "OSS-Fuzz", "name": "OSS-Fuzz",
"version": "0.0.4", "version": "0.0.5",
"dependencies": { "dependencies": {
"@microsoft/vscode-file-downloader-api": "^1.0.1" "@microsoft/vscode-file-downloader-api": "^1.0.1"
}, },

View File

@ -95,6 +95,21 @@
"command": "oss-fuzz.Template", "command": "oss-fuzz.Template",
"title": "OSS-Fuzz: Fuzzer Creation Using Templates", "title": "OSS-Fuzz: Fuzzer Creation Using Templates",
"description": "Creates a template fuzzer file using a catalogue of templates available." "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":[ "walkthroughs":[

View File

@ -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');
}
}

View File

@ -19,7 +19,7 @@ import {setStatusText} from '../utils';
export async function createOssFuzzSetup() { export async function createOssFuzzSetup() {
await setStatusText('Creating OSS-Fuzz setup: starting'); await setStatusText('Creating OSS-Fuzz setup: starting');
const res = await setupProjectInitialFiles(); const res = await setupProjectInitialFiles(false);
if (res) { if (res) {
await setStatusText('Creating OSS-Fuzz setup: finished'); await setStatusText('Creating OSS-Fuzz setup: finished');
} else { } else {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -22,6 +22,8 @@ import {println} from './logger';
// Import the command dispatcher functions // Import the command dispatcher functions
import {cmdInputCollectorRunSpecificFuzzer} from './commands/cmdRunFuzzer'; import {cmdInputCollectorRunSpecificFuzzer} from './commands/cmdRunFuzzer';
import {cmdInputCollectorBuildFuzzersFromWorkspace} from './commands/cmdBuildFuzzerFromWorkspace'; import {cmdInputCollectorBuildFuzzersFromWorkspace} from './commands/cmdBuildFuzzerFromWorkspace';
import {cmdInputCollectorBuildFuzzersFromWorkspaceCFLite} from './commands/cmdBuildFuzzerFromWorkspaceCFLite';
import {cmdInputCollectorTestFuzzerCFLite} from './commands/cmdTestFuzzerCFLite';
import {cmdDispatcherRe} from './commands/cmdRedo'; import {cmdDispatcherRe} from './commands/cmdRedo';
import {setupCIFuzzHandler} from './commands/cmdSetupCIFuzz'; import {setupCIFuzzHandler} from './commands/cmdSetupCIFuzz';
import {cmdInputCollectorTestFuzzer} from './commands/cmdTestFuzzer'; import {cmdInputCollectorTestFuzzer} from './commands/cmdTestFuzzer';
@ -31,6 +33,7 @@ import {runEndToEndAndGetCoverage} from './commands/cmdEndToEndCoverage';
import {listFuzzersHandler} from './commands/cmdListFuzzers'; import {listFuzzersHandler} from './commands/cmdListFuzzers';
import {cmdInputCollectorReproduceTestcase} from './commands/cmdReproduceTestcase'; import {cmdInputCollectorReproduceTestcase} from './commands/cmdReproduceTestcase';
import {cmdDispatcherTemplate} from './commands/cmdTemplate'; import {cmdDispatcherTemplate} from './commands/cmdTemplate';
import {cmdDispatcherGenerateClusterfuzzLite} from './commands/cmdDispatcherGenerateClusterfuzzLite';
import {setUpOssFuzzHandler} from './commands/cmdSetupOSSFuzz'; import {setUpOssFuzzHandler} from './commands/cmdSetupOSSFuzz';
import {setOssFuzzPath} from './commands/cmdSetOSSFuzzPath'; import {setOssFuzzPath} from './commands/cmdSetOSSFuzzPath';
import {extensionConfig} from './config'; import {extensionConfig} from './config';
@ -156,6 +159,36 @@ export function activate(context: vscode.ExtensionContext) {
println('CMD end: template'); 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 // This method is called when your extension is deactivated

View File

@ -25,6 +25,30 @@ import {
import {println} from './logger'; import {println} from './logger';
import {extensionConfig} from './config'; 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. * Builds the fuzzers for a given workspace.
* *
@ -37,7 +61,7 @@ export async function buildFuzzersFromWorkspace(
sanitizer: string, sanitizer: string,
toClean: boolean toClean: boolean
) { ) {
// println('Building fuzzers locally2'); // println('Building fuzzers locally');
// Check if there is an OSS-Fuzz set up, and exit if not. // Check if there is an OSS-Fuzz set up, and exit if not.
if ( if (
@ -244,6 +268,49 @@ export async function buildFuzzersFromWorkspace(
return true; 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. * Runs the fuzzer for a given project.
*/ */

View File

@ -19,22 +19,39 @@ import * as vscode from 'vscode';
import path = require('path'); import path = require('path');
import {println} from './logger'; import {println} from './logger';
export async function setupProjectInitialFiles() { export async function setupProjectInitialFiles(isClusterfuzzLite: boolean) {
const wsedit = new vscode.WorkspaceEdit(); const wsedit = new vscode.WorkspaceEdit();
const workspaceFolder = vscode.workspace.workspaceFolders; const workspaceFolder = vscode.workspace.workspaceFolders;
let projectGithubRepository = '';
const projectGithubRepository = await vscode.window.showInputBox({ const isOssFuzz = isClusterfuzzLite === false;
value: '',
placeHolder: 'Github repository for the project.', // Get the repository if this is not ClusterfuzzLite
}); if (isOssFuzz) {
if (!projectGithubRepository) { const tmpProjectGithubRepository = await vscode.window.showInputBox({
return false; value: '',
placeHolder: 'Github repository for the project.',
});
if (!tmpProjectGithubRepository) {
return false;
}
projectGithubRepository = tmpProjectGithubRepository;
} }
const projectNameFromRepo = path const projectNameFromRepo = path
.parse(projectGithubRepository) .parse(projectGithubRepository)
.base.toLocaleLowerCase(); .base.toLocaleLowerCase();
println('Derived project name: ' + projectNameFromRepo);
let pathOfLocal = '';
if (workspaceFolder) {
pathOfLocal = path
.parse(workspaceFolder[0].uri.fsPath)
.base.toLocaleLowerCase();
println('path of local: ' + pathOfLocal);
}
if (isOssFuzz) {
println('Derived project name: ' + projectNameFromRepo);
}
const pythonFiles = await vscode.workspace.findFiles('**/*.py'); const pythonFiles = await vscode.workspace.findFiles('**/*.py');
const cppFiles = await vscode.workspace.findFiles('**/*.c++'); const cppFiles = await vscode.workspace.findFiles('**/*.c++');
@ -74,11 +91,16 @@ export async function setupProjectInitialFiles() {
} }
println('Target language: ' + target); println('Target language: ' + target);
let baseFolder = '.clusterfuzzlite';
if (isOssFuzz) {
baseFolder = 'OSS-Fuzz';
}
if (workspaceFolder) { if (workspaceFolder) {
const wsPath = workspaceFolder[0].uri.fsPath; // gets the path of the first workspace folder const wsPath = workspaceFolder[0].uri.fsPath; // gets the path of the first workspace folder
const ossfuzzDockerFilepath = vscode.Uri.file( const ossfuzzDockerFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/Dockerfile' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/Dockerfile'
); );
vscode.window.showInformationMessage(ossfuzzDockerFilepath.toString()); vscode.window.showInformationMessage(ossfuzzDockerFilepath.toString());
@ -90,7 +112,8 @@ export async function setupProjectInitialFiles() {
projectNameFromRepo, projectNameFromRepo,
ossfuzzDockerFilepath, ossfuzzDockerFilepath,
wsedit, wsedit,
wsPath wsPath,
baseFolder
); );
} }
if (target === 'cpp') { if (target === 'cpp') {
@ -99,7 +122,10 @@ export async function setupProjectInitialFiles() {
projectNameFromRepo, projectNameFromRepo,
ossfuzzDockerFilepath, ossfuzzDockerFilepath,
wsedit, wsedit,
wsPath wsPath,
baseFolder,
pathOfLocal,
isOssFuzz
); );
} }
if (target === 'c') { if (target === 'c') {
@ -108,7 +134,8 @@ export async function setupProjectInitialFiles() {
projectNameFromRepo, projectNameFromRepo,
ossfuzzDockerFilepath, ossfuzzDockerFilepath,
wsedit, wsedit,
wsPath wsPath,
baseFolder
); );
} }
if (target === 'java') { if (target === 'java') {
@ -117,7 +144,8 @@ export async function setupProjectInitialFiles() {
projectNameFromRepo, projectNameFromRepo,
ossfuzzDockerFilepath, ossfuzzDockerFilepath,
wsedit, wsedit,
wsPath wsPath,
baseFolder
); );
} }
@ -131,7 +159,8 @@ async function setupJavaProjectInitialFiles(
projectNameFromRepo: string, projectNameFromRepo: string,
ossfuzzDockerFilepath: vscode.Uri, ossfuzzDockerFilepath: vscode.Uri,
wsedit: vscode.WorkspaceEdit, wsedit: vscode.WorkspaceEdit,
wsPath: string wsPath: string,
baseFolder: string
) { ) {
const todaysDate = new Date(); const todaysDate = new Date();
const currentYear = todaysDate.getFullYear(); const currentYear = todaysDate.getFullYear();
@ -168,7 +197,7 @@ COPY build.sh *.java $SRC/`;
); );
const ossfuzzBuildFilepath = vscode.Uri.file( const ossfuzzBuildFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/build.sh' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/build.sh'
); );
vscode.window.showInformationMessage(ossfuzzBuildFilepath.toString()); vscode.window.showInformationMessage(ossfuzzBuildFilepath.toString());
wsedit.createFile(ossfuzzBuildFilepath, {ignoreIfExists: true}); wsedit.createFile(ossfuzzBuildFilepath, {ignoreIfExists: true});
@ -196,7 +225,7 @@ COPY build.sh *.java $SRC/`;
// project.yaml // project.yaml
const projectYamlFilepath = vscode.Uri.file( const projectYamlFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/project.yaml' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/project.yaml'
); );
vscode.window.showInformationMessage(projectYamlFilepath.toString()); vscode.window.showInformationMessage(projectYamlFilepath.toString());
wsedit.createFile(projectYamlFilepath, {ignoreIfExists: true}); wsedit.createFile(projectYamlFilepath, {ignoreIfExists: true});
@ -214,7 +243,12 @@ file_github_issue: true
/* Sample template fuzzer */ /* Sample template fuzzer */
const sampleFuzzFile = vscode.Uri.file( const sampleFuzzFile = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/fuzzer_example.java' wsPath +
'/' +
baseFolder +
'/' +
projectNameFromRepo +
'/fuzzer_example.java'
); );
vscode.window.showInformationMessage(projectYamlFilepath.toString()); vscode.window.showInformationMessage(projectYamlFilepath.toString());
wsedit.createFile(sampleFuzzFile, {ignoreIfExists: true}); wsedit.createFile(sampleFuzzFile, {ignoreIfExists: true});
@ -248,7 +282,9 @@ file_github_issue: true
sampleFuzzFileContents sampleFuzzFileContents
); );
const readmeFile = vscode.Uri.file(wsPath + '/OSS-Fuzz/' + '/README.md'); const readmeFile = vscode.Uri.file(
wsPath + '/' + baseFolder + '/' + '/README.md'
);
vscode.window.showInformationMessage(readmeFile.toString()); vscode.window.showInformationMessage(readmeFile.toString());
wsedit.createFile(readmeFile, {ignoreIfExists: true}); wsedit.createFile(readmeFile, {ignoreIfExists: true});
const readmeContents = `# OSS-Fuzz set up const readmeContents = `# OSS-Fuzz set up
@ -264,7 +300,8 @@ async function setupCProjectInitialFiles(
projectNameFromRepo: string, projectNameFromRepo: string,
ossfuzzDockerFilepath: vscode.Uri, ossfuzzDockerFilepath: vscode.Uri,
wsedit: vscode.WorkspaceEdit, wsedit: vscode.WorkspaceEdit,
wsPath: string wsPath: string,
baseFolder: string
) { ) {
const todaysDate = new Date(); const todaysDate = new Date();
const currentYear = todaysDate.getFullYear(); const currentYear = todaysDate.getFullYear();
@ -297,7 +334,7 @@ COPY build.sh *.c $SRC/`;
); );
const ossfuzzBuildFilepath = vscode.Uri.file( const ossfuzzBuildFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/build.sh' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/build.sh'
); );
vscode.window.showInformationMessage(ossfuzzBuildFilepath.toString()); vscode.window.showInformationMessage(ossfuzzBuildFilepath.toString());
wsedit.createFile(ossfuzzBuildFilepath, {ignoreIfExists: true}); wsedit.createFile(ossfuzzBuildFilepath, {ignoreIfExists: true});
@ -332,7 +369,7 @@ COPY build.sh *.c $SRC/`;
// project.yaml // project.yaml
const projectYamlFilepath = vscode.Uri.file( const projectYamlFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/project.yaml' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/project.yaml'
); );
vscode.window.showInformationMessage(projectYamlFilepath.toString()); vscode.window.showInformationMessage(projectYamlFilepath.toString());
wsedit.createFile(projectYamlFilepath, {ignoreIfExists: true}); wsedit.createFile(projectYamlFilepath, {ignoreIfExists: true});
@ -350,7 +387,7 @@ file_github_issue: true
/* Sample template fuzzer */ /* Sample template fuzzer */
const sampleFuzzFile = vscode.Uri.file( const sampleFuzzFile = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/fuzzer_example.c' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/fuzzer_example.c'
); );
vscode.window.showInformationMessage(projectYamlFilepath.toString()); vscode.window.showInformationMessage(projectYamlFilepath.toString());
wsedit.createFile(sampleFuzzFile, {ignoreIfExists: true}); wsedit.createFile(sampleFuzzFile, {ignoreIfExists: true});
@ -383,7 +420,9 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
sampleFuzzFileContents sampleFuzzFileContents
); );
const readmeFile = vscode.Uri.file(wsPath + '/OSS-Fuzz/' + '/README.md'); const readmeFile = vscode.Uri.file(
wsPath + '/' + baseFolder + '/' + '/README.md'
);
vscode.window.showInformationMessage(readmeFile.toString()); vscode.window.showInformationMessage(readmeFile.toString());
wsedit.createFile(readmeFile, {ignoreIfExists: true}); wsedit.createFile(readmeFile, {ignoreIfExists: true});
const readmeContents = `# OSS-Fuzz set up const readmeContents = `# OSS-Fuzz set up
@ -399,7 +438,10 @@ async function setupCPPProjectInitialFiles(
projectNameFromRepo: string, projectNameFromRepo: string,
ossfuzzDockerFilepath: vscode.Uri, ossfuzzDockerFilepath: vscode.Uri,
wsedit: vscode.WorkspaceEdit, wsedit: vscode.WorkspaceEdit,
wsPath: string wsPath: string,
baseFolder: string,
baseName: string,
isOssFuzz: boolean
) { ) {
const todaysDate = new Date(); const todaysDate = new Date();
const currentYear = todaysDate.getFullYear(); const currentYear = todaysDate.getFullYear();
@ -425,14 +467,42 @@ RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone --depth 1 ${projectGithubRepository} ${projectNameFromRepo} RUN git clone --depth 1 ${projectGithubRepository} ${projectNameFromRepo}
WORKDIR ${projectNameFromRepo} WORKDIR ${projectNameFromRepo}
COPY build.sh *.cpp $SRC/`; COPY build.sh *.cpp $SRC/`;
const dockerfileTemplateClusterfuzzLite = `# Copyright ${currentYear} 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.
#
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake libtool
COPY . $SRC/${baseName}
COPY .clusterfuzzlite/build.sh $SRC/build.sh
WORKDIR $SRC/${baseName}`;
const contentToWrite = isOssFuzz
? dockerfileTemplate
: dockerfileTemplateClusterfuzzLite;
wsedit.insert( wsedit.insert(
ossfuzzDockerFilepath, ossfuzzDockerFilepath,
new vscode.Position(0, 0), new vscode.Position(0, 0),
dockerfileTemplate contentToWrite
); );
const ossfuzzBuildFilepath = vscode.Uri.file( const ossfuzzBuildFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/build.sh' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/build.sh'
); );
vscode.window.showInformationMessage(ossfuzzBuildFilepath.toString()); vscode.window.showInformationMessage(ossfuzzBuildFilepath.toString());
wsedit.createFile(ossfuzzBuildFilepath, {ignoreIfExists: true}); wsedit.createFile(ossfuzzBuildFilepath, {ignoreIfExists: true});
@ -466,11 +536,43 @@ COPY build.sh *.cpp $SRC/`;
# Copy all fuzzer executables to $OUT/ # Copy all fuzzer executables to $OUT/
$CXX $CFLAGS $LIB_FUZZING_ENGINE $SRC/fuzzer_example.cpp -o $OUT/fuzzer_example $CXX $CFLAGS $LIB_FUZZING_ENGINE $SRC/fuzzer_example.cpp -o $OUT/fuzzer_example
`; `;
wsedit.insert(ossfuzzBuildFilepath, new vscode.Position(0, 0), buildTemplate); const buildTemplateClusterfuzzLite = `#!/bin/bash -eu
# Copyright ${currentYear} 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.
#
################################################################################
# Supply build instructions
# Use the following environment variables to build the code
# $CXX: c++ compiler
# $CC: c compiler
# CFLAGS: compiler flags for C files
# CXXFLAGS: compiler flags for CPP files
# LIB_FUZZING_ENGINE: linker flag for fuzzing harnesses
# Copy all fuzzer executables to $OUT/
# Copy all fuzzer executables to $OUT/
$CXX $CFLAGS $LIB_FUZZING_ENGINE $SRC/${baseName}/.clusterfuzzlite/fuzzer_example.cpp -o $OUT/fuzzer_example
`;
const buildContent = isOssFuzz ? buildTemplate : buildTemplateClusterfuzzLite;
wsedit.insert(ossfuzzBuildFilepath, new vscode.Position(0, 0), buildContent);
// project.yaml // project.yaml
const projectYamlFilepath = vscode.Uri.file( const projectYamlFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/project.yaml' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/project.yaml'
); );
vscode.window.showInformationMessage(projectYamlFilepath.toString()); vscode.window.showInformationMessage(projectYamlFilepath.toString());
wsedit.createFile(projectYamlFilepath, {ignoreIfExists: true}); wsedit.createFile(projectYamlFilepath, {ignoreIfExists: true});
@ -488,7 +590,12 @@ file_github_issue: true
/* Sample template fuzzer */ /* Sample template fuzzer */
const sampleFuzzFile = vscode.Uri.file( const sampleFuzzFile = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/fuzzer_example.cpp' wsPath +
'/' +
baseFolder +
'/' +
projectNameFromRepo +
'/fuzzer_example.cpp'
); );
vscode.window.showInformationMessage(projectYamlFilepath.toString()); vscode.window.showInformationMessage(projectYamlFilepath.toString());
wsedit.createFile(sampleFuzzFile, {ignoreIfExists: true}); wsedit.createFile(sampleFuzzFile, {ignoreIfExists: true});
@ -519,7 +626,9 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
sampleFuzzFileContents sampleFuzzFileContents
); );
const readmeFile = vscode.Uri.file(wsPath + '/OSS-Fuzz/' + '/README.md'); const readmeFile = vscode.Uri.file(
wsPath + '/' + baseFolder + '/' + '/README.md'
);
vscode.window.showInformationMessage(readmeFile.toString()); vscode.window.showInformationMessage(readmeFile.toString());
wsedit.createFile(readmeFile, {ignoreIfExists: true}); wsedit.createFile(readmeFile, {ignoreIfExists: true});
const readmeContents = `# OSS-Fuzz set up const readmeContents = `# OSS-Fuzz set up
@ -535,7 +644,8 @@ async function setupPythonProjectInitialFiles(
projectNameFromRepo: string, projectNameFromRepo: string,
ossfuzzDockerFilepath: vscode.Uri, ossfuzzDockerFilepath: vscode.Uri,
wsedit: vscode.WorkspaceEdit, wsedit: vscode.WorkspaceEdit,
wsPath: string wsPath: string,
baseFolder: string
) { ) {
const todaysDate = new Date(); const todaysDate = new Date();
const currentYear = todaysDate.getFullYear(); const currentYear = todaysDate.getFullYear();
@ -568,7 +678,7 @@ COPY build.sh *.py $SRC/`;
); );
const ossfuzzBuildFilepath = vscode.Uri.file( const ossfuzzBuildFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/build.sh' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/build.sh'
); );
vscode.window.showInformationMessage(ossfuzzBuildFilepath.toString()); vscode.window.showInformationMessage(ossfuzzBuildFilepath.toString());
wsedit.createFile(ossfuzzBuildFilepath, {ignoreIfExists: true}); wsedit.createFile(ossfuzzBuildFilepath, {ignoreIfExists: true});
@ -599,7 +709,7 @@ done`;
// project.yaml // project.yaml
const projectYamlFilepath = vscode.Uri.file( const projectYamlFilepath = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/project.yaml' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/project.yaml'
); );
vscode.window.showInformationMessage(projectYamlFilepath.toString()); vscode.window.showInformationMessage(projectYamlFilepath.toString());
wsedit.createFile(projectYamlFilepath, {ignoreIfExists: true}); wsedit.createFile(projectYamlFilepath, {ignoreIfExists: true});
@ -617,7 +727,7 @@ file_github_issue: true
/* Sample template fuzzer */ /* Sample template fuzzer */
const sampleFuzzFile = vscode.Uri.file( const sampleFuzzFile = vscode.Uri.file(
wsPath + '/OSS-Fuzz/' + projectNameFromRepo + '/fuzz_ex1.py' wsPath + '/' + baseFolder + '/' + projectNameFromRepo + '/fuzz_ex1.py'
); );
vscode.window.showInformationMessage(projectYamlFilepath.toString()); vscode.window.showInformationMessage(projectYamlFilepath.toString());
wsedit.createFile(sampleFuzzFile, {ignoreIfExists: true}); wsedit.createFile(sampleFuzzFile, {ignoreIfExists: true});
@ -650,7 +760,9 @@ main()`;
sampleFuzzFileContents sampleFuzzFileContents
); );
const readmeFile = vscode.Uri.file(wsPath + '/OSS-Fuzz/' + '/README.md'); const readmeFile = vscode.Uri.file(
wsPath + '/' + baseFolder + '/' + '/README.md'
);
vscode.window.showInformationMessage(readmeFile.toString()); vscode.window.showInformationMessage(readmeFile.toString());
wsedit.createFile(readmeFile, {ignoreIfExists: true}); wsedit.createFile(readmeFile, {ignoreIfExists: true});
const readmeContents = `# OSS-Fuzz set up const readmeContents = `# OSS-Fuzz set up