Giter Site home page Giter Site logo

d0c-s4vage / gramfuzz Goto Github PK

View Code? Open in Web Editor NEW
243.0 18.0 42.0 6.34 MB

gramfuzz is a grammar-based fuzzer that lets one define complex grammars to generate text and binary data formats.

Home Page: https://d0c-s4vage.github.io/gramfuzz/

License: MIT License

Shell 0.28% Python 99.72%
grammar parsing fuzzing complex-grammars fuzzer

gramfuzz's People

Contributors

d0c-s4vage avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gramfuzz's Issues

Feature Request: Weighted Or (already have implementation to use)

Is your feature request related to a problem? Please describe

A request for Or() but with weights
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Or() equally gives each option the same probability.

Describe the solution you'd like

Each statement in the Or is in a tuple of which the first is the option the or chooses and second is the probability that the option is taken.
A clear and concise description of what you want to happen.

Describe alternatives you've considered

class WeightedOr(Field):
    """A ``Field`` subclass that chooses one of the provided values at
    random as the result of a call to the ``build()`` method. Takes an
    odds array rather than just direct values."""
    def __init__(self, *values, **kwargs):
        '''
        values is a list of tuples
        '''
        self.shortest_vals = None
        vals=[x[0] for x in values]
        self.values= list(map(maybe_binstr, vals))
        self.weights = [x[1] for x in values]
        #print(self.weights)
        if abs(1.0 - sum(self.weights)) > 0.0001:
            raise("Weights in WeightedOr don't sum to 1.0: {}".format(self.weights))
        if "options" in kwargs and len(values) == 0:
            self.values = list(map(maybe_binstr, kwargs["options"]))
        self.rolling = kwargs.setdefault("rolling", False)
    def build(self, pre=None, shortest=False):
        """
        :param list pre: The prerequisites list
        :param bool shortest: Whether or not the shortest reference-chain (most minimal) 
        version of the field should be generated.
        """
        #self.values=list(map(val, self.values))
        #self.shortest_vals=list(map(val, self.values))
        if pre is None:
            pre = []
        # self.shortest_vals will be set by the GramFuzzer and will
        # contain a list of value options that have a minimal reference chain
        if shortest and self.shortest_vals is not None:
            return utils.val(random.choices(self.shortest_vals, self.weights)[0], pre, shortest=shortest)
        else:
            return utils.val(random.choices(self.values, self.weights)[0], pre, shortest=shortest)

A clear and concise description of any alternative solutions or features you've considered.
implementation of solution

Additional context

Add any other context or screenshots about the feature request here.

Error in example.py writing to stdout with example.py

Discovered looking into #26

Traceback (most recent call last):
  File "example.py", line 96, in <module>
    main(sys.argv[1:])
  File "example.py", line 91, in main
    seed          = args.seed,
  File "example.py", line 37, in generate
    output.write(res)
TypeError: write() argument must be str, not bytes

add feature - relations

Would be nice to have some kind of predefined relations to make it more customizable, i mean something like:

RDef("value",
    Int | Float | RRef("boolean") | RRef("key") | UInt | UFloat | RRef("null")
)
RDef("key-object",

     RRef("key", relation=relation.sizeOf("value")) & ":"
 
)

Something similar would allow more flexibility!

Regards,
Daniele Linguaglossa

Can the documentation describe the syntax of multi-level relationships in more detail?

I want to use gramfuzz to generate some http package formats, but when I encounter the logic of two layers, I can't understand it. I checked the document, but there is no tree case with more than two layers. Can you help me to see my mistake ?

from gramfuzz.fields import *

class RDef(Def): cat="http-def"
class RRef(Ref): cat="http-def"

# top-level rule
Def("http",
    Join(
        Opt(RRef("request-line")),
        Opt(RRef("base")),
        Opt(RRef("the-rest")),
        sep=" "
    ),
    cat="http"
)

# helper rules
RDef("request-line",
    RRef("method-name"), RRef("space"), RRef("uri"), RRef("space"), RRef("protocol"), RRef("separator"), RRef("version"), RRef("newline")
)
RDef("method-name",
    Or("GET" , "HEAD" , "POST" , "PUT" , "DELETE" , "CONNECT" , "OPTIONS" , "TRACE" , "PATCH")
)
RDef("space",
    " "
)
RDef("uri",
    "http://localhost"
)
RDef("protocol",
    "HTTP"
)
RDef("separator",
    "/"
)
RDef("vsrsion",
    Or("0.9" , "1.0" , "1.1")
)
RDef("newline",
    "\r\n"
)
RDef("base",
    "Host: _HOST_\r\nConnection:close\r\nX-Request-ID: _REQUEST_ID_\r\n"
)
RDef("the-rest",
    "Content-Length: 5\r\n\r\nBBBBBBBBBB"
)

output:

http : referenced definition ('request-line') not defined
Traceback (most recent call last):
  File "fuzz.py", line 17, in <module>
    for roman_numeral in fuzzer.gen(cat="http", num=10):
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/__init__.py", line 504, in gen
    val_res = _val(v, pre)
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/utils.py", line 35, in val
    val = val.build(pre, shortest=shortest)
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/fields.py", line 782, in build
    res.append(utils.val(value, pre, shortest=shortest))
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/utils.py", line 35, in val
    val = val.build(pre, shortest=shortest)
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/fields.py", line 424, in build
    v = utils.val(val, pre, shortest=shortest)
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/utils.py", line 35, in val
    val = val.build(pre, shortest=shortest)
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/fields.py", line 698, in build
    return super(Opt, self).build(pre, shortest=shortest)
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/fields.py", line 461, in build
    res.append(utils.val(x, pre, shortest=shortest))
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/utils.py", line 35, in val
    val = val.build(pre, shortest=shortest)
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/fields.py", line 858, in build
    definition = self.fuzzer.get_ref(self.cat, self.refname)
  File "/home/taolaw/.local/lib/python3.8/site-packages/gramfuzz/__init__.py", line 406, in get_ref
    raise errors.GramFuzzError("referenced definition ({!r}) not defined".format(refname))
gramfuzz.errors.GramFuzzError: referenced definition ('request-line') not defined

UnicodeDecodeError: 'ascii' codec can't decode byte 0xcb in position 2542: ordinal not in range(128)

After creating the issue, checkboxes will appear where [] label exist in the
markdown. You can check/uncheck them to fill out the environment section.

Checklist

  • [ x ] I have included the [relevant portions of the] grammar used that caused the bug
  • [ x ] I have filled out the environment section

Environment

Platform

  • Windows
  • Mac
  • [ x ] Linux
  • Other (please specify)

Python Version

  • Python 2.7
  • Python 3.4
  • Python 3.5
  • [ x ] Python 3.6
  • Python 3.7
  • Python 3.8
  • Other (please specify)

Describe the bug

A clear and concise description of what the bug is.
The file isn't opened with the encoding='utf-8' flag so I end with this error when I run main.py https://github.com/mgree/smoosh-fuzz/blob/master/src/posix/main.py in ubuntu docker python3

  File "main.py", line 4, in <module>
    fuzzer.load_grammar('words.py')
  File "/usr/local/lib/python3.6/dist-packages/gramfuzz/__init__.py", line 125, in load_grammar
    data = f.read()
  File "/usr/lib/python3.6/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xcb in position 2542: ordinal not in range(128)

To Reproduce

The issue is in the function load_grammar in class GramFuzzer:
--->here: with open(path, "r", WE NEED: encoding='utf-8') as f:
data = f.read()
code = compile(data, path, "exec")
Steps to reproduce

Expected Behavior

I expected the behavior to be the same as in Python3.7 on Mac- a grammar is generated and strings from that grammar.
A clear and concise description of what you expected to happen.

add some example grammars

Add some example grammars:

  • python 2.7 grammar
  • us postal addresses
  • roman numerals

Make a note of how the us postal address grammar can import/require the roman numeral grammar

Thanks for implementing the feature but there is a small bug

After creating the issue, checkboxes will appear where [] label exist in the
markdown. You can check/uncheck them to fill out the environment section.

Checklist

  • [ x ] I have included the [relevant portions of the] grammar used that caused the bug
  • I have filled out the environment section

Environment

Platform

  • Windows
  • [ x ] Mac
  • Linux
  • Other (please specify)

Python Version

  • [ x ] Python 2.7
  • Python 3.4
  • Python 3.5
  • Python 3.6
  • Python 3.7
  • Python 3.8
  • Other (please specify)

Describe the bug

A clear and concise description of what the bug is.
I am getting does not add to 1.0 when the probabilities do.
I am currently using my own weightedOr but when I switch to the one in gramfuzz under Python2.7 I get errors. This code builds in main.py
https://github.com/mgree/smoosh-fuzz/blob/master/src/posix/words.py

Steps to reproduce

Expected Behavior

A clear and concise description of what you expected to happen.
I expected the grammar to run. Also I was using Python3 and am having trouble installing the package. In Python2.7 it works fine but I get the bug about probabilities not summing to 1.

Error raise errors.GramFuzzError("referenced definition ({!r}) not defined".format(refname))

After creating the issue, checkboxes will appear where [] label exist in the
markdown. You can check/uncheck them to fill out the environment section.

Checklist

  • [ X] I have included the [relevant portions of the] grammar used that caused the bug
  • [ X] I have filled out the environment section

Environment

Platform

  • Windows
  • [ X] Mac
  • Linux
  • Other (please specify)

Python Version

  • [ X] Python 2.7
  • Python 3.4
  • Python 3.5
  • Python 3.6
  • [ X] Python 3.7
  • Python 3.8
  • Other (please specify)

Describe the bug

A clear and concise description of what the bug is.
Mutual recursion fails on some cases.

To Reproduce

NDef("nl", NRef("newline_list"))
NDef("newline_list", WeightedOr(
                    (NRef("NEWLINE"), 0.95),
                    (And(
                        NRef("nl"),
                        NRef("NEWLINE")
                        ), 0.05)
                    )
)

Steps to reproduce

Expected Behavior

Even when I pass a reference to a different statement, using mutual recursion
results in a large amount of errors.
A clear and concise description of what you expected to happen.
It is expected that a string is still generated from the grammar regardless of mutual recursion as most grammars use this. Additionally, I am still using my own WeightedOr implementation since gramfuzz's has errors with the probabilities not summing to 1 when they do(i.e 1.0!=1 so we get an error saying probabilities don't add up to 1)

TypeError when using String-Field with value parameter

Checklist

  • I have included the [relevant portions of the] grammar used that caused the bug
  • I have filled out the environment section

Environment

Platform

  • Windows
  • Mac
  • Linux
  • Other (please specify)

Python Version

  • Python 2.7
  • Python 3.4
  • Python 3.5
  • Python 3.6
  • Python 3.7
  • Python 3.8
  • Other (please specify)

Describe the bug

When using a String-Field with predefined value and min/max this error randomly occurs:
TypeError: 'bytes' object cannot be interpreted as an integer

gramfuzz tries to use the value of the String-Field as length which fails because the value is a string.

To Reproduce

Grammar:

class TRef(Ref):
    cat = "test_string_error"

class TDef(Def):
    cat = "test_string_error"

Def("error_test", TRef("field"), cat="transport_header")

TDef("field", String("TEST", min=0, max=8))

Execute

    fuzzer = gramfuzz.GramFuzzer()
    gramfuzz.rand.seed(2)
    fuzzer.load_grammar("grammar.py")
    # will trigger the error, if 2 instead of 3 is used no error occurs
    data = fuzzer.gen(3, cat="test_string_error")  

Expected Behavior

gramfuzz generates multiple strings with different lengths as stated in the grammar.

Python3 : NameError: name 'NEWLINE' is not defined

Throws exception "Python3 : NameError: name 'NEWLINE' is not defined" when running

$ python example.py -g python27 -n 1 -s 13337 --max-recursion 7

Output:

...
  File "../gramfuzz/utils.py", line 35, in val
    val = val.build(pre, shortest=shortest)
  File "../gramfuzz/fields.py", line 445, in build
    res.append(utils.val(x, pre, shortest=shortest))
  File "../gramfuzz/utils.py", line 35, in val
    val = val.build(pre, shortest=shortest)
  File "grams/python27.py", line 40, in build
    return NEWLINE().build(pre, shortest=shortest)
NameError: name 'NEWLINE' is not defined

Running with --max-recursion of 6 or lower works ok:

$ python3 example.py -g python27 -n 1 -s 13337 --max-recursion 6

Error with `Int` field: doesn't respect min/max

Checklist

  • I have included the [relevant portions of the] grammar used that caused the bug
  • I have filled out the environment section

Environment

Platform

  • Windows
  • Mac
  • Linux
  • Other (please specify)

Python Version

  • Python 2.7
  • Python 3.4
  • Python 3.5
  • Python 3.6
  • Python 3.7
  • Python 3.8
  • Other (please specify)

Describe the bug

Setting min and max doesn't seem to affect the Int field's behavior. The Int.build() method only checks to see whether min/max constrain a single value rather than using it has a general set of constraints.

To Reproduce

>>> from gramfuzz.fields import Int
>>> g = Int(min = 0, max=65535)
>>> g.build()
4038
>>> g.build()
-2592

Expected Behavior

I expect no values below min or above max to be generated.

Current Workaround

I use UInt with an explicit odds setting.

deal with recursion problems by determining the shortest resolvable reference

Grammar rules that generate lists work well for parsing, but are a pain when using them to generate data. E.g. from the python 2.7 grammar, there's the fpdef and fplist rules. Currently gramfuzz almost always runs into recursion errors when building the fpdef and fplist rules:

fpdef: NAME | '(' fplist ')'
fplist: fpdef (',' fpdef)* [',']

gramfuzz should be able to process all defined rules in a category and determine its distance from a leaf node, as well as each option inside an Or to determine which option gives the shortest resolvable path. This can then be used to determine the shortest-path to generating a rule without chancing recursion errors.

Loading grammars does not use globals() and locals() correctly

Problem

As described in #26 , methods on a class in a loaded grammar don't have access to other classes in the same grammar file:

class DEDENT(Field):
    def build(self, pre=None, shortest=False):
        global INDENT_LEVEL
        INDENT_LEVEL -= 1
        return NEWLINE().build(pre, shortest=shortest)

class NEWLINE():
    # ...

When DEDENT.build() is called, NEWLINE is not defined in the current scope

References

https://stackoverflow.com/questions/2904274/globals-and-locals-in-python-exec

add feature to import [e]bnf grammars

gramfuzz should have a method analogous to the load_grammar method that will parse a grammar file and create analogous gramfuzz structures in memory. Maybe something like:

fuzzer.import_grammar("path/to/test_grammar.bnf", type="bnf")

Both ebnf and bnf grammars should be allowed.

aside it may be cool (not sure how useful really though) to export grammar rules from memory into a file as well.

add feature to import dharma grammars

gramfuzz should have a method analogous to the load_grammar method that will parse a grammar file and create analogous gramfuzz structures in memory. Maybe something like:

fuzzer.import_grammar("path/to/test_grammar.bnf", type="dharma")

This is related to #6

Error

After creating the issue, checkboxes will appear where [] label exist in the
markdown. You can check/uncheck them to

Checklist

  • I have included the [relevant portions of the] grammar used that caused the bug
  • I have filled out the environment section

Environment

  • Windows

  • Mac

  • Linux

  • Python 2.7

  • Python 3.4

  • Python 3.5

  • Python 3.6

  • Python 3.7

  • Python 3.8

  • Other (please specify)

Describe the bug

A clear and concise description of what the bug is.

To Reproduce

Steps to reproduce

Expected Behavior

A clear and concise description of what you expected to happen.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.