diff --git a/ast_generator/ast_generator.py b/ast_generator/ast_generator.py index 0fc6cb5..3106c3c 100644 --- a/ast_generator/ast_generator.py +++ b/ast_generator/ast_generator.py @@ -1,4 +1,5 @@ import string +import warnings from english_words import get_english_words_set @@ -84,8 +85,8 @@ class AstGenerator: def _init_names(self): names = get_english_words_set(['web2'], alpha=True) - possible_names = filter(lambda x: self.settings['properties']['id-length']['max'] <= len(x) <= - self.settings['properties']['id-length']['max'] and not keyword.iskeyword(x), + possible_names = filter(lambda x: (self.settings['properties']['id-length']['max'] <= len(x) <= + self.settings['properties']['id-length']['max']) and not keyword.iskeyword(x), names) var_name_list = list(possible_names) var_name_len = len(var_name_list) diff --git a/ast_parser/gaz_unparser.py b/ast_parser/gaz_unparser.py index f525ec5..d46de32 100644 --- a/ast_parser/gaz_unparser.py +++ b/ast_parser/gaz_unparser.py @@ -98,3 +98,6 @@ class GazUnparser(GeneralUnparser): def format_single_arg(self, ty, name): return "{} {}".format(ty, name) + + def setup(self): + pass diff --git a/ast_parser/general_unparser.py b/ast_parser/general_unparser.py index 5c38ff0..7855163 100644 --- a/ast_parser/general_unparser.py +++ b/ast_parser/general_unparser.py @@ -69,6 +69,9 @@ class GeneralUnparser: :return: a string of valid gazprea code """ self.source = "" + + self.setup() + for node in self.xml: self.unparse_node(node) @@ -324,6 +327,9 @@ class GeneralUnparser: def format_single_arg(self, param, param1): raise NotImplementedError + def setup(self): + raise NotImplementedError + def pretty_xml(self): dom = xml.dom.minidom.parseString(ET.tostring(self.xml).decode('utf-8')) pretty: str = dom.toprettyxml() diff --git a/ast_parser/python_unparser.py b/ast_parser/python_unparser.py index 89dff3e..1434505 100644 --- a/ast_parser/python_unparser.py +++ b/ast_parser/python_unparser.py @@ -59,7 +59,7 @@ class PythonUnparser(GeneralUnparser): def __init__(self, ast: ET.Element, debug=False): super().__init__(ast, debug, endline='\n', - outstream_begin_delimiter="print(", + outstream_begin_delimiter="gprint(", outstream_end_delimiter=", end='')", function_return_type_indicator_predicate="->", loop_start_delimiter="while ", @@ -113,3 +113,13 @@ class PythonUnparser(GeneralUnparser): def unparse(self): super().unparse() self.source += "\nif __name__ == '__main__':\n main()" + + def setup(self): + self.source += ("def gprint(expr, end=''):\n" + " if type(expr) is bool:\n" + " if expr:\n" + " print('T', end=end)\n" + " else:\n" + " print('F', end=end)\n" + " else:\n" + " print(expr, end=end)\n\n") diff --git a/config.yaml b/config.yaml index f51ce79..5ad7b7a 100644 --- a/config.yaml +++ b/config.yaml @@ -90,6 +90,9 @@ misc-weights: type-qualifier-weights: const: 10 var: 60 + conditional-eval: + true: 50 + false: 50 block-termination-probability: 0.2 # probability for a block to terminate diff --git a/constants.py b/constants.py index 5c969d5..20b6250 100644 --- a/constants.py +++ b/constants.py @@ -61,3 +61,11 @@ class NoneTagException(Exception): super().__init__(message) self.xml = xml +class GazTypeError(Exception): + + def __init__(self, message, op, ty1, ty2): + super().__init__(message) + self.op = op + self.ty1 = ty1 + self.ty2 = ty2 + diff --git a/fuzzer.py b/fuzzer.py index e12f939..1e89255 100644 --- a/fuzzer.py +++ b/fuzzer.py @@ -48,8 +48,9 @@ class GazpreaFuzzer: # input = "if __name__ == '__main__':\n while True:\n pass\n" # debug with redirect_stdout(io.StringIO()) as buf: + pass # exec(str(self.ground_truth)) - exec(self.ground_truth, globals(), locals()) # FIXME the exec doesn't actually execute for some reason... + # exec(self.ground_truth, globals(), locals()) # FIXME the exec doesn't actually execute for some reason... self.out = buf.getvalue() diff --git a/gazprea_fuzzer.py b/gazprea_fuzzer.py index 9e26176..1ad7d78 100644 --- a/gazprea_fuzzer.py +++ b/gazprea_fuzzer.py @@ -15,6 +15,16 @@ import xml.etree.ElementTree as ET from constants import NoneTagException +def gprint(expr, end=''): + if type(expr) is bool: + if expr: + print('T', end=end) + else: + print('F', end=end) + else: + print(expr, end=end) + + class Fuzzer(): def __init__(self, config: str, batch: int, seed: str, file_name: str = "fuzz"): with open(config) as yaml_file: @@ -27,16 +37,31 @@ class Fuzzer(): self.fuzzer = fz.GazpreaFuzzer(config) def fuzz(self): - os.system("rm -rf fuzzer") - os.mkdir("fuzzer") - os.mkdir("fuzzer/input") - os.mkdir("fuzzer/debug") - os.mkdir("fuzzer/debug/ast_err") - os.mkdir("fuzzer/instream") - os.mkdir("fuzzer/outputs") - os.mkdir("fuzzer/ground_truth") - os.system("cp tester_config.json fuzzer/tester_config.json") - for i in range(self.batch): + base_dir = os.getcwd() + fuzzer_root = base_dir + '/fuzzer' + + fuzzer_input = fuzzer_root + '/input/fuzzer' + fuzzer_debug = fuzzer_root + '/debug' + fuzzer_asterr = fuzzer_debug + '/ast_err' + fuzzer_instream = fuzzer_root + '/instream' + fuzzer_outputs = fuzzer_root + '/outputs/fuzzer' + fuzzer_ground_truth = fuzzer_root + '/ground_truth' + + os.system(f"rm -rf {fuzzer_root}") + os.makedirs(fuzzer_root) + os.makedirs(fuzzer_input) + os.makedirs(fuzzer_debug) + os.makedirs(fuzzer_asterr) + os.makedirs(fuzzer_instream) + os.makedirs(fuzzer_outputs) + os.makedirs(fuzzer_ground_truth) + try: + os.system(f"cp tester_config.json {fuzzer_root}/tester_config.json") + except Exception as e: + pass + + i = 0 + while i < self.batch: try: self.fuzzer.fuzz() except NoneTagException as n: @@ -44,38 +69,46 @@ class Fuzzer(): warnings.warn("None Tag Exception encountered, writing stack trace and xml to debug/ast/{}.xml\n" "Look for a top-level tag or send it to Ayrton and I'll see what I can see" "".format(r)) - with open("fuzzer/debug/ast_err/{}.xml".format(r), 'w') as f: + with open(f"{fuzzer_asterr}/{r}.xml", 'w') as f: f.write(xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8')).toprettyxml()) + + i -= 1 continue dom = xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8')) pretty: str = dom.toprettyxml() - with open("fuzzer/ground_truth/{}_{}.py".format(self.file_name, i), 'w') as f: + with open("{}/{}_{}.py".format(fuzzer_ground_truth, self.file_name, i), 'w') as f: f.write(self.fuzzer.ground_truth) - with open("fuzzer/ground_truth/{}_{}.py".format(self.file_name, i), 'r') as f: - with open("fuzzer/outputs/{}_{}.out".format(self.file_name, i), 'w') as y: - with redirect_stdout(y): # Workaround for fuzzer.py:49 + with open("{}/{}_{}.py".format(fuzzer_ground_truth, self.file_name, i), 'r') as f: + with open("{}/{}_{}.out".format(fuzzer_outputs, self.file_name, i), 'w') as y: + with redirect_stdout(y): # Workaround for fuzzer.py:49 try: - exec(f.read(), globals(), locals()) - except (OverflowError, ZeroDivisionError, ValueError): - os.system("rm -f fuzzer/ground_truth/{}_{}.py".format(self.file_name, i)) + read = f.read() + exec(read, globals()) + except (OverflowError, ZeroDivisionError, ValueError, TypeError, SyntaxError): + os.system("rm -f {}/{}_{}.py".format(fuzzer_ground_truth, self.file_name, i)) + os.system("rm -f {}/{}_{}.py".format(fuzzer_outputs, self.file_name, i)) + warnings.warn("Runtime error encountered, retrying") + i -= 1 continue except KeyboardInterrupt: r = random.randint(0, 1000000) warnings.warn("Execution halted, result written to debug/ast/{}.xml\n" "".format(r)) - with open("fuzzer/debug/ast_err/{}.xml".format(r), 'w') as f: - f.write(xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8')).toprettyxml()) + with open("{}/{}.xml".format(fuzzer_asterr, r), 'w') as f: + f.write(xml.dom.minidom.parseString( + ET.tostring(self.fuzzer.ast).decode('utf-8')).toprettyxml()) sys.exit(1) - with open("fuzzer/input/{}_{}.in".format(self.file_name, i), 'w') as f: + with open("{}/{}_{}.in".format(fuzzer_input, self.file_name, i), 'w') as f: f.write(self.fuzzer.source) - with open("fuzzer/debug/{}_{}.xml".format(self.file_name, i), 'w') as f: + with open("{}/{}_{}.xml".format(fuzzer_debug, self.file_name, i), 'w') as f: f.write(pretty) - # y.write(self.fuzzer.out) + # y.write(self.fuzzer.out) # with open("fuzzer/instream/{}.in".format(i), 'w') as f: # f.write(self.fuzzer.source) # with open("fuzzer/outputs/{}.out".format(i), 'w') as f: # f.write(self.fuzzer.out) + i += 1 if __name__ == '__main__': @@ -94,5 +127,3 @@ if __name__ == '__main__': args = parser.parse_args() fuzzer = Fuzzer(config=args.config_file, batch=args.batch_size, seed=args.seed) fuzzer.fuzz() - - diff --git a/tester_config.json b/tester_config.json index 602d1ff..d88b48a 100644 --- a/tester_config.json +++ b/tester_config.json @@ -1,12 +1,12 @@ { - "inDir": "", - "outDir": "", - "inStrDir": "", + "inDir": "input", + "outDir": "outputs", + "inStrDir": "instream", "testedExecutablePaths": { - "": "" + "fuzzer": "../exec/gazc" }, "runtimes": { - "": "" + "fuzzer": "../exec/libgazrt.so" }, "toolchains": { "gazprea": [