TinyInst Update (#968)

* tmp

* more

* save

* TODO

* fix

* update to tinyinst on crates

* dep

* fmt

* shmem done

* cpp fmt

* clp

* fmt

* why??

* ver

* more makefile.toml

* windows test

* Update build_and_test.yml

* fix

* a

* install

* fmt

* fix

* only macos and win

* more

* The order matters

* remove

* fmt

* chg

* typo

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
This commit is contained in:
Dongjia "toka" Zhang 2023-01-23 19:11:53 +09:00 committed by GitHub
parent 3b68399cc9
commit fe51286586
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 562 additions and 95 deletions

View File

@ -173,6 +173,9 @@ jobs:
run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade
- name: Add no_std toolchain
run: rustup toolchain install nightly-x86_64-unknown-linux-gnu ; rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- name: Install cxxbridge
if: runner.os == 'macOS'
run: cargo install cxxbridge-cmd
- name: Install python (macOS)
# Removing macOS things already installed in CI against failed linking
if: runner.os == 'macOS'
@ -255,10 +258,14 @@ jobs:
- name: install cargo-make
run: cargo install --force cargo-make
- uses: ilammy/msvc-dev-cmd@v1
- name: install cxx bridge
run: cargo install cxxbridge-cmd
- name: Build fuzzers/frida_libpng
run: cd fuzzers/frida_libpng/ && cargo make test
- name: Build fuzzers/frida_gdiplus
run: cd fuzzers/frida_gdiplus/ && cargo make test
- name: Build fuzzers/tinyinst_simple
run: cd fuzzers/tinyinst_simple/ && cargo make test
macos:
runs-on: macOS-latest
@ -271,6 +278,8 @@ jobs:
run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade
- name: Install deps
run: brew install z3 gtk+3
- name: Install cxxbridge
run: cargo install cxxbridge-cmd
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
- name: MacOS Build

View File

@ -6,8 +6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libafl = { version = "0.8.1", path = "../../libafl", features = ["tui"] }
libafl_tinyinst = { version = "0.8.1", path = "../../libafl_tinyinst" }
libafl = { version = "0.8.2", path = "../../libafl", features = ["introspection"] }
libafl_tinyinst = { version = "0.8.2", path = "../../libafl_tinyinst" }
[profile.release]
codegen-units = 1
opt-level = 3

View File

@ -1,8 +1,56 @@
[tasks.build_test]
command = "cl"
args = ["./test/test.c", "-o", "./test/test.exe"]
[tasks.unsupported]
script_runner="@shell"
script='''
echo "Cargo-make not integrated yet on this"
'''
# Harness
[tasks.harness]
linux_alias = "unsupported"
mac_alias = "unsupported"
windows_alias = "harness_windows"
[tasks.harness_windows]
script='''
cl test\test.cpp -o test.exe
'''
# Fuzzer
[tasks.fuzzer]
linux_alias = "unsupported"
mac_alias = "unsupported"
windows_alias = "fuzzer_windows"
[tasks.fuzzer_windows]
dependencies = ["harness"]
command = "cargo"
args = ["build", "--release"]
# Run the fuzzer
[tasks.run]
dependencies = ["build_test"]
linux_alias = "unsupported"
mac_alias = "unsupported"
windows_alias = "run_windows"
[tasks.run_windows]
dependencies = ["harness", "fuzzer"]
command = "cargo"
args = ["run", "--release"]
# Run the fuzzer
[tasks.test]
linux_alias = "unsupported"
mac_alias = "unsupported"
windows_alias = "test_windows"
[tasks.test_windows]
script_runner = "@shell"
script='''
copy .\target\release\tinyinst_simple.exe .
start "" "tinyinst_simple.exe"
#ping is for timeout
ping -n 10 127.0.0.1>NUL && taskkill /im tinyinst_simple.exe /F
>nul 2>nul dir /a-d "corpus_discovered\*" && (echo Files exist) || (exit /b 1337)
'''
dependencies = [ "harness", "fuzzer" ]

View File

@ -1,3 +1,11 @@
# Run Instruction
# Tinyinst example
This is a fuzzer example to show how libafl_tinyinst works
## How to build
1. Build the harness with `cl test\test.cpp -o test.exe`
2. Build the fuzzer with `cargo build --release`. The fuzzer is `target\release\tinyinst_simple.exe`
## Run with cargo-make
Or, you can simple run it using cargo-make
1. Open up developer powershell so that you have access to cl (Windows Default Compiler)
2. Run `cargo make run` to run the fuzzer

View File

@ -1,8 +1,13 @@
use std::path::PathBuf;
#[cfg(target_vendor = "apple")]
use libafl::bolts::shmem::UnixShMemProvider;
#[cfg(windows)]
use libafl::bolts::shmem::Win32ShMemProvider;
use libafl::{
bolts::{
rands::{RandomSeed, StdRand},
shmem::ShMemProvider,
tuples::tuple_list,
},
corpus::{CachedOnDiskCorpus, Corpus, OnDiskCorpus, Testcase},
@ -17,17 +22,30 @@ use libafl::{
state::StdState,
Fuzzer, StdFuzzer,
};
use libafl_tinyinst::executor::TinyInstExecutor;
use libafl_tinyinst::executor::TinyInstExecutorBuilder;
static mut COVERAGE: Vec<u64> = vec![];
#[cfg(not(any(target_vendor = "apple", windows)))]
fn main() {}
#[cfg(any(target_vendor = "apple", windows))]
fn main() {
// Tinyinst things
let tinyinst_args = vec!["-instrument_module".to_string(), "test.exe".to_string()];
let args = vec![".\\test\\test.exe".to_string(), "@@".to_string()];
// use shmem to pass testcases
let args = vec!["test.exe".to_string(), "-m".to_string(), "@@".to_string()];
// use file to pass testcases
// let args = vec!["test.exe".to_string(), "-f".to_string(), "@@".to_string()];
let observer = unsafe { ListObserver::new("cov", &mut COVERAGE) };
let mut feedback = ListFeedback::with_observer(&observer);
#[cfg(windows)]
let mut shmem_provider = Win32ShMemProvider::new().unwrap();
#[cfg(target_vendor = "apple")]
let mut shmem_provider = UnixShMemProvider::new().unwrap();
let input = BytesInput::new(b"bad".to_vec());
let rand = StdRand::new();
@ -46,13 +64,15 @@ fn main() {
let mut mgr = SimpleEventManager::new(monitor);
let mut executor = unsafe {
TinyInstExecutor::new(
&mut COVERAGE,
tinyinst_args,
args,
5000,
tuple_list!(observer),
)
TinyInstExecutorBuilder::new()
.tinyinst_args(tinyinst_args)
.program_args(args)
.use_shmem()
.persistent("test.exe".to_string(), "fuzz".to_string(), 1, 10000)
.timeout(std::time::Duration::new(5, 0))
.shmem_provider(&mut shmem_provider)
.build(&mut COVERAGE, tuple_list!(observer))
.unwrap()
};
let mutator = StdScheduledMutator::new(havoc_mutations());
let mut stages = tuple_list!(StdMutationalStage::new(mutator));

View File

@ -1,36 +0,0 @@
#include <stdio.h>
void pass1(char *buf, int buf_size) {
char target[0x10];
if (buf[0] == 'b') {
if (buf[1] == 'a') {
if (buf[2] == 'd') {
if (buf[3] == '1') {
if (buf[4] == '2') {
printf("You got me\n");
memcpy(target, buf, 0x1000000);
printf("GG\n");
}
}
}
}
}
}
int main(int argc, char *argv[]) {
FILE *fp;
char buf[0x1000];
if (argc == 2) {
fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("File not found\n");
printf("Received filename %s\n", argv[1]);
return 1;
}
fscanf(fp, "%s", buf);
pass1(buf, sizeof(buf));
} else {
printf("there is nothing\n");
}
}

View File

@ -0,0 +1,163 @@
/*
Copyright 2020 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
https://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.
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <inttypes.h>
// shared memory stuff
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
#include <windows.h>
#else
#include <sys/mman.h>
#endif
#define MAX_SAMPLE_SIZE 1000000
#define SHM_SIZE (4 + MAX_SAMPLE_SIZE)
unsigned char *shm_data;
bool use_shared_memory;
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
int setup_shmem(const char *name) {
HANDLE map_file;
map_file = OpenFileMapping(FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
name); // name of mapping object
if (map_file == NULL) {
printf("Error accessing shared memory\n");
return 0;
}
shm_data = (unsigned char *)MapViewOfFile(
map_file, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0, 0, SHM_SIZE);
if (shm_data == NULL) {
printf("Error accessing shared memory\n");
return 0;
}
return 1;
}
#else
int setup_shmem(const char *name) {
int fd;
// get shared memory file descriptor (NOT a file)
fd = shm_open(name, O_RDONLY, S_IRUSR | S_IWUSR);
if (fd == -1) {
printf("Error in shm_open\n");
return 0;
}
// map shared memory to process address space
shm_data =
(unsigned char *)mmap(NULL, SHM_SIZE, PROT_READ, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED) {
printf("Error in mmap\n");
return 0;
}
return 1;
}
#endif
// used to force a crash
char *crash = NULL;
// ensure we can find the target
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
#define FUZZ_TARGET_MODIFIERS __declspec(dllexport)
#else
#define FUZZ_TARGET_MODIFIERS __attribute__((noinline))
#endif
// actual target function
void FUZZ_TARGET_MODIFIERS fuzz(char *name) {
char *sample_bytes = NULL;
uint32_t sample_size = 0;
// read the sample either from file or
// shared memory
if (use_shared_memory) {
sample_size = *(uint32_t *)(shm_data);
if (sample_size > MAX_SAMPLE_SIZE) sample_size = MAX_SAMPLE_SIZE;
sample_bytes = (char *)malloc(sample_size);
memcpy(sample_bytes, shm_data + sizeof(uint32_t), sample_size);
} else {
FILE *fp = fopen(name, "rb");
if (!fp) {
printf("Error opening %s a\n", name);
return;
}
fseek(fp, 0, SEEK_END);
sample_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
sample_bytes = (char *)malloc(sample_size);
fread(sample_bytes, 1, sample_size, fp);
fclose(fp);
}
// printf("sample_bytes: %s", sample_bytes);
if (sample_size >= 4) {
// check if the sample spells "test"
if (*(uint32_t *)(sample_bytes) == 0x74736574) {
// if so, crash
crash[0] = 1;
}
}
if (sample_bytes) free(sample_bytes);
}
int main(int argc, char **argv) {
if (argc != 3) {
printf("Usage: %s <-f|-m> <file or shared memory name>\n", argv[0]);
return 0;
}
if (!strcmp(argv[1], "-m")) {
use_shared_memory = true;
} else if (!strcmp(argv[1], "-f")) {
use_shared_memory = false;
} else {
printf("Usage: %s <-f|-m> <file or shared memory name>\n", argv[0]);
return 0;
}
// map shared memory here as we don't want to do it
// for every operation
if (use_shared_memory) {
if (!setup_shmem(argv[2])) { printf("Error mapping shared memory\n"); }
}
fuzz(argv[2]);
return 0;
}

View File

@ -254,7 +254,7 @@ where
phantom: _,
} => {
// TODO: The monitor buffer should be added on client add.
let client = &mut monitor.client_stats_mut()[0];
let client = monitor.client_stats_mut_for(0);
client.update_executions(*executions as u64, *time);
client.update_introspection_monitor((**introspection_monitor).clone());
monitor.display(event.name().to_string(), 0);

View File

@ -537,7 +537,7 @@ where
.field("target", &self.target)
.field("args", &self.args)
.field("input_file", &self.input_file)
.field("use_shmem_testcase", &self.uses_shmem_testcase)
.field("uses_shmem_testcase", &self.uses_shmem_testcase)
.field("forkserver", &self.forkserver)
.field("observers", &self.observers)
.field("map", &self.map)

View File

@ -17,7 +17,7 @@ libafl = { path = "../libafl", version = "0.8.0", features = [
"std",
"libafl_derive",
] }
tinyinst-rs = { git = "https://github.com/elbiazo/tinyinst-rs" }
tinyinst = { git = "https://github.com/AFLplusplus/tinyinst-rs" }
# tinyinst-rs = { path = "../../tinyinst-rs" }
[build-dependencies]

View File

@ -1,3 +1,4 @@
# Requirements
- you need `Visual Studio 17 2022`, though it's not tested, it should work on older versions.
- you need `cxxbridge-cmd` to generate bridge files between Rust and c++, you can install this via `cargo install cxxbridge-cmd`
- `Visual Studio 17 2022`. It's not tested, it *should* work on older versions too.
- `cxxbridge-cmd` to generate bridge files between Rust and c++, you can install this with `cargo install cxxbridge-cmd`.
- `cmake` is needed to build tinyinst.

View File

@ -1,27 +1,38 @@
use core::marker::PhantomData;
use std::time::Duration;
use libafl::{
bolts::fs::{InputFile, INPUTFILE_STD},
bolts::{
fs::{InputFile, INPUTFILE_STD},
shmem::{ShMem, ShMemProvider, StdShMemProvider},
AsMutSlice, AsSlice,
},
executors::{Executor, ExitKind, HasObservers},
inputs::{HasTargetBytes, UsesInput},
observers::{ObserversTuple, UsesObservers},
prelude::AsSlice,
state::{State, UsesState},
Error,
};
use tinyinst_rs::tinyinst::{litecov::RunResult, TinyInst};
use tinyinst::tinyinst::{litecov::RunResult, TinyInst};
pub struct TinyInstExecutor<'a, S, OT> {
/// Tinyinst executor
pub struct TinyInstExecutor<'a, S, SP, OT>
where
SP: ShMemProvider,
{
tinyinst: TinyInst,
coverage: &'a mut Vec<u64>,
timeout: u32,
timeout: Duration,
observers: OT,
phantom: PhantomData<S>,
cur_input: InputFile,
use_stdin: bool,
map: Option<<SP as ShMemProvider>::ShMem>,
}
impl<'a, S, OT> std::fmt::Debug for TinyInstExecutor<'a, S, OT> {
impl<'a, S, SP, OT> std::fmt::Debug for TinyInstExecutor<'a, S, SP, OT>
where
SP: ShMemProvider,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TinyInstExecutor")
.field("timeout", &self.timeout)
@ -29,11 +40,12 @@ impl<'a, S, OT> std::fmt::Debug for TinyInstExecutor<'a, S, OT> {
}
}
impl<'a, EM, S, Z, OT> Executor<EM, Z> for TinyInstExecutor<'a, S, OT>
impl<'a, EM, S, SP, OT, Z> Executor<EM, Z> for TinyInstExecutor<'a, S, SP, OT>
where
EM: UsesState<State = S>,
S: UsesInput,
S::Input: HasTargetBytes,
SP: ShMemProvider,
Z: UsesState<State = S>,
{
#[inline]
@ -44,9 +56,23 @@ where
_mgr: &mut EM,
input: &Self::Input,
) -> Result<ExitKind, Error> {
if !self.use_stdin {
match &self.map {
Some(_) => {
// use shmem to pass testcase
let shmem = unsafe { self.map.as_mut().unwrap_unchecked() };
let target_bytes = input.target_bytes();
let size = target_bytes.as_slice().len();
let size_in_bytes = size.to_ne_bytes();
// The first four bytes tells the size of the shmem.
shmem.as_mut_slice()[..SHMEM_FUZZ_HDR_SIZE]
.copy_from_slice(&size_in_bytes[..SHMEM_FUZZ_HDR_SIZE]);
shmem.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)]
.copy_from_slice(target_bytes.as_slice());
}
None => {
self.cur_input.write_buf(input.target_bytes().as_slice())?;
}
}
#[allow(unused_assignments)]
let mut status = RunResult::OK;
@ -66,53 +92,211 @@ where
}
}
impl<'a, S, OT> TinyInstExecutor<'a, S, OT>
where
OT: ObserversTuple<S>,
S: UsesInput,
{
/// # Safety
pub unsafe fn new(
coverage: &'a mut Vec<u64>,
/// Builder for `TinyInstExecutor`
#[derive(Debug)]
pub struct TinyInstExecutorBuilder<'a, SP> {
tinyinst_args: Vec<String>,
program_args: Vec<String>,
timeout: u32,
observers: OT,
) -> Self {
let mut use_stdin = true;
timeout: Duration,
shmem_provider: Option<&'a mut SP>,
}
let program_args = program_args
const MAX_FILE: usize = 1024 * 1024;
const SHMEM_FUZZ_HDR_SIZE: usize = 4;
impl<'a> Default for TinyInstExecutorBuilder<'a, StdShMemProvider> {
fn default() -> Self {
Self::new()
}
}
impl<'a> TinyInstExecutorBuilder<'a, StdShMemProvider> {
/// Constructor
#[must_use]
pub fn new() -> TinyInstExecutorBuilder<'a, StdShMemProvider> {
Self {
tinyinst_args: vec![],
program_args: vec![],
timeout: Duration::new(3, 0),
shmem_provider: None,
}
}
/// Argument for tinyinst instrumentation
#[must_use]
pub fn tinyinst_arg(mut self, arg: String) -> Self {
self.tinyinst_args.push(arg);
self
}
/// Arguments for tinyinst instrumentation
#[must_use]
pub fn tinyinst_args(mut self, args: Vec<String>) -> Self {
for arg in args {
self.tinyinst_args.push(arg);
}
self
}
/// The module to instrument.
#[must_use]
pub fn instrument_module(mut self, module: Vec<String>) -> Self {
for modname in module {
self.tinyinst_args.push("-instrument_module".to_string());
self.tinyinst_args.push(modname);
}
self
}
/// Use shmem
#[must_use]
pub fn use_shmem(mut self) -> Self {
self.tinyinst_args.push("-delivery".to_string());
self.tinyinst_args.push("shmem".to_string());
self
}
/// Persistent mode
#[must_use]
pub fn persistent(
mut self,
target_module: String,
target_method: String,
nargs: usize,
iterations: usize,
) -> Self {
self.tinyinst_args.push("-target_module".to_string());
self.tinyinst_args.push(target_module);
self.tinyinst_args.push("-target_method".to_string());
self.tinyinst_args.push(target_method);
self.tinyinst_args.push("-nargs".to_string());
self.tinyinst_args.push(nargs.to_string());
self.tinyinst_args.push("-iterations".to_string());
self.tinyinst_args.push(iterations.to_string());
self.tinyinst_args.push("-persist".to_string());
self.tinyinst_args.push("-loop".to_string());
self
}
/// Program arg
#[must_use]
pub fn program_arg(mut self, arg: String) -> Self {
self.program_args.push(arg);
self
}
/// Program args
#[must_use]
pub fn program_args(mut self, args: Vec<String>) -> Self {
for arg in args {
self.program_args.push(arg);
}
self
}
/// Set timeout
#[must_use]
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
/// Use this to enable shmem testcase passing.
#[must_use]
pub fn shmem_provider<SP: ShMemProvider>(
self,
shmem_provider: &'a mut SP,
) -> TinyInstExecutorBuilder<'a, SP> {
TinyInstExecutorBuilder {
tinyinst_args: self.tinyinst_args,
program_args: self.program_args,
timeout: self.timeout,
shmem_provider: Some(shmem_provider),
}
}
}
impl<'a, SP> TinyInstExecutorBuilder<'a, SP>
where
SP: ShMemProvider,
{
/// Build tinyinst executor
pub fn build<OT, S>(
&mut self,
coverage: &'a mut Vec<u64>,
observers: OT,
) -> Result<TinyInstExecutor<'a, S, SP, OT>, Error> {
let (map, shmem_id) = match &mut self.shmem_provider {
Some(provider) => {
// setup shared memory
let mut shmem = provider.new_shmem(MAX_FILE + SHMEM_FUZZ_HDR_SIZE)?;
let shmem_id = shmem.id();
// println!("{:#?}", shmem.id());
// shmem.write_to_env("__TINY_SHM_FUZZ_ID")?;
let size_in_bytes = (MAX_FILE + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes();
shmem.as_mut_slice()[..4].clone_from_slice(&size_in_bytes[..4]);
(Some(shmem), Some(shmem_id))
}
None => (None, None),
};
let mut has_input = false;
let program_args: Vec<String> = self
.program_args
.clone()
.into_iter()
.map(|arg| {
if arg == "@@" {
println!("Not using stdin");
use_stdin = false;
INPUTFILE_STD.to_string()
has_input = true;
match shmem_id {
Some(shmem_name) => shmem_name.to_string(),
None => INPUTFILE_STD.to_string(),
}
} else {
arg
}
})
.collect();
let cur_input = InputFile::create(INPUTFILE_STD).expect("Unable to create cur_file");
println!("post init");
let tinyinst = TinyInst::new(tinyinst_args, program_args, timeout);
if !has_input {
return Err(Error::unknown(
"No input file or shmem provided".to_string(),
));
}
println!("tinyinst args: {:#?}", &self.tinyinst_args);
Self {
let cur_input = InputFile::create(INPUTFILE_STD).expect("Unable to create cur_file");
let tinyinst = unsafe {
TinyInst::new(
&self.tinyinst_args,
&program_args,
self.timeout.as_millis() as u32,
)
};
Ok(TinyInstExecutor {
tinyinst,
coverage,
timeout,
timeout: self.timeout,
observers,
phantom: PhantomData,
cur_input,
use_stdin,
}
map,
})
}
}
impl<'a, S, OT> HasObservers for TinyInstExecutor<'a, S, OT>
impl<'a, S, SP, OT> HasObservers for TinyInstExecutor<'a, S, SP, OT>
where
S: State,
SP: ShMemProvider,
OT: ObserversTuple<S>,
{
fn observers(&self) -> &OT {
@ -123,16 +307,18 @@ where
&mut self.observers
}
}
impl<'a, S, OT> UsesState for TinyInstExecutor<'a, S, OT>
impl<'a, S, SP, OT> UsesState for TinyInstExecutor<'a, S, SP, OT>
where
S: UsesInput,
SP: ShMemProvider,
{
type State = S;
}
impl<'a, S, OT> UsesObservers for TinyInstExecutor<'a, S, OT>
impl<'a, S, SP, OT> UsesObservers for TinyInstExecutor<'a, S, SP, OT>
where
OT: ObserversTuple<S>,
S: UsesInput,
SP: ShMemProvider,
{
type Observers = OT;
}

View File

@ -1 +1,69 @@
/*!
The tinyinst module for `LibAFL`.
*/
#![warn(clippy::cargo)]
#![deny(clippy::cargo_common_metadata)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all)]
#![deny(clippy::pedantic)]
#![allow(
clippy::unreadable_literal,
clippy::type_repetition_in_bounds,
clippy::missing_errors_doc,
clippy::cast_possible_truncation,
clippy::used_underscore_binding,
clippy::ptr_as_ptr,
clippy::missing_panics_doc,
clippy::missing_docs_in_private_items,
clippy::module_name_repetitions,
clippy::unreadable_literal
)]
#![cfg_attr(not(test), warn(
missing_debug_implementations,
missing_docs,
//trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
//unused_results
))]
#![cfg_attr(test, deny(
missing_debug_implementations,
missing_docs,
//trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_must_use,
missing_docs,
//unused_results
))]
#![cfg_attr(
test,
deny(
bad_style,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
no_mangle_generic_items,
overflowing_literals,
path_statements,
patterns_in_fns_without_body,
private_in_public,
unconditional_recursion,
unused,
unused_allocation,
unused_comparisons,
unused_parens,
while_true
)
)]
// Till they fix this buggy lint in clippy
#![allow(clippy::borrow_as_ptr)]
#![allow(clippy::borrow_deref_ref)]
/// Tinyinst executor
pub mod executor;