You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.1 KiB
105 lines
3.1 KiB
#
|
|
# Copyright (C) 2016 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
import random
|
|
|
|
REPLICATION_COUNT_IF_NEW_COVERAGE_IS_SEEN = 5
|
|
REPLICATION_PARAM_IF_NO_COVERAGE_IS_SEEN = 10
|
|
|
|
|
|
def CreateGenePool(count, generator, fuzzer, **kwargs):
|
|
"""Creates a gene pool, a set of test input data.
|
|
|
|
Args:
|
|
count: integer, the size of the pool.
|
|
generator: function pointer, which can generate the data.
|
|
fuzzer: function pointer, which can mutate the data.
|
|
**kwargs: the args to the generator function pointer.
|
|
|
|
Returns:
|
|
a list of generated data.
|
|
"""
|
|
genes = []
|
|
for index in range(count):
|
|
gene = generator(**kwargs)
|
|
genes.append(fuzzer(gene))
|
|
return genes
|
|
|
|
|
|
class Evolution(object):
|
|
"""Evolution class
|
|
|
|
Attributes:
|
|
_coverages_database: a list of coverage entities seen previously.
|
|
_alpha: replication count if new coverage is seen.
|
|
_beta: replication parameter if no coverage is seen.
|
|
"""
|
|
|
|
def __init__(self, alpha=REPLICATION_COUNT_IF_NEW_COVERAGE_IS_SEEN,
|
|
beta=REPLICATION_PARAM_IF_NO_COVERAGE_IS_SEEN):
|
|
self._coverages_database = []
|
|
self._alpha = alpha
|
|
self._beta = beta
|
|
|
|
def _IsNewCoverage(self, coverage, add=False):
|
|
"""Returns True iff the 'coverage' is new.
|
|
|
|
Args:
|
|
coverage: int, a coverage entity
|
|
add: boolean, true to add coverage to the db if it's new.
|
|
|
|
Returns:
|
|
True if new, False otherwise
|
|
"""
|
|
is_new_coverage = False
|
|
new_coverage_entities_to_add = []
|
|
for entity in coverage:
|
|
if entity not in self._coverages_database:
|
|
is_new_coverage = True
|
|
if add:
|
|
new_coverage_entities_to_add.append(entity)
|
|
else:
|
|
return True
|
|
if add:
|
|
self._coverages_database.extend(new_coverage_entities_to_add)
|
|
return is_new_coverage
|
|
|
|
def Evolve(self, genes, fuzzer, coverages=None):
|
|
"""Evolves a gene pool.
|
|
|
|
Args:
|
|
genes: a list of input data.
|
|
fuzzer: function pointer, which can mutate the data.
|
|
coverages: a list of the coverage data where coverage data is a list which
|
|
contains IDs of the covered entities (e.g., basic blocks).
|
|
|
|
Returns:
|
|
a list of evolved data.
|
|
"""
|
|
new_genes = []
|
|
if not coverages:
|
|
for gene in genes:
|
|
# TODO: consider cross over
|
|
new_genes.append(fuzzer(gene))
|
|
else:
|
|
for gene, coverage in zip(genes, coverages):
|
|
if self._IsNewCoverage(coverage, add=True):
|
|
for _ in range(self._alpha):
|
|
new_genes.append(fuzzer(gene))
|
|
elif random.randint(0, self._beta) == 1:
|
|
new_genes.append(fuzzer(gene))
|
|
return new_genes
|