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)
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)
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)
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))
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
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)
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
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 ))
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()
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)
def test_uint(self): i = UInt res = i().build() val = gutils.val(res) self.assertRegexpMatches(val, gutils.binstr(r'^\d+$'))
def test_or_explicit(self): data = Or(UInt, "hello") res = data.build() val = gutils.val(res) self.assertRegexpMatches(val, gutils.binstr(r'^(\d+|hello)'))
def test_or_operator(self): data = UInt | "hello" res = data.build() val = gutils.val(res) self.assertRegexpMatches(val, gutils.binstr(r'^(\d+|hello)'))
def test_and_explicit(self): data = And(UInt, ",", UInt) res = data.build() val = gutils.val(res) self.assertRegexpMatches(val, gutils.binstr(r'^\d+,\d+$'))
def test_and_operator(self): data = UInt & "," & UInt res = data.build() val = gutils.val(res) self.assertRegexpMatches(val, gutils.binstr(r'^\d+,\d+$'))
def test_ufloat(self): f = UFloat res = f().build() val = gutils.val(res) self.assertRegexpMatches(val, gutils.binstr(r'^\d+(\.\d+)?$'))
def test_float(self): f = Float res = f().build() val = gutils.val(res) self.assertRegexpMatches(val, r'^(-)?\d+(\.\d+)?$')
def test_int(self): i = Int res = i().build() val = gutils.val(res) self.assertRegexpMatches(val, r'^(-)?\d+$')