Skip to content

Commit

Permalink
feat: add fuzz plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
j-lanson authored and mchernicoff committed Oct 16, 2024
1 parent d5886e3 commit 30bde41
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 13 deletions.
19 changes: 15 additions & 4 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ members = [
"sdk/rust",
"hipcheck-sdk-macros",
"plugins/git",
"plugins/github_api",
"plugins/github_api",
"plugins/npm_dependencies",
"plugins/activity",
"plugins/fuzz"
]

# Make sure Hipcheck is run with `cargo run`.
Expand Down
16 changes: 16 additions & 0 deletions plugins/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "fuzz"
version = "0.1.0"
license = "Apache-2.0"
edition = "2021"
publish = false

[dependencies]
clap = { version = "4.5.20", features = ["derive"] }
hipcheck-sdk = { version = "0.1.0", path = "../../sdk/rust", features = ["macros"] }
serde = { version = "1.0.210", features = ["derive"] }
serde_json = "1.0.128"
tokio = { version = "1.40.0", features = ["rt"] }

[dev-dependencies]
hipcheck-sdk = { path = "../../sdk/rust", features = ["macros", "mock_engine"] }
97 changes: 97 additions & 0 deletions plugins/fuzz/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: Apache-2.0

use clap::Parser;
use hipcheck_sdk::{prelude::*, types::Target};
use serde_json::Value;
use std::result::Result as StdResult;

/// Returns whether the target's remote repo uses Google's OSS fuzzing
#[query(default)]
async fn fuzz(engine: &mut PluginEngine, key: Target) -> Result<Value> {
if let Some(remote) = &key.remote {
engine.query("mitre/github_api", remote.clone()).await
} else {
Err(Error::UnexpectedPluginQueryInputFormat)
}
}

#[derive(Parser, Debug)]
struct Args {
#[arg(long)]
port: u16,
}

#[derive(Clone, Debug)]
struct FuzzAnalysisPlugin {}

impl Plugin for FuzzAnalysisPlugin {
const PUBLISHER: &'static str = "mitre";
const NAME: &'static str = "fuzz";

fn set_config(&self, _config: Value) -> StdResult<(), ConfigError> {
Ok(())
}

fn default_policy_expr(&self) -> Result<String> {
Ok("(eq $ #t)".to_owned())
}

fn explain_default_query(&self) -> Result<Option<String>> {
Ok(Some("Does the target repo do fuzzing".to_owned()))
}

queries! {}
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
let args = Args::try_parse().unwrap();
PluginServer::register(FuzzAnalysisPlugin {})
.listen(args.port)
.await
}

#[cfg(test)]
mod test {
use super::*;
use hipcheck_sdk::types::{KnownRemote, LocalGitRepo, RemoteGitRepo};

fn target() -> Target {
let local = LocalGitRepo {
path: "/home/users/me/.cache/hipcheck/clones/github/mitre/hipcheck/".to_string(),
git_ref: "main".to_string(),
};
let known_remote = Some(KnownRemote::GitHub {
owner: "mitre".to_owned(),
repo: "hipcheck".to_owned(),
});
let remote = Some(RemoteGitRepo {
url: "https://github.com/mitre/hipcheck".parse().unwrap(),
known_remote,
});
Target {
specifier: "hipcheck".to_owned(),
local,
remote,
package: None,
}
}

fn mock_responses() -> StdResult<MockResponses, Error> {
let target = target();
let known_remote = target.remote.as_ref().unwrap().clone();
let output = true;
Ok(MockResponses::new().insert("mitre/github_api", known_remote, Ok(output))?)
}

#[tokio::test]
async fn test_fuzz() {
let target = target();
let mut engine = PluginEngine::mock(mock_responses().unwrap());
let output = fuzz(&mut engine, target).await.unwrap();
let result: bool = serde_json::from_value(output).unwrap();
let expected = true;

assert_eq!(result, expected);
}
}
2 changes: 1 addition & 1 deletion plugins/github_api/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl<'a> GitHub<'a> {
}

pub fn fuzz_check(&self, repo_uri: Rc<String>) -> Result<bool> {
search_code_request(&self.agent, repo_uri).context("unable to search fuzzing information; please check the HC_GITHUB_TOKEN system environment variable")
search_code_request(&self.agent, repo_uri).context("unable to search fuzzing information; please ensure the provided system environment variable exists and contains a valid GitHub API token")
}

pub fn get_reviews_for_pr(&self) -> Result<Vec<GitHubPullRequest>> {
Expand Down
15 changes: 8 additions & 7 deletions sdk/rust/src/mock.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use serde::Serialize;

use crate::{Error, JsonValue, QueryTarget, Result};
use crate::{JsonValue, QueryTarget, Result};
use std::collections::HashMap;

#[derive(Default)]
Expand Down Expand Up @@ -32,13 +30,16 @@ impl MockResponses {
) -> Result<Self>
where
T: TryInto<QueryTarget, Error: Into<crate::Error>>,
V: Serialize,
W: Into<JsonValue>,
V: serde::Serialize,
W: serde::Serialize,
{
let query_target: QueryTarget = query_target.try_into().map_err(|e| e.into())?;
let query_value: JsonValue =
serde_json::to_value(query_value).map_err(Error::InvalidJsonInQueryKey)?;
let query_response = query_response.map(|v| v.into());
serde_json::to_value(query_value).map_err(crate::Error::InvalidJsonInQueryKey)?;
let query_response = match query_response {
Ok(v) => serde_json::to_value(v).map_err(crate::Error::InvalidJsonInQueryKey),
Err(e) => Err(e),
};
self.inner_insert(query_target, query_value, query_response)
}
}

0 comments on commit 30bde41

Please sign in to comment.