Fix fuzzers after HasTestcase (#1123) (#1162)

* Fix fuzzers after HasTestcase (#1123)

* Make the trait a trait

* Implement HasTestcase for Corpora

* fix

* fix

* a

* a

* fix

* wasm32

* a

* f

* f

* aa

---------

Co-authored-by: tokatoka <tokazerkje@outlook.com>
This commit is contained in:
Dominik Maier 2023-03-19 03:58:32 +01:00 committed by GitHub
parent bbe4e85768
commit f4f23de32b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 181 additions and 56 deletions

View File

@ -181,6 +181,8 @@ jobs:
run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade
- name: Add no_std toolchain - 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 run: rustup toolchain install nightly-x86_64-unknown-linux-gnu ; rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- name: Add wasm target
run: rustup target add wasm32-unknown-unknown
- name: Install cxxbridge - name: Install cxxbridge
if: runner.os == 'macOS' if: runner.os == 'macOS'
run: cargo install cxxbridge-cmd run: cargo install cxxbridge-cmd

View File

@ -74,7 +74,11 @@ pub fn main() {
) )
.unwrap(); .unwrap();
if state.metadata_map().get::<NautilusChunksMetadata>().is_none() { if state
.metadata_map()
.get::<NautilusChunksMetadata>()
.is_none()
{
state.add_metadata(NautilusChunksMetadata::new("/tmp/".into())); state.add_metadata(NautilusChunksMetadata::new("/tmp/".into()));
} }

View File

@ -8,7 +8,7 @@ use libafl::{
rands::StdRand, rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider}, shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, MatchName, Merge}, tuples::{tuple_list, MatchName, Merge},
AsMutSlice, AsMutSlice, Truncate,
}, },
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager, events::SimpleEventManager,
@ -22,7 +22,7 @@ use libafl::{
inputs::BytesInput, inputs::BytesInput,
monitors::SimpleMonitor, monitors::SimpleMonitor,
mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens},
observers::{HitcountsMapObserver, MapObserver, StdMapObserver, TimeObserver}, observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::{HasCorpus, HasMetadata, StdState}, state::{HasCorpus, HasMetadata, StdState},

View File

@ -8,7 +8,7 @@ use libafl::{
rands::StdRand, rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider}, shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, MatchName, Merge}, tuples::{tuple_list, MatchName, Merge},
AsMutSlice, AsMutSlice, Truncate,
}, },
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager, events::SimpleEventManager,
@ -22,7 +22,7 @@ use libafl::{
inputs::BytesInput, inputs::BytesInput,
monitors::SimpleMonitor, monitors::SimpleMonitor,
mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens},
observers::{HitcountsMapObserver, MapObserver, StdMapObserver, TimeObserver}, observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::{HasCorpus, HasMetadata, StdState}, state::{HasCorpus, HasMetadata, StdState},

View File

@ -81,7 +81,7 @@ mkdir in || true
echo a > in/a echo a > in/a
# Allow sigterm as exit code # Allow sigterm as exit code
timeout 11s ./${FUZZER_NAME} -o out -i in >fuzz_stdout.log || true timeout 11s ./${FUZZER_NAME} -o out -i in >fuzz_stdout.log || true
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then if [ -z "$(grep "objectives: 10" fuzz_stdout.log)" ]; then
echo "Fuzzer does not generate any testcases or any crashes" echo "Fuzzer does not generate any testcases or any crashes"
exit 1 exit 1
else else

View File

@ -82,7 +82,7 @@ mkdir in || true
echo a > in/a echo a > in/a
# Allow sigterm as exit code # Allow sigterm as exit code
timeout 11s ./${FUZZER_NAME} -o out -i in >fuzz_stdout.log || true timeout 11s ./${FUZZER_NAME} -o out -i in >fuzz_stdout.log || true
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then if [ -z "$(grep "objectives: 10" fuzz_stdout.log)" ]; then
echo "Fuzzer does not generate any testcases or any crashes" echo "Fuzzer does not generate any testcases or any crashes"
exit 1 exit 1
else else

View File

@ -105,7 +105,7 @@ script_runner = "@shell"
script=''' script='''
rm -rf libafl_unix_shmem_server || true rm -rf libafl_unix_shmem_server || true
timeout 11s ./${FUZZER_NAME} --cores 0 >fuzz_stdout.log 2>/dev/null || true timeout 11s ./${FUZZER_NAME} --cores 0 >fuzz_stdout.log 2>/dev/null || true
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then if [ -z "$(grep "corpus: 8" fuzz_stdout.log)" ]; then
echo "Fuzzer does not generate any testcases or any crashes" echo "Fuzzer does not generate any testcases or any crashes"
exit 1 exit 1
else else

View File

@ -172,7 +172,11 @@ pub fn libafl_main() {
.unwrap() .unwrap()
}); });
if state.metadata_map().get::<NautilusChunksMetadata>().is_none() { if state
.metadata_map()
.get::<NautilusChunksMetadata>()
.is_none()
{
state.add_metadata(NautilusChunksMetadata::new("/tmp/".into())); state.add_metadata(NautilusChunksMetadata::new("/tmp/".into()));
} }

View File

@ -63,9 +63,10 @@ where
} }
#[inline] #[inline]
fn append_metadata( fn append_metadata<OT>(
&mut self, &mut self,
_state: &mut S, _state: &mut S,
_observers: &OT,
testcase: &mut Testcase<PacketData>, testcase: &mut Testcase<PacketData>,
) -> Result<(), Error> { ) -> Result<(), Error> {
testcase testcase

View File

@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{ corpus::{
inmemory_ondisk::InMemoryOnDiskCorpus, ondisk::OnDiskMetadataFormat, Corpus, CorpusId, inmemory_ondisk::InMemoryOnDiskCorpus, ondisk::OnDiskMetadataFormat, Corpus, CorpusId,
Testcase, HasTestcase, Testcase,
}, },
inputs::{Input, UsesInput}, inputs::{Input, UsesInput},
Error, Error,
@ -130,6 +130,22 @@ where
} }
} }
impl<I> HasTestcase for CachedOnDiskCorpus<I>
where
I: Input,
{
fn testcase(&self, id: CorpusId) -> Result<core::cell::Ref<Testcase<Self::Input>>, Error> {
Ok(self.get(id)?.borrow())
}
fn testcase_mut(
&self,
id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<Self::Input>>, Error> {
Ok(self.get(id)?.borrow_mut())
}
}
impl<I> CachedOnDiskCorpus<I> impl<I> CachedOnDiskCorpus<I>
where where
I: Input, I: Input,

View File

@ -5,6 +5,7 @@ use core::cell::RefCell;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::HasTestcase;
use crate::{ use crate::{
corpus::{Corpus, CorpusId, Testcase}, corpus::{Corpus, CorpusId, Testcase},
inputs::{Input, UsesInput}, inputs::{Input, UsesInput},
@ -381,6 +382,25 @@ where
} }
} }
impl<I> HasTestcase for InMemoryCorpus<I>
where
I: Input,
{
fn testcase(
&self,
id: CorpusId,
) -> Result<core::cell::Ref<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow())
}
fn testcase_mut(
&self,
id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow_mut())
}
}
impl<I> InMemoryCorpus<I> impl<I> InMemoryCorpus<I>
where where
I: Input, I: Input,

View File

@ -13,7 +13,10 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::ondisk::{OnDiskMetadata, OnDiskMetadataFormat}; use super::{
ondisk::{OnDiskMetadata, OnDiskMetadataFormat},
HasTestcase,
};
#[cfg(feature = "gzip")] #[cfg(feature = "gzip")]
use crate::bolts::compress::GzipCompressor; use crate::bolts::compress::GzipCompressor;
use crate::{ use crate::{
@ -134,6 +137,25 @@ where
} }
} }
impl<I> HasTestcase for InMemoryOnDiskCorpus<I>
where
I: Input,
{
fn testcase(
&self,
id: CorpusId,
) -> Result<core::cell::Ref<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow())
}
fn testcase_mut(
&self,
id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow_mut())
}
}
impl<I> InMemoryOnDiskCorpus<I> impl<I> InMemoryOnDiskCorpus<I>
where where
I: Input, I: Input,

View File

@ -1,7 +1,7 @@
//! Corpuses contain the testcases, either in memory, on disk, or somewhere else. //! Corpuses contain the testcases, either in memory, on disk, or somewhere else.
pub mod testcase; pub mod testcase;
pub use testcase::{SchedulerTestcaseMetadata, Testcase}; pub use testcase::{HasTestcase, SchedulerTestcaseMetadata, Testcase};
pub mod inmemory; pub mod inmemory;
pub use inmemory::InMemoryCorpus; pub use inmemory::InMemoryCorpus;
@ -187,7 +187,7 @@ pub mod pybind {
cached::pybind::PythonCachedOnDiskCorpus, inmemory::pybind::PythonInMemoryCorpus, cached::pybind::PythonCachedOnDiskCorpus, inmemory::pybind::PythonInMemoryCorpus,
inmemory_ondisk::pybind::PythonInMemoryOnDiskCorpus, inmemory_ondisk::pybind::PythonInMemoryOnDiskCorpus,
ondisk::pybind::PythonOnDiskCorpus, testcase::pybind::PythonTestcaseWrapper, Corpus, ondisk::pybind::PythonOnDiskCorpus, testcase::pybind::PythonTestcaseWrapper, Corpus,
CorpusId, Testcase, CorpusId, HasTestcase, Testcase,
}, },
inputs::{BytesInput, UsesInput}, inputs::{BytesInput, UsesInput},
Error, Error,
@ -384,6 +384,22 @@ pub mod pybind {
}*/ }*/
} }
impl HasTestcase for PythonCorpus {
fn testcase(
&self,
id: CorpusId,
) -> Result<core::cell::Ref<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow())
}
fn testcase_mut(
&self,
id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow_mut())
}
}
/// Register the classes to the python module /// Register the classes to the python module
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> { pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonCorpus>()?; m.add_class::<PythonCorpus>()?;

View File

@ -9,7 +9,7 @@ use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::CachedOnDiskCorpus; use super::{CachedOnDiskCorpus, HasTestcase};
use crate::{ use crate::{
bolts::serdeany::SerdeAnyMap, bolts::serdeany::SerdeAnyMap,
corpus::{Corpus, CorpusId, Testcase}, corpus::{Corpus, CorpusId, Testcase},
@ -140,6 +140,25 @@ where
} }
} }
impl<I> HasTestcase for OnDiskCorpus<I>
where
I: Input,
{
fn testcase(
&self,
id: CorpusId,
) -> Result<core::cell::Ref<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow())
}
fn testcase_mut(
&self,
id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow_mut())
}
}
impl<I> OnDiskCorpus<I> impl<I> OnDiskCorpus<I>
where where
I: Input, I: Input,

View File

@ -2,18 +2,38 @@
//! It will contain a respective input, and metadata. //! It will contain a respective input, and metadata.
use alloc::string::String; use alloc::string::String;
use core::{default::Default, option::Option, time::Duration}; use core::{
cell::{Ref, RefMut},
default::Default,
option::Option,
time::Duration,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
bolts::{serdeany::SerdeAnyMap, HasLen}, bolts::{serdeany::SerdeAnyMap, HasLen},
corpus::CorpusId, corpus::CorpusId,
inputs::Input, inputs::{Input, UsesInput},
state::HasMetadata, state::HasMetadata,
Error, Error,
}; };
/// Shorthand to receive a [`Ref`] or [`RefMut`] to a stored [`Testcase`], by [`CorpusId`].
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
pub trait HasTestcase: UsesInput {
/// Shorthand to receive a [`Ref`] to a stored [`Testcase`], by [`CorpusId`].
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
fn testcase(&self, id: CorpusId) -> Result<Ref<Testcase<<Self as UsesInput>::Input>>, Error>;
/// Shorthand to receive a [`RefMut`] to a stored [`Testcase`], by [`CorpusId`].
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
fn testcase_mut(
&self,
id: CorpusId,
) -> Result<RefMut<Testcase<<Self as UsesInput>::Input>>, Error>;
}
/// An entry in the Testcase Corpus /// An entry in the Testcase Corpus
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")] #[serde(bound = "I: serde::de::DeserializeOwned")]

View File

@ -8,12 +8,12 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
bolts::{rands::Rand, tuples::Named}, bolts::{rands::Rand, tuples::Named},
corpus::Corpus, corpus::{Corpus, HasTestcase},
generators::GramatronGenerator, generators::GramatronGenerator,
inputs::{GramatronInput, Terminal}, inputs::{GramatronInput, Terminal},
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},
random_corpus_id, random_corpus_id,
state::{HasCorpus, HasMetadata, HasRand, HasTestcase}, state::{HasCorpus, HasMetadata, HasRand},
Error, Error,
}; };

View File

@ -6,11 +6,11 @@ use core::marker::PhantomData;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{Corpus, CorpusId, SchedulerTestcaseMetadata, Testcase}, corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase},
inputs::UsesInput, inputs::UsesInput,
observers::{MapObserver, ObserversTuple}, observers::{MapObserver, ObserversTuple},
schedulers::{powersched::SchedulerMetadata, testcase_score::TestcaseScore, Scheduler}, schedulers::{powersched::SchedulerMetadata, testcase_score::TestcaseScore, Scheduler},
state::{HasCorpus, HasExecutions, HasMetadata, HasRand, HasTestcase, UsesState}, state::{HasCorpus, HasExecutions, HasMetadata, HasRand, UsesState},
Error, Error,
}; };

View File

@ -9,11 +9,11 @@ use core::{marker::PhantomData, time::Duration};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{Corpus, CorpusId, SchedulerTestcaseMetadata, Testcase}, corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase},
inputs::UsesInput, inputs::UsesInput,
observers::{MapObserver, ObserversTuple}, observers::{MapObserver, ObserversTuple},
schedulers::{RemovableScheduler, Scheduler}, schedulers::{RemovableScheduler, Scheduler},
state::{HasCorpus, HasMetadata, HasTestcase, UsesState}, state::{HasCorpus, HasMetadata, UsesState},
Error, Error,
}; };

View File

@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
bolts::rands::Rand, bolts::rands::Rand,
corpus::{Corpus, CorpusId, SchedulerTestcaseMetadata}, corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata},
inputs::UsesInput, inputs::UsesInput,
observers::{MapObserver, ObserversTuple}, observers::{MapObserver, ObserversTuple},
random_corpus_id, random_corpus_id,
@ -18,7 +18,7 @@ use crate::{
testcase_score::{CorpusWeightTestcaseScore, TestcaseScore}, testcase_score::{CorpusWeightTestcaseScore, TestcaseScore},
RemovableScheduler, Scheduler, RemovableScheduler, Scheduler,
}, },
state::{HasCorpus, HasMetadata, HasRand, HasTestcase, UsesState}, state::{HasCorpus, HasMetadata, HasRand, UsesState},
Error, Error,
}; };

View File

@ -11,16 +11,13 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
bolts::{current_time, shmem::ShMemProvider}, bolts::{current_time, shmem::ShMemProvider},
corpus::{Corpus, CorpusId}, corpus::{Corpus, CorpusId, HasTestcase},
events::{llmp::LlmpEventConverter, Event, EventConfig, EventFirer}, events::{llmp::LlmpEventConverter, Event, EventConfig, EventFirer},
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor}, fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor},
inputs::{Input, InputConverter, UsesInput}, inputs::{Input, InputConverter, UsesInput},
stages::Stage, stages::Stage,
state::{ state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasMetadata, HasRand, UsesState},
HasClientPerfMonitor, HasCorpus, HasExecutions, HasMetadata, HasRand, HasTestcase,
UsesState,
},
Error, Error,
}; };

View File

@ -22,7 +22,7 @@ use crate::{
rands::Rand, rands::Rand,
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap}, serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
}, },
corpus::{Corpus, CorpusId, Testcase}, corpus::{Corpus, CorpusId, HasTestcase, Testcase},
events::{Event, EventFirer, LogSeverity}, events::{Event, EventFirer, LogSeverity},
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::{Evaluator, ExecuteInputResult}, fuzzer::{Evaluator, ExecuteInputResult},
@ -219,22 +219,6 @@ pub trait HasStartTime {
fn start_time_mut(&mut self) -> &mut Duration; fn start_time_mut(&mut self) -> &mut Duration;
} }
/// Trait for the testcase
pub trait HasTestcase: HasCorpus {
/// To get the testcase
fn testcase(&self, id: CorpusId) -> Result<Ref<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.corpus().get(id)?.borrow())
}
/// To get mutable testcase
fn testcase_mut(
&self,
id: CorpusId,
) -> Result<RefMut<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.corpus().get(id)?.borrow_mut())
}
}
/// The state a fuzz run. /// The state a fuzz run.
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = " #[serde(bound = "
@ -324,6 +308,26 @@ where
} }
} }
impl<I, C, R, SC> HasTestcase for StdState<I, C, R, SC>
where
I: Input,
C: Corpus<Input = <Self as UsesInput>::Input>,
R: Rand,
{
/// To get the testcase
fn testcase(&self, id: CorpusId) -> Result<Ref<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.corpus().get(id)?.borrow())
}
/// To get mutable testcase
fn testcase_mut(
&self,
id: CorpusId,
) -> Result<RefMut<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.corpus().get(id)?.borrow_mut())
}
}
impl<I, C, R, SC> HasSolutions for StdState<I, C, R, SC> impl<I, C, R, SC> HasSolutions for StdState<I, C, R, SC>
where where
I: Input, I: Input,

View File

@ -23,5 +23,5 @@ fn main() {
} }
} }
log::info!("{}", fuzzers.join("\n")); println!("{}", fuzzers.join("\n"));
} }

View File

@ -9,7 +9,7 @@ extern "C" {
/// Hooked `exit` function /// Hooked `exit` function
#[no_mangle] #[no_mangle]
pub extern "C" fn exit(status: i32) { pub extern "C" fn exit(status: i32) {
log::info!("DeExit: The target called exit with status code {status}"); println!("DeExit: The target called exit with status code {status}");
unsafe { unsafe {
abort(); abort();
} }

View File

@ -165,7 +165,7 @@ fn prepare_transitions(
state_stacks.s.insert(dest, state_stack_sorted); state_stacks.s.insert(dest, state_stack_sorted);
pda.push(transition); pda.push(transition);
log::info!("worklist size: {}", worklist.len()); println!("worklist size: {}", worklist.len());
*state_count += 1; *state_count += 1;
// i += 1; // i += 1;
@ -193,10 +193,10 @@ fn postprocess(pda: &[Transition], stack_limit: usize) -> Automaton {
assert!(initial.len() == 1); assert!(initial.len() == 1);
log::info!("# transitions: {}", pda.len()); println!("# transitions: {}", pda.len());
log::info!("# states: {}", states.len()); println!("# states: {}", states.len());
log::info!("initial state: {:?}", &initial); println!("initial state: {:?}", &initial);
log::info!("final states: {:?}", &finals); println!("final states: {:?}", &finals);
let mut memoized = Vec::with_capacity(states.len()); let mut memoized = Vec::with_capacity(states.len());
//let mut memoized_unique = Vec::with_capacity(states.len()); //let mut memoized_unique = Vec::with_capacity(states.len());
@ -238,7 +238,7 @@ fn postprocess(pda: &[Transition], stack_limit: usize) -> Automaton {
}); });
if num_transition % 4096 == 0 { if num_transition % 4096 == 0 {
log::info!( println!(
"processed {} transitions over {}", "processed {} transitions over {}",
num_transition, num_transition,
culled_pda.len() culled_pda.len()
@ -279,7 +279,7 @@ fn postprocess(pda: &[Transition], stack_limit: usize) -> Automaton {
}); });
if num_transition % 4096 == 0 { if num_transition % 4096 == 0 {
log::info!( println!(
"processed {} transitions over {}", "processed {} transitions over {}",
num_transition, num_transition,
pda.len() pda.len()