Beispiel #1
0
    def build(self, pre=None, shortest=False):
        """Build this rule definition
        
        :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.
        """
        if pre is None:
            pre = []

        res = deque()
        for value in self.values:
            try:
                res.append(utils.val(value, pre, shortest=shortest))
            except errors.FlushGrams as e:
                prev = "".join(res)
                res.clear()
                # this is assuming a scope was pushed!
                if len(self.fuzzer._scope_stack) == 1:
                    pre.append(prev)
                else:
                    stmts = self.fuzzer._curr_scope.setdefault(
                        "prev_append", deque())
                    stmts.extend(pre)
                    stmts.append(prev)
                    pre.clear()
                continue
            except errors.OptGram as e:
                continue
            except errors.GramFuzzError as e:
                print("{} : {}".format(self.name, str(e)))
                raise

        return self.sep.join(res)
Beispiel #2
0
    def build(self, pre=None, shortest=False):
        """Build the ``Or`` instance

        :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.
        """
        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(rand.choice(self.shortest_vals), pre, shortest=shortest)
        else:
            return utils.val(rand.choice(self.values), pre, shortest=shortest)
Beispiel #3
0
    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.
        """
        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
        # 
        # see https://narly.me/posts/controlling-recursion-depth-in-grammars/
        # for an in-depth discussion
        if shortest and self.shortest_vals is not None:
            chosen_weights = [self.weights[idx] for idx in self.shortest_indices]
            chosen_vals = self.shortest_vals

            total_percent = sum(chosen_weights)
            # scale the percent weights up if the new chosen weights don't sum
            # to 1.0
            if total_percent != 1.0:
                scale = 1.0 / total_percent
                chosen_weights = [x * scale for x in chosen_weights]
        else:
            chosen_weights = self.weights
            chosen_vals = self.values

        val = rand.weighted_choice(chosen_vals, chosen_weights)
        return utils.val(val, pre, shortest=shortest)
Beispiel #4
0
    def test_or_probabilities(self):
        """Make sure that Or does its probabilities correctly
        """
        # for two items, their probability of being generated should
        # be 50%

        hello_count = 0
        int_count = 0
        data = Or(UInt, "hello")

        for x in six.moves.range(LOOP_NUM):
            res = data.build()
            val = gutils.val(res)
            if val == b"hello":
                hello_count += 1
            elif re.match(gutils.binstr(r'^\d+$'), val) is not None:
                int_count += 1
            else:
                self.assertTrue(False, "was neither an int or hello")

        for v in [hello_count, int_count]:
            percent = v / float(LOOP_NUM)
            diff = abs(percent - 0.50)
            self.assertLess(
                diff, PERCENT_ERROR,
                "{}/{} == {}% error, bad".format(v, LOOP_NUM, diff))
Beispiel #5
0
    def build(self, pre=None, shortest=False):
        """Build the ``Ref`` instance by fetching the rule from
        the GramFuzzer instance and building it

        :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.
        """
        global REF_LEVEL
        REF_LEVEL += 1

        try:
            if pre is None:
                pre = []

            #print("{:04d} - {} - {}:{}".format(REF_LEVEL, shortest, self.cat, self.refname))

            definition = self.fuzzer.get_ref(self.cat, self.refname)
            res = utils.val(definition,
                            pre,
                            shortest=(shortest
                                      or REF_LEVEL >= self.max_recursion))

            return res

        # this needs to happen no matter what
        finally:
            REF_LEVEL -= 1
Beispiel #6
0
    def build(self, pre=None, shortest=False):
        """Build the ``Join`` field instance.
        
        :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.
        """

        if pre is None:
            pre = []

        if self.max is not None:
            if shortest:
                vals = [self.values[0]]
            else:
                # +1 to make it inclusive
                vals = [self.values[0]] * rand.randint(1, self.max + 1)
        else:
            vals = self.values

        joins = []
        for val in vals:
            try:
                v = utils.val(val, pre, shortest=shortest)
                joins.append(v)
            except errors.OptGram as e:
                continue
        return self.sep.join(joins)
Beispiel #7
0
    def build(self, pre=None, shortest=False):
        """Build the String instance

        :param list pre: The prerequisites list (optional, default=None)
        :param bool shortest: Whether or not the shortest reference-chain (most minimal) version of the field should be generated.
        """
        if pre is None:
            pre = []

        if self.value is not None and rand.maybe():
            return utils.val(self.value, pre, shortest=shortest)

        length = super(String, self).build(pre, shortest=shortest)
        res = rand.data(length, self.charset)
        return res
Beispiel #8
0
    def test_weighted_or_probabilities(self):
        """Make sure that WeightedOr does its probabilities correctly
        """
        counts = {
            "int": {
                "prob": 0.1,
                "val": UInt,
                "count": 0,
                "match": lambda x: re.match(gutils.binstr(r'^\d+$'), x) is not None
            },
            "hello": {
                "prob": 0.6,
                "val": b"hello",
                "count": 0,
                "match": lambda x: x == b"hello"
            },
            "a": {
                "prob": 0.3,
                "val": b"a",
                "count": 0,
                "match": lambda x: x == b"a"
            },
        }
        values = [(v["val"], v["prob"]) for k, v in counts.items()]
        data = WeightedOr(*values)

        for x in six.moves.range(LOOP_NUM):
            res = data.build()
            val = gutils.val(res)
            matched = False
            for val_name, val_info in counts.items():
                if val_info["match"](val):
                    val_info["count"] += 1
                    matched = True
            if matched is False:
                raise Exception("Something went wrong, could not match to a value")

        for val_name, val_info in counts.items():
            percent = val_info["count"] / float(LOOP_NUM)
            diff = abs(percent - val_info["prob"])
            self.assertLess(diff, PERCENT_ERROR, "{}: {}/{} == {}% error, bad".format(
                val_name,
                val_info["count"],
                LOOP_NUM,
                diff
            ))
Beispiel #9
0
    def build(self, pre=None, shortest=False):
        """Build the integer, optionally providing a ``pre`` list
        that *may* be used to define prerequisites for a Field being built.

        :param list pre: A list of prerequisites to be collected during the building of a Field.
        :param bool shortest: Whether or not the shortest reference-chain (most minimal) version of the field should be generated.
        """
        if pre is None:
            pre = []

        if self.value is not None and rand.maybe():
            return utils.val(self.value, pre, shortest=shortest)

        if self.min == self.max:
            return self.min

        return self._odds_val()
Beispiel #10
0
    def build(self, pre=None, shortest=False):
        """Build the ``Or`` instance

        :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.
        """
        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
        # 
        # see https://narly.me/posts/controlling-recursion-depth-in-grammars/
        # for an in-depth discussion
        if shortest and self.shortest_vals is not None:
            chosen_val = rand.choice(self.shortest_vals)
        else:
            chosen_val = rand.choice(self.values)

        return utils.val(chosen_val, pre, shortest=shortest)
Beispiel #11
0
 def test_uint(self):
     i = UInt
     res = i().build()
     val = gutils.val(res)
     self.assertRegexpMatches(val, gutils.binstr(r'^\d+$'))
Beispiel #12
0
 def test_or_explicit(self):
     data = Or(UInt, "hello")
     res = data.build()
     val = gutils.val(res)
     self.assertRegexpMatches(val, gutils.binstr(r'^(\d+|hello)'))
Beispiel #13
0
 def test_or_operator(self):
     data = UInt | "hello"
     res = data.build()
     val = gutils.val(res)
     self.assertRegexpMatches(val, gutils.binstr(r'^(\d+|hello)'))
Beispiel #14
0
 def test_and_explicit(self):
     data = And(UInt, ",", UInt)
     res = data.build()
     val = gutils.val(res)
     self.assertRegexpMatches(val, gutils.binstr(r'^\d+,\d+$'))
Beispiel #15
0
 def test_and_operator(self):
     data = UInt & "," & UInt
     res = data.build()
     val = gutils.val(res)
     self.assertRegexpMatches(val, gutils.binstr(r'^\d+,\d+$'))
Beispiel #16
0
 def test_ufloat(self):
     f = UFloat
     res = f().build()
     val = gutils.val(res)
     self.assertRegexpMatches(val, gutils.binstr(r'^\d+(\.\d+)?$'))
Beispiel #17
0
 def test_float(self):
     f = Float
     res = f().build()
     val = gutils.val(res)
     self.assertRegexpMatches(val, r'^(-)?\d+(\.\d+)?$')
Beispiel #18
0
 def test_int(self):
     i = Int
     res = i().build()
     val = gutils.val(res)
     self.assertRegexpMatches(val, r'^(-)?\d+$')