Skip to content

Commit

Permalink
Try cargo-fuzz
Browse files Browse the repository at this point in the history
  RUSTC_WRAPPER=$PWD/misc/fuzzshim/rustc_wrapper.py cargo fuzz run --dev --sanitizer none fuzz_target_1

Unfortunately still failing lining on protobuf-native:

  target/x86_64-unknown-linux-gnu/debug/build/protobuf-native-b0ba7c5e922fceec/out/cxxbridge/sources/protobuf-native/src/io.rs.cc:1086:(.text.protobuf_native$io$cxxbridge1$DeleteCodedOutputStream+0x13): undefined reference to `protobuf_native::io::DeleteCodedOutputStream(google::protobuf::io::CodedOutputStream*)'

There was a similar error before in rust-lang/rustc_codegen_cranelift#1411, but their workaround doesn't work for me (we're already using llvm codegen-backend)
  • Loading branch information
def- committed Feb 21, 2024
1 parent 7a2fa2a commit 1f9c997
Show file tree
Hide file tree
Showing 41 changed files with 1,041 additions and 35 deletions.
49 changes: 44 additions & 5 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[workspace]
members = [
"fuzz",
"src/adapter",
"src/adapter-types",
"src/alloc",
Expand Down
4 changes: 4 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage
85 changes: 85 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
[package]
name = "mz-fuzz"
version = "0.0.0"
publish = false
edition = "2021"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4"
tokio = "1.32.0"
clap = { version = "3.2.24", features = ["derive"] }
chrono = { version = "0.4.23", default-features = false, features = ["std"] }
tempfile = "3.8.1"
time = "0.3.17"
walkdir = "2.3.2"

[dependencies.mz-orchestrator-tracing]
path = "../src/orchestrator-tracing"

[dependencies.mz-environmentd]
path = "../src/environmentd"

[dependencies.mz-sqllogictest]
path = "../src/sqllogictest"

[dependencies.mz-tracing]
path = "../src/tracing"

[dependencies.mz-ore]
path = "../src/ore"

[dependencies.mz-sql]
path = "../src/sql"

[dependencies.mz-sql-lexer]
path = "../src/sql-lexer"

[dependencies.mz-sql-pretty]
path = "../src/sql-pretty"

[dependencies.mz-repr-test-util]
path = "../src/repr-test-util"

[dependencies.mz-lowertest]
path = "../src/lowertest"

[dependencies.mz-repr]
path = "../src/repr"

[[bin]]
name = "fuzz_target_1"
path = "fuzz_targets/fuzz_target_1.rs"
test = false
doc = false
bench = false

[[bin]]
name = "fuzz_target_2"
path = "fuzz_targets/fuzz_target_2.rs"
test = false
doc = false
bench = false

[[bin]]
name = "fuzz_target_3"
path = "fuzz_targets/fuzz_target_3.rs"
test = false
doc = false
bench = false

[[bin]]
name = "fuzz_target_4"
path = "fuzz_targets/fuzz_target_4.rs"
test = false
doc = false
bench = false

[[bin]]
name = "fuzz_target_5"
path = "fuzz_targets/fuzz_target_5.rs"
test = false
doc = false
bench = false
9 changes: 9 additions & 0 deletions fuzz/fuzz_targets/fuzz_target_1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![no_main]

use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let _ = mz_sql::parse::parse(s);
}
});
9 changes: 9 additions & 0 deletions fuzz/fuzz_targets/fuzz_target_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![no_main]

use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let _ = mz_sql_lexer::lexer::lex(s);
}
});
9 changes: 9 additions & 0 deletions fuzz/fuzz_targets/fuzz_target_3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![no_main]

use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let _ = mz_sql_pretty::pretty_str(s, 128);
}
});
23 changes: 23 additions & 0 deletions fuzz/fuzz_targets/fuzz_target_4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#![no_main]

use mz_lowertest::{deserialize_optional_generic, tokenize};
use mz_repr_test_util::*;
use mz_repr::Row;
use libfuzzer_sys::fuzz_target;

fn f(s: &str) -> Result<Row, String> {
let mut stream_iter = tokenize(s)?.into_iter();
if let Some(litval) =
extract_literal_string(&stream_iter.next().ok_or("Empty test")?, &mut stream_iter)? {
let scalar_type = get_scalar_type_or_default(&litval[..], &mut stream_iter)?;
mz_repr_test_util::test_spec_to_row(std::iter::once((&litval[..], &scalar_type)))
} else {
Err("foo".to_string())
}
}

fuzz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let _ = f(s);
}
});
151 changes: 151 additions & 0 deletions fuzz/fuzz_targets/fuzz_target_5.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#![no_main]

use libfuzzer_sys::fuzz_target;

use std::cell::RefCell;
use std::fmt;
use std::fs::File;
use std::io::{self, Write, Stdout, Stderr};
use std::path::PathBuf;
use std::process::ExitCode;
use std::collections::BTreeMap;

use chrono::Utc;
use tokio::runtime::Runtime;
use mz_orchestrator_tracing::{StaticTracingConfig, TracingCliArgs};
use mz_ore::cli::{self, CliConfig, KeyValueArg};
use mz_ore::metrics::MetricsRegistry;
use mz_sqllogictest::runner::{self, Outcomes, RunConfig, Runner, WriteFmt, run_string};
use mz_sqllogictest::util;
use mz_tracing::CloneableEnvFilter;
use walkdir::WalkDir;

struct State {
stdout: OutputStream<Stdout>,
stderr: OutputStream<Stderr>,
config: Option<RunConfig<'static>>,
runner: Option<Runner<'static>>
}

async fn init() {
let tracing_args = TracingCliArgs {
..Default::default()
};
let (tracing_handle, _tracing_guard) = tracing_args
.configure_tracing(
StaticTracingConfig {
service_name: "sqllogictest",
build_info: mz_environmentd::BUILD_INFO,
},
MetricsRegistry::new(),
)
.await
.unwrap();

STATE.with(|state| async {
let mut state = state.borrow();
state.config = Some(RunConfig {
stdout: &state.stdout,
stderr: &state.stderr,
verbosity: 3,
postgres_url: "postgres://root@localhost:26257".to_string(),
no_fail: true,
fail_fast: false,
auto_index_tables: false,
auto_index_selects: false,
auto_transactions: false,
enable_table_keys: false,
orchestrator_process_wrapper: None,
tracing: tracing_args.clone(),
tracing_handle,
system_parameter_defaults: BTreeMap::new(),
persist_dir: tempfile::tempdir().unwrap(),
replicas: 1,
});
state.runner = Some(Runner::start(&state.config.unwrap()).await.unwrap());
});
}

thread_local!(static STATE: RefCell<State> = RefCell::new(State {
stdout: OutputStream::new(io::stdout(), false),
stderr: OutputStream::new(io::stderr(), false),
config: None,
runner: None,
}));

async fn run(s: String) {
STATE.with(|mut state| async {
run_string(&state.borrow().runner, "", &*s).await;
});
}

struct OutputStream<W> {
inner: RefCell<W>,
need_timestamp: RefCell<bool>,
timestamps: bool,
}

impl<W> OutputStream<W>
where
W: Write,
{
fn new(inner: W, timestamps: bool) -> OutputStream<W> {
OutputStream {
inner: RefCell::new(inner),
need_timestamp: RefCell::new(true),
timestamps,
}
}

fn emit_str(&self, s: &str) {
self.inner.borrow_mut().write_all(s.as_bytes()).unwrap();
}
}

impl<W> WriteFmt for OutputStream<W>
where
W: Write,
{
fn write_fmt(&self, fmt: fmt::Arguments<'_>) {
let s = format!("{}", fmt);
if self.timestamps {
// We need to prefix every line in `s` with the current timestamp.

let timestamp = Utc::now();
let timestamp_str = timestamp.format("%Y-%m-%d %H:%M:%S.%f %Z");

// If the last character we outputted was a newline, then output a
// timestamp prefix at the start of this line.
if self.need_timestamp.replace(false) {
self.emit_str(&format!("[{}] ", timestamp_str));
}

// Emit `s`, installing a timestamp at the start of every line
// except the last.
let (s, last_was_timestamp) = match s.strip_suffix('\n') {
None => (&*s, false),
Some(s) => (s, true),
};
self.emit_str(&s.replace('\n', &format!("\n[{}] ", timestamp_str)));

// If the line ended with a newline, output the newline but *not*
// the timestamp prefix. We want the timestamp to reflect the moment
// the *next* character is output. So instead we just remember that
// the last character we output was a newline.
if last_was_timestamp {
*self.need_timestamp.borrow_mut() = true;
self.emit_str("\n");
}
} else {
self.emit_str(&s)
}
}
}

fuzz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let rt = tokio::runtime::Runtime::new().unwrap();
let st = s.to_string();
rt.block_on(run(st));
}
});
Loading

0 comments on commit 1f9c997

Please sign in to comment.