def setupTypes(ast, entryFunc, inputs, nondets, entry, typedefs): for fun in ast.ext: if isinstance(fun, c_ast.Decl) and isinstance(fun.type, c_ast.FuncDecl): if fun.name.startswith('__VERIFIER_nondet_'): info = {} info['type'] = ext_c_generator.GnuCGenerator().visit(fun.type) info['line'] = fun.coord.line nondets[fun.name] = info if isinstance(fun, c_ast.Decl) and isinstance( fun.type, ext_c_parser.FuncDeclExt): if fun.name.startswith('__VERIFIER_nondet_'): info = {} info['type'] = ext_c_generator.GnuCGenerator().visit(fun) info['type'] = re.sub(r'^extern ', '', info['type']) info['line'] = fun.coord.line nondets[fun.name] = info elif isinstance(fun, c_ast.FuncDef): inputs[fun.decl.name] = {} if fun.body.block_items: for d in fun.body.block_items: if isinstance(d, c_ast.Decl): info = {} typestr = ext_c_generator.GnuCGenerator().visit(d) typestr = re.sub(r'\b%s\b' % d.name, '', typestr) if typedefs.get(typestr): typestr = typedefs[typestr] info['type'] = typestr info['line'] = d.coord.line if d.init is None: inputs[fun.decl.name][d.name] = info if fun.decl.name == entryFunc: entry['type'] = ext_c_generator.GnuCGenerator().visit( fun.decl.type) entry['line'] = fun.coord.line elif isinstance(fun, c_ast.Typedef): name = fun.name if isinstance(fun.type, ext_c_parser.FuncDeclExt): typestr = ext_c_generator.GnuCGenerator().visit( fun.type.type) + ('()' + '(' + ext_c_generator.GnuCGenerator().visit( fun.type.args) + ')') name = fun.name + ' (*)' elif isinstance(fun.type, c_ast.PtrDecl) and isinstance( fun.type.type, ext_c_parser.FuncDeclExt): typestr = ext_c_generator.GnuCGenerator().visit( fun.type.type.type) + ( '(*)' + '(' + ext_c_generator.GnuCGenerator().visit( fun.type.type.args) + ')') else: typestr = ext_c_generator.GnuCGenerator().visit(fun.type) while typedefs.get(typestr): typestr = typedefs.get(typestr) typedefs[name] = typestr
def preprocess(path): text = preprocess_file(path) cparser = GnuCParser() ast = cparser.parse(text, path) generator = ext_c_generator.GnuCGenerator() with open(path, "w") as o: o.write(generator.visit(ast)) return ast
def start_prediction(id, pred_dir, req_file): P, ast = run_clf_predict(pred_dir, req_file) F = to_func(ast) generator = ext_c_generator.GnuCGenerator() for name, ast in F.items(): path = os.path.join(pred_dir, name+".c") with open(path, "w") as o: out = generator.visit(ast) o.write(out)
def test_double_pointer(): src = """ typedef struct Error { int dummy; } Error; void func_with_p2pp(const char *, Error **); """ import pycparserext.ext_c_parser as ext_c_parser import pycparserext.ext_c_generator as ext_c_generator parser = ext_c_parser.GnuCParser() ast = parser.parse(src) gen = ext_c_generator.GnuCGenerator() ast.show() assert gen.visit(ast).find("func_with_p2pp(const char *, Error **)") != -1
def test_no_added_attr(): src = """ char* foo() { return ""; } int main() { return 0; } """ import pycparserext.ext_c_parser as ext_c_parser import pycparserext.ext_c_generator as ext_c_generator parser = ext_c_parser.GnuCParser() ast = parser.parse(src) gen = ext_c_generator.GnuCGenerator() print(gen.visit(ast)) assert "attr" not in gen.visit(ast)
def test_pointer_reproduction(): src = """ struct foo { const char *bar; const char *baz; }; int main () { return 0; } """ import pycparserext.ext_c_parser as ext_c_parser import pycparserext.ext_c_generator as ext_c_generator parser = ext_c_parser.GnuCParser() ast = parser.parse(src) gen = ext_c_generator.GnuCGenerator() print(gen.visit(ast))
def processWitness(witness, benchmark, bitwidth): try: root = ElementTree.parse(witness).getroot() except: eprint("INVALID WITNESS FILE: failed to parse XML") sys.exit(1) # print(ElementTree.tostring(root)) ns = {'graphml': 'http://graphml.graphdrawing.org/xmlns'} graph = root.find('./graphml:graph', ns) if graph is None: eprint("INVALID WITNESS FILE: failed to parse XML - no graph node") sys.exit(1) entryFun = validateConfig(graph, ns, witness, benchmark, bitwidth) benchmarkString = '' with tempfile.NamedTemporaryFile() as fp: # preprocess and remove __attribute__ subprocess.check_call([ 'gcc', '-D__attribute__(x)=', '-x', 'c', '-E', benchmark, '-o', fp.name ]) with open(fp.name, 'r') as b: needStructBody = False skipAsm = False for line in b: # rewrite some GCC extensions """ line = re.sub(r'__extension__\s*\(\{\s*if\s*\(0\)\s*;\s*else\s+(__assert_fail\s*\("0",\s*".*",\s*\d+,\s*__extension__\s+__PRETTY_FUNCTION__\s*\));\s*\}\)', r'\1', line) """ line = re.sub(r'__extension__', '', line) """ line = re.sub(r'__restrict', 'restrict', line) line = re.sub(r'__inline__', 'inline', line) line = re.sub(r'__inline', 'inline', line) line = re.sub(r'__const', 'const', line) """ line = re.sub(r'__signed__', 'signed', line) """ line = re.sub(r'__builtin_va_list', 'int', line) """ # a hack for some C-standards violating code in LDV benchmarks if needStructBody and re.match(r'^\s*}\s*;\s*$', line): line = 'int __dummy; ' + line needStructBody = False elif needStructBody: needStructBody = re.match(r'^\s*$', line) is not None elif re.match(r'^\s*struct\s+[a-zA-Z0-9_]+\s*{\s*$', line): needStructBody = True # remove inline asm if re.match( r'^\s*__asm__(\s+volatile)?\s*\("([^"]|\\")*"[^;]*$', line): skipAsm = True elif skipAsm and re.search(r'\)\s*;\s*$', line): line = '\n' skipAsm = False line = '\n' if (skipAsm or re.match( r'^\s*__asm__(\s+volatile)?\s*\("([^"]|\\")*"[^;]*\)\s*;\s*$', line)): line = '\n' # remove asm renaming line = re.sub(r'__asm__\s*\(""\s+"[a-zA-Z0-9_]+"\)', '', line) benchmarkString += line parser = ext_c_parser.GnuCParser() ast = parser.parse(benchmarkString, filename=benchmark) # ast.show(showcoord=True, buf=sys.stderr) inputs = {} nondets = {} entry = {} typedefs = {} setupTypes(ast, entryFun, inputs, nondets, entry, typedefs) assert entry watch = {} setupWatch(ast, watch) trace = {} entryNode = buildTrace(graph, ns, trace) values = [] n = entryNode missing_nondets = set(nondets) while trace[n].get('target') is not None: if trace[n].get('assumption') is not None: # assumptions may use = or == a = re.sub(r'==', '=', trace[n]['assumption']) a = re.sub(r'\\result', '__SV_COMP_result', a) # we may be missing typedefs used in type casts a_copy = a if re.search(r'\(\s*[a-zA-Z_][a-zA-Z0-9_]*.*\)', a): # do two rounds - strictly speaking, we'd need a fixed point here for t in typedefs: if t.endswith(' (*)'): a = re.sub(r'%s' % re.escape(t), typedefs[t], a) else: a = re.sub(r'\b%s\b' % re.escape(t), typedefs[t], a) for t in typedefs: if t.endswith(' (*)'): a = re.sub(r'%s' % re.escape(t), typedefs[t], a) else: a = re.sub(r'\b%s\b' % re.escape(t), typedefs[t], a) wrapped = 'void foo() { ' + a + ';}' try: block_items = parser.parse(wrapped).ext[0].body.block_items except: eprint('Failed to parse ' + wrapped + '(expanded from ' + a_copy + ')') raise for a_ast in block_items: if isinstance(a_ast, c_ast.Assignment): f = trace[n].get('assumption.scope') v = ext_c_generator.GnuCGenerator().visit(a_ast.rvalue) if (trace[n].get('startline') is not None and watch.get( int(trace[n]['startline'])) is not None): w = watch[int(trace[n]['startline'])] values.append([w, v]) if w in missing_nondets: missing_nondets.remove(w) elif (f is not None and isinstance(a_ast.lvalue, c_ast.ID) and inputs.get(f) is not None and inputs[f].get(a_ast.lvalue.name) is not None): values.append([f, a_ast.lvalue.name, v]) # else: # print(trace[n]['startline']) # a_ast.show() # else: # print(trace[n]['startline']) # a_ast.show() n = trace[n]['target'] if watch and not values: eprint('inputs: ') eprint(inputs) eprint('nondets: ') eprint(nondets) eprint('watch: ') eprint(watch) eprint( "WARNING: no input values found in witness file, behaviour of harness may be undefined" ) print('IN:') print(' ENTRY {n}()@[file {f} line {l}]'.format(n=entryFun, f=benchmark, l=entry['line'])) for v in values: if len(v) == 3: info = inputs[v[0]][v[1]] print( ' {t} {n}@[file {f} line {l} function {fun}]={value}'.format( t=info['type'], n=v[1], f=benchmark, l=info['line'], fun=v[0], value=v[2])) else: info = nondets[v[0]] print(' {t}@[file {f} line {l}]={value}'.format(t=info['type'], f=benchmark, l=info['line'], value=v[1])) for n in missing_nondets: info = nondets[n] print(' {t}@[file {f} line {l}]=0'.format(t=info['type'], f=benchmark, l=info['line']))