Compare commits
4 commits
15449c8899
...
0d96551e82
Author | SHA1 | Date | |
---|---|---|---|
aCompetentBean | 0d96551e82 | ||
Ayrton | 1c91f6ac86 | ||
ayrton | ddc3875f56 | ||
ayrton | 1aef59672f |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
fuzzer/
|
fuzzer/
|
||||||
|
exec/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import string
|
import string
|
||||||
|
import warnings
|
||||||
|
|
||||||
from english_words import get_english_words_set
|
from english_words import get_english_words_set
|
||||||
|
|
||||||
|
@ -84,8 +85,8 @@ class AstGenerator:
|
||||||
|
|
||||||
def _init_names(self):
|
def _init_names(self):
|
||||||
names = get_english_words_set(['web2'], alpha=True)
|
names = get_english_words_set(['web2'], alpha=True)
|
||||||
possible_names = filter(lambda x: self.settings['properties']['id-length']['max'] <= len(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),
|
self.settings['properties']['id-length']['max']) and not keyword.iskeyword(x),
|
||||||
names)
|
names)
|
||||||
var_name_list = list(possible_names)
|
var_name_list = list(possible_names)
|
||||||
var_name_len = len(var_name_list)
|
var_name_len = len(var_name_list)
|
||||||
|
@ -155,6 +156,8 @@ class AstGenerator:
|
||||||
self.generate_return(return_type=return_type, return_value=return_value)
|
self.generate_return(return_type=return_type, return_value=return_value)
|
||||||
if self.settings['generation-options']['generate-dead-code']:
|
if self.settings['generation-options']['generate-dead-code']:
|
||||||
self.generate_statements(exclude='declaration')
|
self.generate_statements(exclude='declaration')
|
||||||
|
|
||||||
|
self.print_all_current_scope_vars()
|
||||||
self.pop_scope()
|
self.pop_scope()
|
||||||
self.current_ast_element = parent
|
self.current_ast_element = parent
|
||||||
|
|
||||||
|
@ -642,7 +645,7 @@ class AstGenerator:
|
||||||
self.comp_op_numline,
|
self.comp_op_numline,
|
||||||
self.comp_op_cutoffs,
|
self.comp_op_cutoffs,
|
||||||
self.comp_op_options,
|
self.comp_op_options,
|
||||||
comparison=True)
|
comparison=True) #, evals=self.get_truth())
|
||||||
|
|
||||||
def push_scope(self, xml_element: ET.Element = None):
|
def push_scope(self, xml_element: ET.Element = None):
|
||||||
scope = Scope(self.current_scope)
|
scope = Scope(self.current_scope)
|
||||||
|
@ -898,3 +901,25 @@ class AstGenerator:
|
||||||
self.generate_binary(op, random.choice([GAZ_INT_KEY, GAZ_FLOAT_KEY]))
|
self.generate_binary(op, random.choice([GAZ_INT_KEY, GAZ_FLOAT_KEY]))
|
||||||
else:
|
else:
|
||||||
self.generate_binary(op, random.choice(expr_type))
|
self.generate_binary(op, random.choice(expr_type))
|
||||||
|
|
||||||
|
def print_all_current_scope_vars(self):
|
||||||
|
for key, value in self.current_scope.symbols.items():
|
||||||
|
if isinstance(value, Variable):
|
||||||
|
self.print_variable(value)
|
||||||
|
|
||||||
|
def print_variable(self, var: Variable):
|
||||||
|
"""
|
||||||
|
@brief generate an outstream for a variable
|
||||||
|
|
||||||
|
@param var: the variable to print
|
||||||
|
@return:
|
||||||
|
"""
|
||||||
|
parent = self.current_ast_element
|
||||||
|
|
||||||
|
args = [
|
||||||
|
("type", GAZ_OUT_STREAM),
|
||||||
|
]
|
||||||
|
self.make_element(GAZ_STREAM_TAG, args)
|
||||||
|
self.current_ast_element.append(var.xml)
|
||||||
|
|
||||||
|
self.current_ast_element = parent
|
||||||
|
|
|
@ -9,7 +9,7 @@ generation-options:
|
||||||
max-globals: 5 # maximum number of global variables
|
max-globals: 5 # maximum number of global variables
|
||||||
properties:
|
properties:
|
||||||
max-range-length: 5 # maximum length of ranges, vectors and tuples, (AxA matrices can exist)
|
max-range-length: 5 # maximum length of ranges, vectors and tuples, (AxA matrices can exist)
|
||||||
use-english-words: True # use english words instead of random names (this may limit the maximum number of names)
|
use-english-words: True # use english words instead of random names (if we run out, we switch to random)
|
||||||
id-length: # length of identifiers
|
id-length: # length of identifiers
|
||||||
min: 1
|
min: 1
|
||||||
max: 5
|
max: 5
|
||||||
|
@ -68,12 +68,12 @@ statement-weights: # set to 0 for any statements y
|
||||||
in-stream: 5
|
in-stream: 5
|
||||||
|
|
||||||
type-weights:
|
type-weights:
|
||||||
value-types:
|
atomic-types:
|
||||||
integer: 50
|
int: 50 # TODO change these to the gaz types
|
||||||
real: 50
|
float: 50
|
||||||
boolean: 50
|
bool: 50
|
||||||
character: 50
|
char: 50
|
||||||
void: 10
|
void: 0 # TODO add support for void
|
||||||
composite-types:
|
composite-types:
|
||||||
vector: 20
|
vector: 20
|
||||||
tuple: 5
|
tuple: 5
|
||||||
|
@ -90,6 +90,9 @@ misc-weights:
|
||||||
type-qualifier-weights:
|
type-qualifier-weights:
|
||||||
const: 10
|
const: 10
|
||||||
var: 60
|
var: 60
|
||||||
|
conditional-eval:
|
||||||
|
true: 50
|
||||||
|
false: 50
|
||||||
|
|
||||||
block-termination-probability: 0.2 # probability for a block to terminate
|
block-termination-probability: 0.2 # probability for a block to terminate
|
||||||
|
|
||||||
|
|
|
@ -309,6 +309,22 @@ class TestGeneration(unittest.TestCase):
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def test_print_all_current_scope_vars(self):
|
||||||
|
self.ast_gen.ast = ET.Element("block")
|
||||||
|
self.ast_gen.current_ast_element = self.ast_gen.ast
|
||||||
|
self.ast_gen.generate_declaration(mut='var')
|
||||||
|
self.ast_gen.generate_declaration(mut='var')
|
||||||
|
self.ast_gen.generate_declaration(mut='var')
|
||||||
|
self.ast_gen.generate_declaration(mut='var')
|
||||||
|
|
||||||
|
self.ast_gen.print_all_current_scope_vars()
|
||||||
|
|
||||||
|
print(ET.tostring(self.ast_gen.ast))
|
||||||
|
|
||||||
|
streams = self.ast_gen.ast.findall("stream")
|
||||||
|
|
||||||
|
self.assertEqual(4, len(streams))
|
||||||
|
|
||||||
def write_ast(self):
|
def write_ast(self):
|
||||||
dom = xml.dom.minidom.parseString(ET.tostring(self.ast_gen.ast).decode('utf-8'))
|
dom = xml.dom.minidom.parseString(ET.tostring(self.ast_gen.ast).decode('utf-8'))
|
||||||
pretty: str = dom.toprettyxml()
|
pretty: str = dom.toprettyxml()
|
||||||
|
|
|
@ -98,3 +98,6 @@ class GazUnparser(GeneralUnparser):
|
||||||
|
|
||||||
def format_single_arg(self, ty, name):
|
def format_single_arg(self, ty, name):
|
||||||
return "{} {}".format(ty, name)
|
return "{} {}".format(ty, name)
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
pass
|
||||||
|
|
|
@ -69,6 +69,9 @@ class GeneralUnparser:
|
||||||
:return: a string of valid gazprea code
|
:return: a string of valid gazprea code
|
||||||
"""
|
"""
|
||||||
self.source = ""
|
self.source = ""
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
|
||||||
for node in self.xml:
|
for node in self.xml:
|
||||||
self.unparse_node(node)
|
self.unparse_node(node)
|
||||||
|
|
||||||
|
@ -324,6 +327,9 @@ class GeneralUnparser:
|
||||||
def format_single_arg(self, param, param1):
|
def format_single_arg(self, param, param1):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def pretty_xml(self):
|
def pretty_xml(self):
|
||||||
dom = xml.dom.minidom.parseString(ET.tostring(self.xml).decode('utf-8'))
|
dom = xml.dom.minidom.parseString(ET.tostring(self.xml).decode('utf-8'))
|
||||||
pretty: str = dom.toprettyxml()
|
pretty: str = dom.toprettyxml()
|
||||||
|
|
|
@ -59,7 +59,7 @@ class PythonUnparser(GeneralUnparser):
|
||||||
def __init__(self, ast: ET.Element, debug=False):
|
def __init__(self, ast: ET.Element, debug=False):
|
||||||
super().__init__(ast, debug,
|
super().__init__(ast, debug,
|
||||||
endline='\n',
|
endline='\n',
|
||||||
outstream_begin_delimiter="print(",
|
outstream_begin_delimiter="gprint(",
|
||||||
outstream_end_delimiter=", end='')",
|
outstream_end_delimiter=", end='')",
|
||||||
function_return_type_indicator_predicate="->",
|
function_return_type_indicator_predicate="->",
|
||||||
loop_start_delimiter="while ",
|
loop_start_delimiter="while ",
|
||||||
|
@ -113,3 +113,13 @@ class PythonUnparser(GeneralUnparser):
|
||||||
def unparse(self):
|
def unparse(self):
|
||||||
super().unparse()
|
super().unparse()
|
||||||
self.source += "\nif __name__ == '__main__':\n main()"
|
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")
|
||||||
|
|
|
@ -90,6 +90,9 @@ misc-weights:
|
||||||
type-qualifier-weights:
|
type-qualifier-weights:
|
||||||
const: 10
|
const: 10
|
||||||
var: 60
|
var: 60
|
||||||
|
conditional-eval:
|
||||||
|
true: 50
|
||||||
|
false: 50
|
||||||
|
|
||||||
block-termination-probability: 0.2 # probability for a block to terminate
|
block-termination-probability: 0.2 # probability for a block to terminate
|
||||||
|
|
||||||
|
|
|
@ -61,3 +61,11 @@ class NoneTagException(Exception):
|
||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
self.xml = xml
|
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
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,11 @@ class GazpreaFuzzer:
|
||||||
self.ground_truth = None
|
self.ground_truth = None
|
||||||
self.out = None
|
self.out = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs('debug/ast')
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
|
||||||
def fuzz(self):
|
def fuzz(self):
|
||||||
self.generator.generate_ast()
|
self.generator.generate_ast()
|
||||||
self.write_ast() # FIXME sometimes this is none
|
self.write_ast() # FIXME sometimes this is none
|
||||||
|
@ -48,8 +53,9 @@ class GazpreaFuzzer:
|
||||||
# input = "if __name__ == '__main__':\n while True:\n pass\n" # debug
|
# input = "if __name__ == '__main__':\n while True:\n pass\n" # debug
|
||||||
|
|
||||||
with redirect_stdout(io.StringIO()) as buf:
|
with redirect_stdout(io.StringIO()) as buf:
|
||||||
|
pass
|
||||||
# exec(str(self.ground_truth))
|
# 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()
|
self.out = buf.getvalue()
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,16 @@ import xml.etree.ElementTree as ET
|
||||||
from constants import NoneTagException
|
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():
|
class Fuzzer():
|
||||||
def __init__(self, config: str, batch: int, seed: str, file_name: str = "fuzz"):
|
def __init__(self, config: str, batch: int, seed: str, file_name: str = "fuzz"):
|
||||||
with open(config) as yaml_file:
|
with open(config) as yaml_file:
|
||||||
|
@ -27,16 +37,32 @@ class Fuzzer():
|
||||||
self.fuzzer = fz.GazpreaFuzzer(config)
|
self.fuzzer = fz.GazpreaFuzzer(config)
|
||||||
|
|
||||||
def fuzz(self):
|
def fuzz(self):
|
||||||
os.system("rm -rf fuzzer")
|
base_dir = os.getcwd()
|
||||||
os.mkdir("fuzzer")
|
fuzzer_root = base_dir + '/fuzzer'
|
||||||
os.mkdir("fuzzer/input")
|
|
||||||
os.mkdir("fuzzer/debug")
|
fuzzer_input = fuzzer_root + '/input/fuzzer'
|
||||||
os.mkdir("fuzzer/debug/ast_err")
|
fuzzer_debug = fuzzer_root + '/debug'
|
||||||
os.mkdir("fuzzer/instream")
|
fuzzer_asterr = fuzzer_debug + '/ast_err'
|
||||||
os.mkdir("fuzzer/outputs")
|
fuzzer_instream = fuzzer_root + '/instream'
|
||||||
os.mkdir("fuzzer/ground_truth")
|
fuzzer_outputs = fuzzer_root + '/outputs/fuzzer'
|
||||||
os.system("cp tester_config.json fuzzer/tester_config.json")
|
fuzzer_ground_truth = fuzzer_root + '/ground_truth'
|
||||||
for i in range(self.batch):
|
|
||||||
|
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
|
||||||
|
min_i = 0
|
||||||
|
while i < self.batch:
|
||||||
try:
|
try:
|
||||||
self.fuzzer.fuzz()
|
self.fuzzer.fuzz()
|
||||||
except NoneTagException as n:
|
except NoneTagException as n:
|
||||||
|
@ -44,38 +70,52 @@ class Fuzzer():
|
||||||
warnings.warn("None Tag Exception encountered, writing stack trace and xml to debug/ast/{}.xml\n"
|
warnings.warn("None Tag Exception encountered, writing stack trace and xml to debug/ast/{}.xml\n"
|
||||||
"Look for a top-level <argument> tag or send it to Ayrton and I'll see what I can see"
|
"Look for a top-level <argument> tag or send it to Ayrton and I'll see what I can see"
|
||||||
"".format(r))
|
"".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())
|
f.write(xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8')).toprettyxml())
|
||||||
|
if i - 1 >= min_i:
|
||||||
|
i -= 1
|
||||||
|
else:
|
||||||
|
i = min_i
|
||||||
continue
|
continue
|
||||||
dom = xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8'))
|
dom = xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8'))
|
||||||
pretty: str = dom.toprettyxml()
|
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)
|
f.write(self.fuzzer.ground_truth)
|
||||||
with open("fuzzer/ground_truth/{}_{}.py".format(self.file_name, i), 'r') as f:
|
with open("{}/{}_{}.py".format(fuzzer_ground_truth, self.file_name, i), 'r') as f:
|
||||||
with open("fuzzer/outputs/{}_{}.out".format(self.file_name, i), 'w') as y:
|
with open("{}/{}_{}.out".format(fuzzer_outputs, self.file_name, i), 'w') as y:
|
||||||
with redirect_stdout(y): # Workaround for fuzzer.py:49
|
with redirect_stdout(y): # Workaround for fuzzer.py:49
|
||||||
try:
|
try:
|
||||||
exec(f.read(), globals(), locals())
|
read = f.read()
|
||||||
except (OverflowError, ZeroDivisionError, ValueError):
|
exec(read, globals())
|
||||||
os.system("rm -f fuzzer/ground_truth/{}_{}.py".format(self.file_name, i))
|
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")
|
||||||
|
if i - 1 >= min_i:
|
||||||
|
i -= 1
|
||||||
|
else:
|
||||||
|
i = min_i
|
||||||
continue
|
continue
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
r = random.randint(0, 1000000)
|
r = random.randint(0, 1000000)
|
||||||
warnings.warn("Execution halted, result written to debug/ast/{}.xml\n"
|
warnings.warn("Execution halted, result written to debug/ast/{}.xml\n"
|
||||||
"".format(r))
|
"".format(r))
|
||||||
with open("fuzzer/debug/ast_err/{}.xml".format(r), 'w') as f:
|
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())
|
f.write(xml.dom.minidom.parseString(
|
||||||
|
ET.tostring(self.fuzzer.ast).decode('utf-8')).toprettyxml())
|
||||||
sys.exit(1)
|
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)
|
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)
|
f.write(pretty)
|
||||||
# y.write(self.fuzzer.out)
|
# y.write(self.fuzzer.out)
|
||||||
# with open("fuzzer/instream/{}.in".format(i), 'w') as f:
|
# with open("fuzzer/instream/{}.in".format(i), 'w') as f:
|
||||||
# f.write(self.fuzzer.source)
|
# f.write(self.fuzzer.source)
|
||||||
# with open("fuzzer/outputs/{}.out".format(i), 'w') as f:
|
# with open("fuzzer/outputs/{}.out".format(i), 'w') as f:
|
||||||
# f.write(self.fuzzer.out)
|
# f.write(self.fuzzer.out)
|
||||||
|
i += 1
|
||||||
|
min_i = i
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -94,5 +134,3 @@ if __name__ == '__main__':
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
fuzzer = Fuzzer(config=args.config_file, batch=args.batch_size, seed=args.seed)
|
fuzzer = Fuzzer(config=args.config_file, batch=args.batch_size, seed=args.seed)
|
||||||
fuzzer.fuzz()
|
fuzzer.fuzz()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"inDir": "<inDir>",
|
"inDir": "input",
|
||||||
"outDir": "<outDir>",
|
"outDir": "outputs",
|
||||||
"inStrDir": "<inStrDir>",
|
"inStrDir": "instream",
|
||||||
"testedExecutablePaths": {
|
"testedExecutablePaths": {
|
||||||
"<team id>": "<path_to_gazc_exe>"
|
"fuzzer": "../exec/gazc"
|
||||||
},
|
},
|
||||||
"runtimes": {
|
"runtimes": {
|
||||||
"<team id>": "<path_to_libgazrt.so>"
|
"fuzzer": "../exec/libgazrt.so"
|
||||||
},
|
},
|
||||||
"toolchains": {
|
"toolchains": {
|
||||||
"gazprea": [
|
"gazprea": [
|
||||||
|
|
Loading…
Reference in a new issue