-
-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default mutators for String
/str
types?
#6
Comments
I agree :) I don't have any time to work on this at the moment, but I will starting beginning of July. If you don't want to wait a couple months for a String mutator, or if you don't mind spending some time getting familiar with the One problem I have with writing a string mutator is that there are a lot of substrings that we'd like to generate more often than others. Knowing which substrings are interesting is something I need to research more, and it will probably require some unicode knowledge. But of course it doesn't need to be perfect. I think I think we need to create at least two kinds of string mutators. The first kind is for truly arbitrary strings and the second one is for strings that match a regex/grammar. So far I have only played with a prototype for the second kind. |
Quick update to say that I am currently working on a regex-based string mutator. The goal is to be able to write: let string_mutator = regex_based_mutator_or_sth!("(a|b)+[0-9]?"); // impl Mutator<String> We'll see how well it works. I'll try to push it to this repo within two weeks. |
Ah sorry, my inbox filter seemed to miss your earlier message. A regex-conforming mutator would be awesome! An arbitrary string-based one would be useful to, but I would imagine is a subset of the regex-conforming In any case, thanks for your awesome library :D |
Thanks :) I have pushed a lot of commits that I didn't realise were not on Github. Also, I have the first draft of a grammar-based string mutator. I have jotted down a quick summary of the design, which you can read about here if you'd like. It's still very early, not well-tested, and will change a lot. But for now, what one can do is something like: use fuzzcheck_mutators::{concatenation, alternation, repetition, literal};
use fuzzcheck_mutators::grammar::GrammarBasedStringMutator;
// corresponds to [a-z][a-z0-9]{5,10}[0-9]{2,6}z)
// the type is Grammar. It is easy to create it without a macro, but a bit more verbose
let grammar = concatenation! {
literal!('a' ..= 'z'),
repetition! {
literal!(('a'..='z'), ('0'..='9')),
5..=10
},
repetition! {
literal!('0'..='9'),
2 ..= 6
},
literal!('z')
};
let mutator = GrammarBasedStringMutator::new(grammar); // impl Mutator<String> I don't know when all that will make it to a release. |
Hi just wondering how I can combine this with the struct based approach. For example I have this struct and due to the strings the derive will fail to compile. The struct is used within another struct. And i wonder how I can now use that grammar based mutator with that. Code I used before with arbitrary is this: use serde::{Deserialize, Serialize};
#[cfg_attr(test, derive(fuzzcheck::DefaultMutator))]
#[derive(Serialize, Deserialize, Clone, Debug, arbitrary::Arbitrary)]
#[serde(rename_all = "lowercase")]
pub enum RegisterKind {
Guest,
User,
}
#[cfg_attr(test, derive(fuzzcheck::DefaultMutator))]
#[derive(Serialize, Deserialize, Clone, Debug, arbitrary::Arbitrary)]
pub struct AuthenticationData {
pub session: String,
#[serde(rename = "type")]
pub register_type: String,
}
#[cfg_attr(test, derive(fuzzcheck::DefaultMutator))]
#[derive(Serialize, Deserialize, Clone, Debug, arbitrary::Arbitrary)]
pub struct DummyRegistrationJson {
pub kind: RegisterKind,
pub auth: AuthenticationData,
pub device_id: String,
pub inhibit_login: bool,
pub initial_device_display_name: String,
pub password: String,
pub username: String,
} |
Hi! #[derive(.., DefaultMutator)]
struct AuthenticationData {
#[field_mutator(GrammarBasedStringMutator = { grammar_based_string_mutator(regex("[a-z0-9]+")) })]
session: String
} But I've temporarily removed grammar-based string mutators because they were broken. So for now, all the grammar-based stuff can only produce values of type So for a proper solution, you may need to wait maybe a month or two :( There is a workaround that works if you're ok with a non-grammar-based #![feature(no_coverage)]
// I'm sure there is a way to do it without those two extra features, but it requires a lot more work
#![feature(trivial_bounds)]
#![feature(type_alias_impl_trait)]
use fuzzcheck::{Mutator, DefaultMutator};
use fuzzcheck::mutators::map::MapMutator;
type StringMutator = impl Mutator<String>;
fn string_mutator() -> StringMutator {
MapMutator::new(
// the base mutator produces values of type Vector<u8>
<Vec<u8>>::default_mutator(),
// the parse function: given a string, how can I get a vector?
|string: &String| Some(string.as_bytes().to_vec()),
// the map function: how can I get a string from a vector?
|xs| String::from_utf8_lossy(&xs).to_string(),
// the complexity function
|_, cplx| cplx,
)
}
// we can't use DefaultMutator here yet, that should be fixed at some point in the future
#[derive(Clone, serde::Serialize, serde::Deserialize)]
struct AuthenticationData {
session: String
}
// instead, we use the more customisable make_mutator! macro
fuzzcheck::make_mutator! {
// name of the generated mutator
name: AuthenticationDataMutator,
// whether AuthenticationData should implement DefaultMutator
default: true,
// we repeat the type declaration
type:
struct AuthenticationData {
// this field is generated by a `StringMutator`, which is initialised by the code between the curly braces
#[field_mutator(StringMutator = { string_mutator() })]
session: String,
}
}
#[test]
fn fuzz() {
let mutator = AuthenticationData::default_mutator();
// ...
} |
Ah ok. Thanks for that example though. I think the workaround will do it for now as I am still evaluating options for a fuzzer in the project. (Mostly as by now all I tested behaved very different to exactly the same code :( ) |
Hm does the example miss something? I am getting a lot of not satisfied trait bounds with it:
|
ah, I got rid of all those trait requirements recently, but forgot those changes didn't make it to fuzzcheck 0.9. I'll publish a quick update next week so that you can run this code, and maybe ship a String mutator as well. Sorry about this! |
Ah ok :) No problem 👍 |
Hello! I have released fuzzcheck 0.10 with a default string mutator based on |
Thanks, it seems to work now :) |
Hi. was there any update on this? :) |
No, sorry, I don't see how to do it :/ What I'll do then in the meantime is provide a naive implementation of it. In the documentation, it will say that you can't use it for ambiguous grammars such as |
This would be a nice addition :)
(I am currently using a
Vec<u8>
, and then converting this intoString
s, but I suspect that this is suboptimal)If you could suggest how to do this (just the general approach) I would also be happy to try to implement this.
The text was updated successfully, but these errors were encountered: